| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.sqoop.manager.oracle; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.sql.Connection; |
| import java.sql.SQLException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.FSDataOutputStream; |
| import org.apache.hadoop.fs.FileSystem; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.log4j.Category; |
| import org.apache.log4j.Level; |
| import org.apache.log4j.Logger; |
| import org.apache.sqoop.manager.oracle.OraOopOutputFormatInsert.InsertMode; |
| import org.apache.sqoop.manager.oracle.OraOopOutputFormatUpdate.UpdateMode; |
| |
| import org.apache.sqoop.Sqoop; |
| import org.apache.sqoop.SqoopOptions; |
| import org.apache.sqoop.mapreduce.ExportJobBase; |
| |
| /** |
| * Utilities used by OraOop. |
| */ |
| public final class OraOopUtilities { |
| |
| private OraOopUtilities() { |
| } |
| |
| private static String currentSessionUser = null; |
| |
| /** |
| * Used for testing purposes - can get OraOop to call a class to run a report |
| * on various performance metrics. |
| */ |
| public static class OraOopStatsReports { |
| private String csvReport; |
| private String performanceReport; |
| |
| public String getPerformanceReport() { |
| return performanceReport; |
| } |
| |
| public void setPerformanceReport(String newPerformanceReport) { |
| this.performanceReport = newPerformanceReport; |
| } |
| |
| public String getCsvReport() { |
| return csvReport; |
| } |
| |
| public void setCsvReport(String newCsvReport) { |
| this.csvReport = newCsvReport; |
| } |
| } |
| |
| protected static final OraOopLog LOG = OraOopLogFactory |
| .getLog(OraOopUtilities.class.getName()); |
| |
| public static List<String> copyStringList(List<String> list) { |
| |
| List<String> result = new ArrayList<String>(list.size()); |
| result.addAll(list); |
| return result; |
| } |
| |
| public static OracleTable decodeOracleTableName( |
| String oracleConnectionUserName, String tableStr) { |
| |
| String tableOwner; |
| String tableName; |
| |
| // These are the possibilities for double-quote location... |
| // table |
| // "table" |
| // schema.table |
| // schema."table" |
| // "schema".table |
| // "schema"."table" |
| String[] tableStrings = tableStr.split("\""); |
| |
| if (oracleConnectionUserName == null) { |
| oracleConnectionUserName = currentSessionUser; |
| } |
| |
| switch (tableStrings.length) { |
| |
| case 1: // <- table or schema.table |
| |
| tableStrings = tableStr.split("\\."); |
| |
| switch (tableStrings.length) { |
| |
| case 1: // <- No period |
| tableOwner = oracleConnectionUserName.toUpperCase(); |
| tableName = tableStrings[0].toUpperCase(); |
| break; |
| case 2: // <- 1 period |
| tableOwner = tableStrings[0].toUpperCase(); |
| tableName = tableStrings[1].toUpperCase(); |
| break; |
| default: |
| LOG.debug(String.format( |
| "Unable to decode the table name (displayed in " |
| + "double quotes): \"%s\"", tableStr)); |
| throw new RuntimeException(String.format( |
| "Unable to decode the table name: %s", tableStr)); |
| } |
| break; |
| |
| case 2: // <- "table" or schema."table" |
| |
| if (tableStrings[0] == null || tableStrings[0].isEmpty()) { |
| tableOwner = oracleConnectionUserName.toUpperCase(); |
| } else { |
| tableOwner = tableStrings[0].toUpperCase(); |
| // Remove the "." from the end of the schema name... |
| if (tableOwner.endsWith(".")) { |
| tableOwner = tableOwner.substring(0, tableOwner.length() - 1); |
| } |
| } |
| |
| tableName = tableStrings[1]; |
| break; |
| |
| case 3: // <- "schema".table |
| |
| tableOwner = tableStrings[1]; |
| tableName = tableStrings[2].toUpperCase(); |
| // Remove the "." from the start of the table name... |
| if (tableName.startsWith(".")) { |
| tableName = tableName.substring(1, tableName.length()); |
| } |
| |
| break; |
| |
| case 4: // <- "schema"."table" |
| tableOwner = tableStrings[1]; |
| tableName = tableStrings[3]; |
| break; |
| |
| default: |
| LOG.debug(String.format( |
| "Unable to decode the table name (displayed in double " |
| + "quotes): \"%s\"", tableStr)); |
| throw new RuntimeException(String.format( |
| "Unable to decode the table name: %s", tableStr)); |
| |
| } |
| OracleTable result = new OracleTable(tableOwner, tableName); |
| return result; |
| } |
| |
| public static OracleTable decodeOracleTableName( |
| String oracleConnectionUserName, String tableStr, |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| OracleTable result = new OracleTable(); |
| |
| // Have we already determined the answer to this question?... |
| if (conf != null) { |
| String tableOwner = conf.get(OraOopConstants.ORAOOP_TABLE_OWNER); |
| String tableName = conf.get(OraOopConstants.ORAOOP_TABLE_NAME); |
| result = new OracleTable(tableOwner, tableName); |
| } |
| |
| // If we couldn't look up the answer, then determine it now... |
| if (result.getSchema() == null || result.getName() == null) { |
| |
| result = decodeOracleTableName(oracleConnectionUserName, tableStr); |
| |
| LOG.debug(String.format( |
| "The Oracle table context has been derived from:\n" |
| + "\toracleConnectionUserName = %s\n" + "\ttableStr = %s\n" |
| + "\tas:\n" + "\towner : %s\n" + "\ttable : %s", |
| oracleConnectionUserName, tableStr, result.getSchema(), result |
| .getName())); |
| |
| // Save the answer for next time... |
| if (conf != null) { |
| conf.set(OraOopConstants.ORAOOP_TABLE_OWNER, result.getSchema()); |
| conf.set(OraOopConstants.ORAOOP_TABLE_NAME, result.getName()); |
| } |
| } |
| |
| return result; |
| } |
| |
| public static boolean oracleJdbcUrlGenerationDisabled( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getBoolean(OraOopConstants.ORAOOP_JDBC_URL_VERBATIM, false); |
| } |
| |
| public static boolean userWantsOracleSessionStatisticsReports( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getBoolean(OraOopConstants.ORAOOP_REPORT_SESSION_STATISTICS, |
| false); |
| } |
| |
| public static boolean enableDebugLoggingIfRequired( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| boolean result = false; |
| |
| try { |
| |
| Level desiredOraOopLoggingLevel = |
| Level.toLevel(conf.get(OraOopConstants.ORAOOP_LOGGING_LEVEL), |
| Level.INFO); |
| |
| Level sqoopLogLevel = |
| Logger.getLogger(Sqoop.class.getName()).getParent().getLevel(); |
| |
| if (desiredOraOopLoggingLevel == Level.DEBUG |
| || desiredOraOopLoggingLevel == Level.ALL |
| || sqoopLogLevel == Level.DEBUG || sqoopLogLevel == Level.ALL) { |
| |
| Category oraOopLogger = |
| Logger.getLogger(OraOopManagerFactory.class.getName()).getParent(); |
| oraOopLogger.setLevel(Level.DEBUG); |
| LOG.debug("Enabled OraOop debug logging."); |
| result = true; |
| |
| conf.set(OraOopConstants.ORAOOP_LOGGING_LEVEL, Level.DEBUG.toString()); |
| } |
| } catch (Exception ex) { |
| LOG.error(String.format( |
| "Unable to determine whether debug logging should be enabled.\n%s", |
| getFullExceptionMessage(ex))); |
| } |
| |
| return result; |
| } |
| |
| public static String generateDataChunkId(int fileId, int fileBatch) { |
| StringBuilder sb = new StringBuilder(); |
| return sb.append(fileId).append("_").append(fileBatch).toString(); |
| } |
| |
| public static String getCurrentMethodName() { |
| |
| StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace(); |
| return String.format("%s()", stackTraceElements[1].getMethodName()); |
| } |
| |
| public static String[] getDuplicatedStringArrayValues(String[] list, |
| boolean ignoreCase) { |
| |
| if (list == null) { |
| throw new IllegalArgumentException("The list argument cannot be null"); |
| } |
| |
| ArrayList<String> duplicates = new ArrayList<String>(); |
| |
| for (int idx1 = 0; idx1 < list.length - 1; idx1++) { |
| for (int idx2 = idx1 + 1; idx2 < list.length; idx2++) { |
| if (list[idx1].equals(list[idx2])) { |
| // If c is a duplicate of both a & b, don't add c to the list twice... |
| if (!duplicates.contains(list[idx2])) { |
| duplicates.add(list[idx2]); |
| } |
| |
| } else if (ignoreCase && list[idx1].equalsIgnoreCase((list[idx2]))) { |
| // If c is a duplicate of both a & b, don't add c to the list twice... |
| if (stringListIndexOf(duplicates, list[idx2], ignoreCase) == -1) { |
| duplicates.add(list[idx2]); |
| } |
| } |
| } |
| } |
| |
| return duplicates.toArray(new String[duplicates.size()]); |
| } |
| |
| public static String getFullExceptionMessage(Exception ex) { |
| |
| ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); |
| PrintStream printStream = new PrintStream(arrayStream); |
| ex.printStackTrace(printStream); |
| return arrayStream.toString(); |
| } |
| |
| public static int getMinNumberOfImportMappersAcceptedByOraOop( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getInt(OraOopConstants.ORAOOP_MIN_IMPORT_MAPPERS, |
| OraOopConstants.MIN_NUM_IMPORT_MAPPERS_ACCEPTED_BY_ORAOOP); |
| } |
| |
| public static int getMinAppendValuesBatchSize( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getInt(OraOopConstants.ORAOOP_MIN_APPEND_VALUES_BATCH_SIZE, |
| OraOopConstants.ORAOOP_MIN_APPEND_VALUES_BATCH_SIZE_DEFAULT); |
| } |
| |
| public static int getMinNumberOfExportMappersAcceptedByOraOop( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getInt(OraOopConstants.ORAOOP_MIN_EXPORT_MAPPERS, |
| OraOopConstants.MIN_NUM_EXPORT_MAPPERS_ACCEPTED_BY_ORAOOP); |
| } |
| |
| public static int getMinNumberOfOracleRacActiveInstancesForDynamicJdbcUrlUse( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getInt(OraOopConstants.ORAOOP_MIN_RAC_ACTIVE_INSTANCES, |
| OraOopConstants.MIN_NUM_RAC_ACTIVE_INSTANCES_FOR_DYNAMIC_JDBC_URLS); |
| } |
| |
| public static int getNumberOfDataChunksPerOracleDataFile( |
| int desiredNumberOfMappers, org.apache.hadoop.conf.Configuration conf) { |
| |
| final String MAPPER_MULTIPLIER = "oraoop.datachunk.mapper.multiplier"; |
| final String RESULT_INCREMENT = "oraoop.datachunk.result.increment"; |
| |
| int numberToMultiplyMappersBy = conf.getInt(MAPPER_MULTIPLIER, 2); |
| int numberToIncrementResultBy = conf.getInt(RESULT_INCREMENT, 1); |
| |
| // The number of chunks generated will *not* be a multiple of the number of |
| // splits, |
| // to ensure that each split doesn't always get data from the start of each |
| // data-file... |
| int numberOfDataChunksPerOracleDataFile = |
| (desiredNumberOfMappers * numberToMultiplyMappersBy) |
| + numberToIncrementResultBy; |
| |
| LOG.debug(String.format("%s:\n" + "\t%s=%d\n" + "\t%s=%d\n" |
| + "\tdesiredNumberOfMappers=%d\n" + "\tresult=%d", |
| getCurrentMethodName(), MAPPER_MULTIPLIER, numberToMultiplyMappersBy, |
| RESULT_INCREMENT, numberToIncrementResultBy, desiredNumberOfMappers, |
| numberOfDataChunksPerOracleDataFile)); |
| |
| return numberOfDataChunksPerOracleDataFile; |
| } |
| |
| public static OraOopConstants.OraOopOracleDataChunkMethod |
| getOraOopOracleDataChunkMethod(Configuration conf) { |
| if (conf == null) { |
| throw new IllegalArgumentException("The conf argument cannot be null"); |
| } |
| |
| String strMethod = |
| conf.get(OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD); |
| if (strMethod == null) { |
| return OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD_DEFAULT; |
| } |
| |
| OraOopConstants.OraOopOracleDataChunkMethod result; |
| |
| try { |
| strMethod = strMethod.toUpperCase().trim(); |
| result = OraOopConstants.OraOopOracleDataChunkMethod.valueOf(strMethod); |
| } catch (IllegalArgumentException ex) { |
| result = OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD_DEFAULT; |
| LOG.error("An invalid value of \"" + strMethod |
| + "\" was specified for the \"" |
| + OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD |
| + "\" configuration property value.\n" + "\tThe default value of " |
| + OraOopConstants.ORAOOP_ORACLE_DATA_CHUNK_METHOD_DEFAULT |
| + " will be used."); |
| } |
| return result; |
| } |
| |
| public static |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod |
| getOraOopOracleBlockToSplitAllocationMethod( |
| org.apache.hadoop.conf.Configuration conf, |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod |
| defaultMethod) { |
| |
| if (conf == null) { |
| throw new IllegalArgumentException("The conf argument cannot be null"); |
| } |
| |
| String strMethod = |
| conf.get( |
| OraOopConstants.ORAOOP_ORACLE_BLOCK_TO_SPLIT_ALLOCATION_METHOD); |
| if (strMethod == null) { |
| return defaultMethod; |
| } |
| |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod result; |
| |
| try { |
| strMethod = strMethod.toUpperCase().trim(); |
| result = |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod |
| .valueOf(strMethod); |
| } catch (IllegalArgumentException ex) { |
| result = defaultMethod; |
| |
| String errorMsg = |
| String |
| .format( |
| "An invalid value of \"%s\" was specified for the \"%s\" " |
| + "configuration property value.\n" |
| + "\tValid values are: %s\n" |
| + "\tThe default value of %s will be used.", |
| strMethod, |
| OraOopConstants.ORAOOP_ORACLE_BLOCK_TO_SPLIT_ALLOCATION_METHOD, |
| getOraOopOracleBlockToSplitAllocationMethods(), defaultMethod |
| .name()); |
| LOG.error(errorMsg); |
| } |
| |
| return result; |
| } |
| |
| private static String getOraOopOracleBlockToSplitAllocationMethods() { |
| |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod[] values = |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod.values(); |
| |
| StringBuilder result = |
| new StringBuilder((2 * values.length) - 1); // <- Include capacity |
| // for commas |
| |
| for (int idx = 0; idx < values.length; idx++) { |
| OraOopConstants.OraOopOracleBlockToSplitAllocationMethod value = |
| values[idx]; |
| if (idx > 0) { |
| result.append(" or "); |
| } |
| result.append(value.name()); |
| } |
| return result.toString(); |
| } |
| |
| public static OraOopConstants.OraOopTableImportWhereClauseLocation |
| getOraOopTableImportWhereClauseLocation( |
| org.apache.hadoop.conf.Configuration conf, |
| OraOopConstants.OraOopTableImportWhereClauseLocation defaultLocation) { |
| |
| if (conf == null) { |
| throw new IllegalArgumentException("The conf argument cannot be null"); |
| } |
| |
| String strLocation = |
| conf.get(OraOopConstants.ORAOOP_TABLE_IMPORT_WHERE_CLAUSE_LOCATION); |
| if (strLocation == null) { |
| return defaultLocation; |
| } |
| |
| OraOopConstants.OraOopTableImportWhereClauseLocation result; |
| |
| try { |
| strLocation = strLocation.toUpperCase().trim(); |
| result = |
| OraOopConstants.OraOopTableImportWhereClauseLocation |
| .valueOf(strLocation); |
| } catch (IllegalArgumentException ex) { |
| result = defaultLocation; |
| |
| String errorMsg = |
| String |
| .format( |
| "An invalid value of \"%s\"was specified for the \"%s\" " |
| + "configuration property value.\n" |
| + "\tValid values are: %s\n" |
| + "\tThe default value of %s will be used.", strLocation, |
| OraOopConstants.ORAOOP_TABLE_IMPORT_WHERE_CLAUSE_LOCATION, |
| getOraOopTableImportWhereClauseLocations(), defaultLocation |
| .name()); |
| LOG.error(errorMsg); |
| } |
| |
| return result; |
| } |
| |
| private static String getOraOopTableImportWhereClauseLocations() { |
| |
| OraOopConstants.OraOopTableImportWhereClauseLocation[] locationValues = |
| OraOopConstants.OraOopTableImportWhereClauseLocation.values(); |
| |
| StringBuilder result = |
| new StringBuilder((2 * locationValues.length) - 1); // <- Include |
| // capacity for |
| // commas |
| |
| for (int idx = 0; idx < locationValues.length; idx++) { |
| OraOopConstants.OraOopTableImportWhereClauseLocation locationValue = |
| locationValues[idx]; |
| if (idx > 0) { |
| result.append(" or "); |
| } |
| result.append(locationValue.name()); |
| } |
| return result.toString(); |
| } |
| |
| public static String getOutputDirectory( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String workingDir = conf.get("mapred.working.dir"); |
| String outputDir = conf.get("mapred.output.dir"); |
| |
| return workingDir + "/" + outputDir; |
| } |
| |
| public static String padLeft(String s, int n) { |
| return StringUtils.leftPad(s, n); |
| } |
| |
| public static String padRight(String s, int n) { |
| return StringUtils.rightPad(s, n); |
| } |
| |
| public static String replaceConfigurationExpression(String str, |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| int startPos = str.indexOf('{'); |
| int endPos = str.indexOf('}'); |
| |
| // Example: |
| // alter session set timezone = '{oracle.sessionTimeZone|GMT}'; |
| |
| if (startPos == -1 || endPos == -1) { |
| return str; |
| } |
| |
| String configName = null; |
| String defaultValue = null; |
| |
| String expression = str.substring(startPos + 1, endPos); |
| int defaultValuePos = expression.indexOf('|'); |
| if (defaultValuePos == -1) { |
| // return expression; |
| configName = expression; |
| } else { |
| configName = expression.substring(0, defaultValuePos); |
| defaultValue = expression.substring(defaultValuePos + 1); |
| } |
| |
| if (defaultValue == null) { |
| defaultValue = ""; |
| } |
| |
| String configValue = conf.get(configName); |
| if (configValue == null) { |
| configValue = defaultValue; |
| } |
| |
| String result = str.replace(String.format("{%s}", expression), configValue); |
| |
| LOG.debug(String.format("The expression:\n%s\nwas replaced with:\n%s", str, |
| result)); |
| |
| // Recurse to evaluate any other expressions... |
| result = replaceConfigurationExpression(result, conf); |
| |
| return result; |
| } |
| |
| public static boolean stackContainsClass(String className) { |
| |
| StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace(); |
| for (StackTraceElement stackTraceElement : stackTraceElements) { |
| if (stackTraceElement.getClassName().equalsIgnoreCase(className)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public static Object startSessionSnapshot(Connection connection) { |
| |
| Object result = null; |
| try { |
| |
| Class<?> oraOopOraStatsClass = |
| Class.forName("quest.com.oraOop.oracleStats.OraOopOraStats"); |
| Method startSnapshotMethod = |
| oraOopOraStatsClass.getMethod("startSnapshot", Connection.class); |
| if (connection != null) { |
| result = startSnapshotMethod.invoke(null, connection); |
| } |
| } catch (ClassNotFoundException ex) { |
| throw new RuntimeException(ex); |
| } catch (NoSuchMethodException ex) { |
| throw new RuntimeException(ex); |
| } catch (InvocationTargetException ex) { |
| throw new RuntimeException(ex); |
| } catch (IllegalAccessException ex) { |
| throw new RuntimeException(ex); |
| } |
| |
| return result; |
| } |
| |
| public static OraOopStatsReports stopSessionSnapshot(Object oraOopOraStats) { |
| |
| OraOopStatsReports result = new OraOopStatsReports(); |
| |
| if (oraOopOraStats == null) { |
| return result; |
| } |
| |
| try { |
| |
| Class<?> oraOopOraStatsClass = |
| Class.forName("quest.com.oraOop.oracleStats.OraOopOraStats"); |
| Method finalizeSnapshotMethod = |
| oraOopOraStatsClass.getMethod("finalizeSnapshot", (Class<?>[]) null); |
| finalizeSnapshotMethod.invoke(oraOopOraStats, (Object[]) null); |
| |
| Method performanceReportCsvMethod = |
| oraOopOraStatsClass.getMethod("getStatisticsCSV", (Class<?>[]) null); |
| result.setCsvReport((String) performanceReportCsvMethod.invoke( |
| oraOopOraStats, (Object[]) null)); |
| |
| Method performanceReportMethod = |
| oraOopOraStatsClass.getMethod("performanceReport", (Class<?>[]) null); |
| result.setPerformanceReport((String) performanceReportMethod.invoke( |
| oraOopOraStats, (Object[]) null)); |
| } catch (ClassNotFoundException ex) { |
| throw new RuntimeException(ex); |
| } catch (NoSuchMethodException ex) { |
| throw new RuntimeException(ex); |
| } catch (InvocationTargetException ex) { |
| throw new RuntimeException(ex); |
| } catch (IllegalAccessException ex) { |
| throw new RuntimeException(ex); |
| } |
| |
| return result; |
| } |
| |
| public static boolean stringArrayContains(String[] list, String value, |
| boolean ignoreCase) { |
| |
| return stringArrayIndexOf(list, value, ignoreCase) > -1; |
| } |
| |
| public static int stringArrayIndexOf(String[] list, String value, |
| boolean ignoreCase) { |
| |
| for (int idx = 0; idx < list.length; idx++) { |
| if (list[idx].equals(value)) { |
| return idx; |
| } |
| if (ignoreCase && list[idx].equalsIgnoreCase(value)) { |
| return idx; |
| } |
| } |
| return -1; |
| } |
| |
| public static String stringArrayToCSV(String[] list) { |
| |
| return stringArrayToCSV(list, ""); |
| } |
| |
| public static String |
| stringArrayToCSV(String[] list, String encloseValuesWith) { |
| |
| StringBuilder result = new StringBuilder((list.length * 2) - 1); |
| for (int idx = 0; idx < list.length; idx++) { |
| if (idx > 0) { |
| result.append(","); |
| } |
| result |
| .append(String.format("%1$s%2$s%1$s", encloseValuesWith, list[idx])); |
| } |
| return result.toString(); |
| } |
| |
| public static int stringListIndexOf(List<String> list, String value, |
| boolean ignoreCase) { |
| |
| for (int idx = 0; idx < list.size(); idx++) { |
| if (list.get(idx).equals(value)) { |
| return idx; |
| } |
| if (ignoreCase && list.get(idx).equalsIgnoreCase(value)) { |
| return idx; |
| } |
| } |
| return -1; |
| } |
| |
| public static void writeOutputFile(org.apache.hadoop.conf.Configuration conf, |
| String fileName, String fileText) { |
| |
| Path uniqueFileName = null; |
| try { |
| // NOTE: This code is not thread-safe. |
| // i.e. A race-condition could still cause this code to 'fail'. |
| |
| int suffix = 0; |
| String fileNameTemplate = fileName + "%s"; |
| Path outputDirectory = new Path(getOutputDirectory(conf)); |
| FileSystem fileSystem = outputDirectory.getFileSystem(conf); |
| while (true) { |
| uniqueFileName = |
| new Path(outputDirectory, String.format(fileNameTemplate, |
| suffix == 0 ? "" : String.format(" (%d)", suffix))); |
| if (!fileSystem.exists(uniqueFileName)) { |
| break; |
| } |
| suffix++; |
| } |
| |
| FSDataOutputStream outputStream = |
| fileSystem.create(uniqueFileName, false); |
| if (fileText != null) { |
| outputStream.writeBytes(fileText); |
| } |
| outputStream.flush(); |
| outputStream.close(); |
| } catch (IOException ex) { |
| LOG.error(String.format("Error attempting to write the file %s\n" + "%s", |
| (uniqueFileName == null ? "null" : uniqueFileName.toUri()), |
| getFullExceptionMessage(ex))); |
| } |
| } |
| |
| /** |
| * Class to wrap details about Oracle connection string. |
| */ |
| public static class JdbcOracleThinConnection { |
| private String host; |
| private int port; |
| private String sid; |
| private String service; |
| private String tnsName; |
| |
| public JdbcOracleThinConnection(String host, int port, String sid, |
| String service, String tnsName) { |
| this.host = host; |
| this.port = port; |
| this.sid = sid; |
| this.service = service; |
| this.tnsName = tnsName; |
| } |
| |
| @Override |
| public String toString() { |
| // Use tnsName if it is available |
| if (this.tnsName != null && !this.tnsName.isEmpty()) { |
| return String.format("jdbc:oracle:thin:@%s", tnsName); |
| } |
| |
| // Use the SID if it's available... |
| if (this.sid != null && !this.sid.isEmpty()) { |
| return String.format("jdbc:oracle:thin:@%s:%d:%s", this.host, |
| this.port, this.sid); |
| } |
| |
| // Otherwise, use the SERVICE. Note that the service is prefixed by "/", |
| // not by ":"... |
| if (this.service != null && !this.service.isEmpty()) { |
| return String.format("jdbc:oracle:thin:@%s:%d/%s", this.host, |
| this.port, this.service); |
| } |
| |
| throw new RuntimeException( |
| "Unable to generate a JDBC URL, as no TNS name, SID or SERVICE " |
| + "has been provided."); |
| |
| } |
| |
| public String getHost() { |
| return host; |
| } |
| |
| public int getPort() { |
| return port; |
| } |
| |
| public String getSid() { |
| return sid; |
| } |
| |
| public String getService() { |
| return service; |
| } |
| |
| public String getTnsName() { |
| return tnsName; |
| } |
| } |
| |
| /** |
| * Thrown if the Oracle connection string cannot be parsed. |
| */ |
| public static class JdbcOracleThinConnectionParsingError extends Exception { |
| |
| private static final long serialVersionUID = 1559860600099354233L; |
| |
| public JdbcOracleThinConnectionParsingError(String message) { |
| |
| super(message); |
| } |
| |
| public JdbcOracleThinConnectionParsingError(String message, |
| Throwable cause) { |
| |
| super(message, cause); |
| } |
| |
| public JdbcOracleThinConnectionParsingError(Throwable cause) { |
| |
| super(cause); |
| } |
| } |
| |
| public static String getOracleServiceName( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.get(OraOopConstants.ORAOOP_ORACLE_RAC_SERVICE_NAME, ""); |
| } |
| |
| public static String generateOracleSidJdbcUrl(String hostName, int port, |
| String sid) { |
| |
| return String.format("jdbc:oracle:thin:@(DESCRIPTION=" + "(ADDRESS_LIST=" |
| + "(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%d))" + ")" |
| + "(CONNECT_DATA=(SERVER=DEDICATED)(SID=%s))" + ")", hostName, port, |
| sid); |
| } |
| |
| public static String generateOracleServiceNameJdbcUrl(String hostName, |
| int port, String serviceName) { |
| |
| return String.format("jdbc:oracle:thin:@(DESCRIPTION=" + "(ADDRESS_LIST=" |
| + "(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%d))" + ")" |
| + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=%s))" + ")", hostName, |
| port, serviceName); |
| } |
| |
| public static String generateOracleTnsNameJdbcUrl(String tnsName) { |
| return String.format("jdbc:oracle:thin:@%s", tnsName); |
| } |
| |
| public static String getMapperJdbcUrlPropertyName(int mapperId, |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return String.format("oraoop.mapper.jdbc.url.%d", mapperId); |
| } |
| |
| public static final String SQOOP_JOB_TYPE = "oraoop.sqoop.job.type"; |
| |
| public static void rememberSqoopJobType(OraOopConstants.Sqoop.Tool jobType, |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| conf.set(SQOOP_JOB_TYPE, jobType.name()); |
| } |
| |
| public static OraOopConstants.Sqoop.Tool recallSqoopJobType( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String jobType = conf.get(SQOOP_JOB_TYPE); |
| if (jobType == null || jobType.isEmpty()) { |
| throw new RuntimeException( |
| "RecallSqoopJobType() cannot be called unless RememberSqoopJobType() " |
| + "has been used."); |
| } |
| |
| OraOopConstants.Sqoop.Tool result = |
| OraOopConstants.Sqoop.Tool.valueOf(jobType); |
| return result; |
| } |
| |
| public static boolean omitLobAndLongColumnsDuringImport( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return conf.getBoolean(OraOopConstants.ORAOOP_IMPORT_OMIT_LOBS_AND_LONG, |
| false); |
| } |
| |
| public static boolean oracleSessionHasBeenKilled(Exception exception) { |
| |
| Throwable ex = exception; |
| |
| while (ex != null) { |
| if (ex instanceof SQLException |
| && ((SQLException) ex).getErrorCode() == 28) { // ORA-00028: your |
| // session has been |
| // killed |
| return true; |
| } |
| |
| ex = ex.getCause(); |
| } |
| |
| return false; |
| } |
| |
| private static String |
| formatTimestampForOracleObjectName(Object oracleDateTime) { |
| |
| // NOTE: Update decodeTimestampFromOracleObjectName() if you modify this |
| // method. |
| |
| String jobTimeStr = |
| OraOopOracleQueries.oraDATEToString(oracleDateTime, |
| OraOopConstants.ORACLE_OBJECT_NAME_DATE_TO_STRING_FORMAT_STRING); |
| |
| return jobTimeStr; |
| |
| // E.g. 20101028_151000 (15 characters) |
| } |
| |
| private static Object decodeTimestampFromOracleObjectName( |
| String oracleObjectNameTimestampFragment) { |
| |
| String dateString = oracleObjectNameTimestampFragment; |
| String dateFormatString = |
| OraOopConstants.ORACLE_OBJECT_NAME_DATE_TO_STRING_FORMAT_STRING; |
| |
| // return oracle.sql.DATE.fromText(oracleObjectNameTimestampFragment |
| // ,OraOopConstants.ORACLE_OBJECT_NAME_DATE_TO_STRING_FORMAT_STRING |
| // ,null); |
| |
| /* |
| * Unfortunately, we don't seem to be able to reliably decode strings into |
| * DATE objects using Oracle. For example, the following string will cause |
| * Oracle to throw an "Invalid Oracle date" exception, due to the time |
| * portion starting with a zero... |
| * oracle.sql.DATE.fromText("20101123 091554", "yyyymmdd hh24miss", null); |
| * |
| * Therefore, we need to manually deconstruct the date string and insert |
| * some colons into the time so that Oracle can decode the string. (This is |
| * therefore an Oracle bug we're working around.) |
| */ |
| |
| try { |
| String year = oracleObjectNameTimestampFragment.substring(0, 4); |
| String month = oracleObjectNameTimestampFragment.substring(4, 6); |
| String day = oracleObjectNameTimestampFragment.substring(6, 8); |
| String hour = oracleObjectNameTimestampFragment.substring(9, 11); |
| String minute = oracleObjectNameTimestampFragment.substring(11, 13); |
| String second = oracleObjectNameTimestampFragment.substring(13, 15); |
| dateString = |
| String.format("%s/%s/%s %s:%s:%s", year, month, day, hour, minute, |
| second); |
| dateFormatString = "yyyy/mm/dd hh24:mi:ss"; |
| |
| return OraOopOracleQueries.oraDATEFromString( |
| dateString, dateFormatString); |
| } catch (Exception ex) { |
| LOG.debug(String.format( |
| "%s could not convert the string \"%s\" into a DATE via the format " |
| + "string \"%s\".\n" + "The error encountered was:\n%s", |
| getCurrentMethodName(), dateString, dateFormatString, |
| getFullExceptionMessage(ex))); |
| |
| return null; |
| } |
| } |
| |
| public static String createExportTablePartitionNameFromOracleTimestamp( |
| Object oracleDateTime) { |
| |
| // Partition name can be up to 30 characters long and must start with a |
| // letter... |
| return OraOopConstants.EXPORT_TABLE_PARTITION_NAME_PREFIX |
| + formatTimestampForOracleObjectName(oracleDateTime); |
| |
| // E.g. ORAOOP_20101028_151000 (22 characters) |
| } |
| |
| public static String createExportTableNamePrefixFromOracleTimestamp( |
| Object oracleDateTime) { |
| |
| // NOTE: Alter decodeExportTableNamePrefix() if you modify this method. |
| |
| // Table name can be 30 characters long and must start with a letter... |
| return OraOopConstants.EXPORT_MAPPER_TABLE_NAME_PREFIX |
| + formatTimestampForOracleObjectName(oracleDateTime); |
| // G1.ORAOOP_20101028_152500 (22 characters) (This is just the prefix, |
| // append "_3" for mapper 4) |
| } |
| |
| public static Object decodeExportTableNamePrefix(String tableNamePrefix) { |
| |
| if (tableNamePrefix == null || tableNamePrefix.isEmpty()) { |
| return null; |
| } |
| |
| if (!tableNamePrefix |
| .startsWith(OraOopConstants.EXPORT_MAPPER_TABLE_NAME_PREFIX)) { |
| return null; |
| } |
| |
| String formattedTimestamp = |
| tableNamePrefix.substring( |
| OraOopConstants.EXPORT_MAPPER_TABLE_NAME_PREFIX.length(), |
| tableNamePrefix.length()); |
| |
| return decodeTimestampFromOracleObjectName(formattedTimestamp); |
| } |
| |
| private static boolean userWantsToCreateExportTableFromTemplate( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String exportTableTemplate = |
| conf.get(OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_TEMPLATE, ""); |
| if (exportTableTemplate.isEmpty()) { |
| return false; |
| } |
| |
| OraOopConstants.Sqoop.Tool tool = OraOopUtilities.recallSqoopJobType(conf); |
| switch (tool) { |
| case UNKNOWN: |
| case EXPORT: |
| return true; |
| |
| default: |
| return false; |
| } |
| } |
| |
| public static boolean enableOracleParallelProcessingDuringExport( |
| org.apache.hadoop.conf.Configuration conf) { |
| return conf.getBoolean(OraOopConstants.ORAOOP_EXPORT_PARALLEL, false); |
| } |
| |
| public static boolean userWantsToCreatePartitionedExportTableFromTemplate( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return userWantsToCreateExportTableFromTemplate(conf) |
| && conf.getBoolean( |
| OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_PARTITIONED, false); |
| } |
| |
| public static boolean userWantsToCreateNonPartitionedExportTableFromTemplate( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| return userWantsToCreateExportTableFromTemplate(conf) |
| && !conf.getBoolean( |
| OraOopConstants.ORAOOP_EXPORT_CREATE_TABLE_PARTITIONED, false); |
| } |
| |
| public static String generateExportTableSubPartitionName(int mapperId, |
| Object sysDateTime, org.apache.hadoop.conf.Configuration conf) { |
| |
| String partitionName = |
| createExportTablePartitionNameFromOracleTimestamp(sysDateTime); |
| |
| String subPartitionName = String.format("%s_MAP_%d" // <- Should allow for |
| // 1,000 mappers before |
| // exceeding 30 |
| // characters |
| , partitionName // <- Partition name is 22 characters |
| , mapperId); |
| |
| // Check the length of the name... |
| if (subPartitionName.length() |
| > OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH) { |
| throw new RuntimeException( |
| String |
| .format( |
| "The generated Oracle subpartition name \"%s\" is longer " |
| + "than %d characters.", |
| subPartitionName, |
| OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH)); |
| } |
| |
| return subPartitionName; |
| } |
| |
| public static String[] generateExportTableSubPartitionNames(int numMappers, |
| Object sysDateTime, org.apache.hadoop.conf.Configuration conf) { |
| |
| String[] result = new String[numMappers]; |
| for (int idx = 0; idx < numMappers; idx++) { |
| result[idx] = generateExportTableSubPartitionName(idx, sysDateTime, conf); |
| } |
| |
| return result; |
| } |
| |
| public static OracleTable generateExportTableMapperTableName(int mapperId, |
| Object sysDateTime, String schema) { |
| //mapperId: should allow 10,000,000 mappers before it exceeds 30 characters. |
| return generateExportTableMapperTableName(Integer.toString(mapperId) |
| , sysDateTime, schema); |
| } |
| |
| public static OracleTable generateExportTableMapperTableName( |
| String mapperSuffix, Object sysDateTime, String schema) { |
| |
| // NOTE: Update decodeExportTableMapperTableName() if you alter this method. |
| |
| // Generate a (22 character) prefix to use for the N tables that need to be |
| // created for the N mappers to insert into... |
| String mapperTableNamePrefix = |
| createExportTableNamePrefixFromOracleTimestamp(sysDateTime); |
| |
| // Generate the name... |
| String tableName = String.format("%s_%s", mapperTableNamePrefix // <- 22 |
| // chars |
| , mapperSuffix); |
| |
| // Check the length of the name... |
| if (tableName.length() > OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH) { |
| throw new RuntimeException( |
| String |
| .format( |
| "The generated Oracle table name \"%s\" is longer than " |
| + "%d characters.", |
| tableName, OraOopConstants.Oracle.MAX_IDENTIFIER_LENGTH)); |
| } |
| |
| return new OracleTable(schema, tableName); |
| } |
| |
| /** |
| * Class to wrap the table name to be used for the mapper. |
| */ |
| public static class DecodedExportMapperTableName { |
| private String mapperId; // <- This is not an int, because it might be "CHG" |
| // in the case of a "changes-table". |
| private Object tableDateTime; |
| |
| public String getMapperId() { |
| return mapperId; |
| } |
| |
| public void setMapperId(String newMapperId) { |
| this.mapperId = newMapperId; |
| } |
| |
| public Object getTableDateTime() { |
| return tableDateTime; |
| } |
| |
| public void setTableDateTime(Object newTableDateTime) { |
| this.tableDateTime = newTableDateTime; |
| } |
| } |
| |
| public static DecodedExportMapperTableName decodeExportTableMapperTableName( |
| OracleTable oracleTable) { |
| |
| DecodedExportMapperTableName result = null; |
| try { |
| int lastUnderScoreIndex = oracleTable.getName().lastIndexOf("_"); |
| if (lastUnderScoreIndex == -1) { |
| return result; |
| } |
| |
| String dateFragment = |
| oracleTable.getName().substring(0, lastUnderScoreIndex); |
| String mapperIdFragment = |
| oracleTable.getName().substring(lastUnderScoreIndex + 1, |
| oracleTable.getName().length()); |
| |
| Object sysDateTime = decodeExportTableNamePrefix(dateFragment); |
| if (sysDateTime != null) { |
| result = new DecodedExportMapperTableName(); |
| result.setTableDateTime(sysDateTime); |
| result.setMapperId(mapperIdFragment); |
| } |
| } catch (Exception ex) { |
| LOG.debug( |
| String.format( |
| "Error when attempting to decode the export mapper-table name \"%s\".", |
| oracleTable.toString()), ex); |
| } |
| return result; |
| } |
| |
| public static void rememberOracleDateTime( |
| org.apache.hadoop.conf.Configuration conf, String propertyName, |
| String dateTime) { |
| conf.set(propertyName, dateTime); |
| } |
| |
| public static Object recallOracleDateTime( |
| org.apache.hadoop.conf.Configuration conf, String propertyName) { |
| |
| String dateTimeStr = conf.get(propertyName); |
| if (dateTimeStr == null || dateTimeStr.isEmpty()) { |
| throw new RuntimeException(String.format( |
| "Unable to recall the value of the property \"%s\".", propertyName)); |
| } |
| |
| return OraOopOracleQueries.oraDATEFromString(dateTimeStr, |
| "yyyy-mm-dd hh24:mi:ss"); |
| } |
| |
| public static UpdateMode getExportUpdateMode( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| // NB: The Sqoop code does not add the column specified in the |
| // "--update-key" argument |
| // as a configuration property value until quite late in the process. i.e. |
| // After the |
| // OraOopManagerFactory.accept() have been called. |
| // (It is available via sqoopOptions.getUpdateKeyCol() however.) |
| // Therefore, when calling this method you need to be confident that the |
| // export being |
| // performed is actually an "update" export and not an "import" one. |
| |
| // String updateKeyCol = |
| // conf.get(ExportJobBase.SQOOP_EXPORT_UPDATE_COL_KEY); |
| // if(updateKeyCol == null || |
| // updateKeyCol.isEmpty()) |
| // throw new |
| // RuntimeException(String.format("This job is not an update-export. "+ |
| // "i.e. %s has not been specified." |
| // ,ExportJobBase.SQOOP_EXPORT_UPDATE_COL_KEY)); |
| |
| UpdateMode updateMode = UpdateMode.Update; |
| |
| boolean mergeData = |
| conf.getBoolean(OraOopConstants.ORAOOP_EXPORT_MERGE, false); |
| if (mergeData) { |
| updateMode = UpdateMode.Merge; |
| } |
| |
| return updateMode; |
| } |
| |
| public static InsertMode getExportInsertMode( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| InsertMode result = InsertMode.DirectInsert; |
| |
| if (OraOopUtilities |
| .userWantsToCreatePartitionedExportTableFromTemplate(conf) |
| || conf.getBoolean(OraOopConstants.EXPORT_TABLE_HAS_ORAOOP_PARTITIONS, |
| false)) { |
| result = InsertMode.ExchangePartition; |
| } |
| |
| return result; |
| } |
| |
| public static String getJavaClassPath() { |
| |
| return System.getProperty("java.class.path"); |
| } |
| |
| public static String replaceAll(String inputString, String textToReplace, |
| String replaceWith) { |
| |
| String result = inputString.replaceAll(textToReplace, replaceWith); |
| if (!result.equals(inputString)) { |
| result = replaceAll(result, textToReplace, replaceWith); |
| } |
| |
| return result; |
| } |
| |
| public static String getTemporaryTableStorageClause( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String result = |
| conf.get(OraOopConstants.ORAOOP_TEMPORARY_TABLE_STORAGE_CLAUSE, ""); |
| if (result == null) { |
| result = ""; |
| } |
| return result; |
| } |
| |
| public static String getExportTableStorageClause( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String result = |
| conf.get(OraOopConstants.ORAOOP_EXPORT_TABLE_STORAGE_CLAUSE, ""); |
| if (result == null) { |
| result = ""; |
| } |
| return result; |
| } |
| |
| public static String[] getExportUpdateKeyColumnNames(SqoopOptions options) { |
| |
| String updateKey = options.getUpdateKeyCol(); |
| return getExtraExportUpdateKeyColumnNames(updateKey, options.getConf()); |
| } |
| |
| public static String[] getExportUpdateKeyColumnNames( |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| String updateKey = conf.get(ExportJobBase.SQOOP_EXPORT_UPDATE_COL_KEY); |
| return getExtraExportUpdateKeyColumnNames(updateKey, conf); |
| } |
| |
| /** |
| * Splits a string separated by commas - the elements can be optionally |
| * enclosed in quotes - this allows the elements to have commas in them. |
| * |
| * @param value |
| * The String to be split |
| * @return A list of values |
| */ |
| public static List<String> splitStringList(String value) { |
| List<String> result = new ArrayList<String>(); |
| if (value != null && !value.isEmpty()) { |
| Pattern pattern = Pattern.compile("([^\",]*|\"[^\"]*\")(,|$)"); |
| Matcher matcher = pattern.matcher(value); |
| while (matcher.find()) { |
| if (matcher.group(1) != null && !matcher.group(1).isEmpty()) { |
| result.add(matcher.group(1)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Splits a string list separated by commas. If the element is not surrounded |
| * by quotes it will be return in upper case. If the element is enclosed in |
| * quotes it will be returned in the same case and special characters will be |
| * retained. |
| * |
| * @param value |
| * The String to be split |
| * @return A list of values |
| */ |
| public static List<String> splitOracleStringList(String value) { |
| List<String> result = new ArrayList<String>(); |
| List<String> splitValue = splitStringList(value); |
| Pattern pattern = Pattern.compile("(\")([^\"]*)(\")"); |
| for (String element : splitValue) { |
| Matcher matcher = pattern.matcher(element); |
| if (matcher.find()) { |
| result.add(matcher.group(2)); |
| } else { |
| result.add(element.toUpperCase()); |
| } |
| } |
| return result; |
| } |
| |
| private static String[] getExtraExportUpdateKeyColumnNames(String updateKey, |
| org.apache.hadoop.conf.Configuration conf) { |
| |
| if (updateKey == null) { |
| // This must be an "insert-export" if no --update-key has been specified! |
| return new String[0]; |
| } |
| |
| String extraKeys = |
| conf.get(OraOopConstants.ORAOOP_UPDATE_KEY_EXTRA_COLUMNS, ""); |
| if (!extraKeys.isEmpty()) { |
| updateKey += "," + extraKeys; |
| } |
| |
| String[] columnNames = updateKey.split(","); |
| for (int idx = 0; idx < columnNames.length; idx++) { |
| columnNames[idx] = columnNames[idx].trim(); |
| if (!columnNames[idx].startsWith("\"")) { |
| columnNames[idx] = columnNames[idx].toUpperCase(); |
| } |
| |
| } |
| return columnNames; |
| } |
| |
| public static OraOopConstants.AppendValuesHintUsage |
| getOracleAppendValuesHintUsage(org.apache.hadoop.conf.Configuration conf) { |
| |
| if (conf == null) { |
| throw new IllegalArgumentException("The conf argument cannot be null"); |
| } |
| |
| String strUsage = |
| conf.get(OraOopConstants.ORAOOP_ORACLE_APPEND_VALUES_HINT_USAGE); |
| if (strUsage == null) { |
| return OraOopConstants.AppendValuesHintUsage.AUTO; |
| } |
| |
| OraOopConstants.AppendValuesHintUsage result; |
| |
| try { |
| strUsage = strUsage.toUpperCase().trim(); |
| result = OraOopConstants.AppendValuesHintUsage.valueOf(strUsage); |
| } catch (IllegalArgumentException ex) { |
| result = OraOopConstants.AppendValuesHintUsage.AUTO; |
| |
| String errorMsg = |
| String |
| .format( |
| "An invalid value of \"%s\" was specified for the \"%s\" " |
| + "configuration property value.\n" |
| + "\tValid values are: %s\n" |
| + "\tThe default value of %s will be used.", strUsage, |
| OraOopConstants.ORAOOP_ORACLE_APPEND_VALUES_HINT_USAGE, |
| getOraOopOracleAppendValuesHintUsageValues(), |
| OraOopConstants.AppendValuesHintUsage.AUTO.name()); |
| LOG.error(errorMsg); |
| } |
| |
| return result; |
| } |
| |
| private static String getOraOopOracleAppendValuesHintUsageValues() { |
| |
| OraOopConstants.AppendValuesHintUsage[] values = |
| OraOopConstants.AppendValuesHintUsage.values(); |
| |
| StringBuilder result = new StringBuilder((2 * values.length) - 1); // <- |
| // Include |
| // capacity |
| // for |
| // commas |
| |
| for (int idx = 0; idx < values.length; idx++) { |
| OraOopConstants.AppendValuesHintUsage value = values[idx]; |
| if (idx > 0) { |
| result.append(" or "); |
| } |
| result.append(value.name()); |
| } |
| return result.toString(); |
| } |
| |
| public static String getImportHint( |
| org.apache.hadoop.conf.Configuration conf) { |
| String result = null; |
| result = conf.get(OraOopConstants.IMPORT_QUERY_HINT); |
| if (result == null || result.trim().isEmpty()) { |
| result = ""; |
| } else { |
| result = String.format(OraOopConstants.Oracle.HINT_SYNTAX, result); |
| } |
| return result; |
| } |
| |
| public static void appendJavaSecurityEgd(Configuration conf) { |
| String mapredJavaOpts = conf.get("mapred.child.java.opts"); |
| if (mapredJavaOpts == null |
| || !mapredJavaOpts.contains("-Djava.security.egd")) { |
| StringBuilder newMapredJavaOpts = |
| new StringBuilder("-Djava.security.egd=file:///dev/urandom"); |
| if (mapredJavaOpts != null && !mapredJavaOpts.isEmpty()) { |
| newMapredJavaOpts.append(" ").append(mapredJavaOpts); |
| } |
| String newMapredJavaOptsString = newMapredJavaOpts.toString(); |
| conf.set("mapred.child.java.opts", newMapredJavaOptsString); |
| LOG.debug("Updated mapred.child.java.opts from \"" + mapredJavaOpts |
| + "\" to \"" + newMapredJavaOptsString + "\""); |
| } |
| } |
| |
| public static void checkJavaSecurityEgd() { |
| String javaSecurityEgd = System.getProperty("java.security.egd"); |
| if (!"file:///dev/urandom".equals(javaSecurityEgd)) { |
| LOG.warn("System property java.security.egd is not set to " |
| + "file:///dev/urandom - Oracle connections may time out."); |
| } |
| } |
| public static void setCurrentSessionUser(String user) { |
| currentSessionUser = user; |
| } |
| } |