public String getPKIndex(OracleTriggerMonitoredSourceInfo sourceInfo) { String index = _pKeyIndexMap.get(sourceInfo.getEventView()); if (null == index) { index = sourceInfo.getEventView() + "_pk"; } return index; }
@Override public ReadEventCycleSummary readEventsFromAllSources(long sinceSCN) throws DatabusException, EventCreationException, UnsupportedKeyException { List<EventReaderSummary> summaries = new ArrayList<EventReaderSummary>(); long maxScn = EventReaderSummary.NO_EVENTS_SCN; long endScn = maxScn; boolean error = false; long startTS = System.currentTimeMillis(); try { _rate.start(); _rate.suspend(); Connection conn = null; try { conn = _dataSource.getConnection(); LOG.info("Oracle JDBC Version :" + conn.getMetaData().getDriverVersion()); } finally { DBHelper.close(conn); } if (!_sources.isEmpty()) { // Script assumes seeding is done for one schema at a time // just use one source to get the schema name for sy$txlog maxScn = getMaxScn(_sources.get(0)); } for (OracleTriggerMonitoredSourceInfo sourceInfo : _sources) { LOG.info("Bootstrapping " + sourceInfo.getEventView()); _bootstrapSeedWriter.start(maxScn); EventReaderSummary summary = readEventsForSource(sourceInfo, maxScn); // Script assumes seeding is done for one schema at a time // just use one source to get the schema name for sy$txlog endScn = getMaxScn(_sources.get(0)); _bootstrapSeedWriter.endEvents(BootstrapEventBuffer.END_OF_SOURCE, endScn, null); summaries.add(summary); } } catch (Exception ex) { error = true; throw new DatabusException(ex); } finally { // Notify writer that I am done if (error) { _bootstrapSeedWriter.endEvents(BootstrapEventBuffer.ERROR_CODE, endScn, null); LOG.error("Seeder stopping unexpectedly !!"); } else { _bootstrapSeedWriter.endEvents(BootstrapEventBuffer.END_OF_FILE, endScn, null); LOG.info("Completed Seeding !!"); } LOG.info("Start SCN :" + maxScn); LOG.info("End SCN :" + endScn); } long endTS = System.currentTimeMillis(); ReadEventCycleSummary cycleSummary = new ReadEventCycleSummary("seeder", summaries, maxScn, (endTS - startTS)); return cycleSummary; }
public void validate() throws Exception { if (null == _pKeyTypeMap) throw new Exception("_pKeyTypeMap cannot be null !!"); if (null == _pKeyNameMap) throw new Exception("_pKeyNameMap cannot be null !!"); boolean isNullIndex = (null == _pKeyIndexMap); boolean isNullQueryHint = (null == _queryHintMap); if (isNullIndex && isNullQueryHint) throw new Exception("Index and Query Hint both cannot be null !!"); for (OracleTriggerMonitoredSourceInfo s : _sources) { if (null == _pKeyTypeMap.get(s.getEventView())) throw new Exception("pKey Type for Source (" + s.getEventView() + ") not provided !!"); if (null == _pKeyNameMap.get(s.getEventView())) throw new Exception("pKey Name for Source (" + s.getEventView() + ") not provided !!"); if ((isNullIndex || (null == _pKeyIndexMap.get(s.getEventView()))) && (isNullQueryHint || (null == _queryHintMap.get(s.getEventView())))) { throw new Exception( "Both pkey Index and Query Hint for source (" + s.getEventView() + ") not provided !!"); } } }
public String getQueryHint(OracleTriggerMonitoredSourceInfo sourceInfo) { String index = _queryHintMap.get(sourceInfo.getEventView()); if (null == index) { return null; } return index; }
private long getMaxScn(OracleTriggerMonitoredSourceInfo sourceInfo) throws SQLException { String schema = (sourceInfo.getEventSchema() == null) ? "" : sourceInfo.getEventSchema() + "."; String table = schema + "sy$txlog"; /* StringBuilder sql = new StringBuilder(); sql.append("select max(scn) from "); sql.append(table); String query = sql.toString(); */ String query = "select " + "max(" + schema + "sync_core.getScn(scn,ora_rowscn)) " + "from " + table + " where " + "scn >= (select max(scn) from " + table + ")"; long maxScn = executeAndGetLong(query); return maxScn; }
public static String getTableName(OracleTriggerMonitoredSourceInfo sourceInfo) { String schema = (sourceInfo.getEventSchema() == null) ? "" : sourceInfo.getEventSchema() + "."; String table = schema + "sy$" + sourceInfo.getEventView(); return table; }
private EventReaderSummary readEventsForSource( OracleTriggerMonitoredSourceInfo sourceInfo, long maxScn) throws DatabusException, EventCreationException, UnsupportedKeyException, SQLException, IOException { int retryMax = _numRetries; int numRetry = 0; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; KeyType keyType = _pKeyTypeMap.get(sourceInfo.getEventView()); String keyName = _pKeyNameMap.get(sourceInfo.getEventView()); String sql = _eventQueryMap.get(sourceInfo.getEventView()); String beginSrcKey = _beginSrcKeyMap.get(sourceInfo.getEventView()); String endSrcKey = _endSrcKeyMap.get(sourceInfo.getEventView()); if (sql == null) { sql = generateEventQuery2( sourceInfo, keyName, keyType, getPKIndex(sourceInfo), getQueryHint(sourceInfo)); } LOG.info("Chunked Query for Source (" + sourceInfo + ") is :" + sql); LOG.info("EndSrcKey for source (" + sourceInfo + ") is :" + endSrcKey); PrimaryKeyTxn endKeyTxn = null; if ((null != endSrcKey) && (!endSrcKey.trim().isEmpty())) { if (KeyType.LONG == keyType) endKeyTxn = new PrimaryKeyTxn(new Long(endSrcKey)); else endKeyTxn = new PrimaryKeyTxn(endSrcKey); } long timestamp = System.currentTimeMillis(); int numRowsFetched = 0; long totalEventSize = 0; long timeStart = System.currentTimeMillis(); long checkpointInterval = _commitInterval; boolean done = false; long lastTime = timeStart; long numRows = 0; PrimaryKeyTxn pKey = null; String minKeySQL = generateMinKeyQuery(sourceInfo, keyName); String srcName = sourceInfo.getEventView(); LOG.info("Bootstrapping for Source :" + srcName); String lastKey = _lastKeys.get(sourceInfo.getEventView()); File f = _keyTxnFilesMap.get(srcName); FileWriter oStream = new FileWriter(f, f.exists()); BufferedWriter keyTxnWriter = new BufferedWriter(oStream, _keyTxnBufferSizeMap.get(srcName)); _bootstrapSeedWriter.startEvents(); RateMonitor seedingRate = new RateMonitor("Seeding Rate"); RateMonitor queryRate = new RateMonitor("Query Rate"); seedingRate.start(); seedingRate.suspend(); queryRate.start(); queryRate.suspend(); boolean isException = false; long totProcessTime = 0; try { conn = _dataSource.getConnection(); pstmt = conn.prepareStatement(sql); if (_enableNumRowsQuery) numRows = getNumRows(conn, getTableName(sourceInfo)); else numRows = -1; long currRowId = _lastRows.get(sourceInfo.getEventView()); /** * First Key to be seeded will be decided in the following order: 1. Use * bootstrap_seeder_state's last srcKey as the key for the first chunk. 2. If (1) is empty, * use passed-in begin srcKey. 3. If (2) is also empty, use Oracle's minKey as the first Chunk * Key. */ if (null == lastKey) { lastKey = _beginSrcKeyMap.get(sourceInfo.getEventView()); LOG.info( "No last Src Key available in bootstrap_seeder_state for source (" + sourceInfo + ". Trying beginSrc Key from config :" + lastKey); } if ((null == lastKey) || (lastKey.trim().isEmpty())) { if (KeyType.LONG == keyType) pKey = new PrimaryKeyTxn(executeAndGetLong(minKeySQL)); else pKey = new PrimaryKeyTxn(executeAndGetString(minKeySQL)); } else { if (KeyType.LONG == keyType) pKey = new PrimaryKeyTxn(Long.parseLong(lastKey)); else pKey = new PrimaryKeyTxn(lastKey); } PrimaryKeyTxn lastRoundKeyTxn = new PrimaryKeyTxn(pKey); PrimaryKeyTxn lastKeyTxn = new PrimaryKeyTxn(pKey); long numUniqueKeysThisRound = 0; boolean first = true; _rate.resume(); while (!done) { LOG.info("MinKey being used for this round:" + pKey); numUniqueKeysThisRound = 0; try { lastRoundKeyTxn.copyFrom(pKey); if (KeyType.LONG == keyType) { pstmt.setLong(1, pKey.getKey()); } else { String key = pKey.getKeyStr(); pstmt.setString(1, key); } pstmt.setLong(2, _numRowsPerQuery); pstmt.setFetchSize(_numRowsPrefetch); if (_oraclePreparedStatementClass.isInstance(pstmt)) { try { _setLobPrefetchSizeMethod.invoke(pstmt, _LOBPrefetchSize); } catch (Exception e) { throw new EventCreationException("Unable to set Lob Prefetch size" + e.getMessage()); } } LOG.info( "Executing Oracle Query :" + sql + ". Key: " + pKey + ",NumRows: " + _numRowsPerQuery); queryRate.resume(); rs = pstmt.executeQuery(); queryRate.suspend(); LOG.info("Total Query Latency :" + queryRate.getDuration() / 1000000000L); long totLatency = 0; long txnId = 0; int numRowsThisRound = 0; seedingRate.resume(); while (rs.next()) { _rate.tick(); seedingRate.tick(); currRowId++; txnId = rs.getLong(2); if (KeyType.LONG == keyType) { pKey.setKeyTxn(rs.getLong(1), txnId); } else { String key = rs.getString(1); pKey.setKeyStrTxn(key, txnId); } // Write TXN to file pKey.writeTo(keyTxnWriter); // LOG.info("TXNId is :" + txnId + ",RowId is :" + currRowId); long start = System.nanoTime(); long eventSize = sourceInfo .getFactory() .createAndAppendEvent(maxScn, timestamp, rs, _bootstrapSeedWriter, false, null); long latency = System.nanoTime() - start; totLatency += latency; totalEventSize += eventSize; totProcessTime += (totLatency / 1000 * 1000); numRowsFetched++; numRowsThisRound++; if (lastKeyTxn.compareKey(pKey) != 0) { numUniqueKeysThisRound++; lastKeyTxn.copyFrom(pKey); } if (numRowsFetched % checkpointInterval == 0) { // Commit this batch and reinit _bootstrapSeedWriter.endEvents(currRowId, timestamp, null); keyTxnWriter.flush(); _bootstrapSeedWriter.startEvents(); long procTime = totLatency / 1000000000; long currTime = System.currentTimeMillis(); long diff = (currTime - lastTime) / 1000; long timeSinceStart = (currTime - timeStart) / 1000; double currRate = _rate.getRate(); currRate = (currRate <= 0) ? 1 : currRate; if (_enableNumRowsQuery) { double remTime = (numRows - currRowId) / (currRate); LOG.info( "Processed " + checkpointInterval + " rows in " + diff + " seconds, Processing Time (seconds) so far :" + (procTime) + ",Seconds elapsed since start :" + (timeSinceStart) + ",Approx Seconds remaining :" + remTime + ",Overall Row Rate:" + _rate.getRate() + "(" + seedingRate.getRate() + ")" + ",NumRows Fetched so far:" + numRowsFetched + ". TotalEventSize :" + totalEventSize); } else { LOG.info( "Processed " + checkpointInterval + " rows in " + diff + " seconds, Processing Time (seconds) so far :" + (procTime) + ",Seconds elapsed since start :" + (timeSinceStart) + ",Overall Row Rate:" + _rate.getRate() + "(" + seedingRate.getRate() + ")" + ",NumRows Fetched so far:" + numRowsFetched + ". TotalEventSize :" + totalEventSize); } lastTime = currTime; } if ((null != endKeyTxn) && (endKeyTxn.compareKey(lastKeyTxn) < 0)) { LOG.info( "Seeding to be stopped for current source as it has completed seeding upto endSrckey :" + endKeyTxn + ", Current SrcKey :" + lastKeyTxn); break; } } seedingRate.suspend(); if ((numRowsThisRound <= 1) || ((numRowsThisRound < _numRowsPerQuery) && (numUniqueKeysThisRound <= 1))) { LOG.info( "Seeding Done for source :" + sourceInfo.getEventView() + ", numRowsThisRound :" + numRowsThisRound + ", _numRowsPerQuery :" + _numRowsPerQuery + ", numUniqueKeys :" + numUniqueKeysThisRound); done = true; } else if ((numRowsThisRound == _numRowsPerQuery) && (numUniqueKeysThisRound <= 1)) { String msg = "Seeding stuck at infinte loop for source : " + sourceInfo.getEventView() + ", numRowsThisRound :" + numRowsThisRound + ", _numRowsPerQuery :" + _numRowsPerQuery + ", numUniqueKeys :" + numUniqueKeysThisRound + ", lastChunkKey :" + lastRoundKeyTxn; LOG.error(msg); throw new DatabusException(msg); } else if (null != endKeyTxn) { if (endKeyTxn.compareKey(lastKeyTxn) < 0) { LOG.info( "Seeding stopped for source :" + sourceInfo.getEventView() + ", as it has completed seeding upto the endSrckey :" + endKeyTxn + ", numRowsThisRound :" + numRowsThisRound + ", _numRowsPerQuery :" + _numRowsPerQuery + ", numUniqueKeys :" + numUniqueKeysThisRound + " , Current SrcKey :" + lastKeyTxn); done = true; } } if (currRowId > 0 && (!first || done)) { currRowId--; // Since next time, we will read the last seen record again } LOG.info("about to call end events with currRowId = " + currRowId); first = false; _bootstrapSeedWriter.endEvents(currRowId, timestamp, null); isException = false; } catch (SQLException ex) { LOG.error("Got SQLException for source (" + sourceInfo + ")", ex); _bootstrapSeedWriter.rollbackEvents(); numRetry++; isException = true; if (numRetry >= retryMax) { throw new DatabusException( "Error: Reached max retries for reading/processing bootstrap", ex); } } finally { DBHelper.close(rs); rs = null; } } } catch (DatabusException ex) { isException = true; throw ex; } finally { DBHelper.close(rs, pstmt, conn); keyTxnWriter.close(); rs = null; _rate.suspend(); if (!isException) { dedupeKeyTxnFile(_keyTxnFilesMap.get(srcName), keyType); } } long timeEnd = System.currentTimeMillis(); long elapsedMin = (timeEnd - timeStart) / (MILLISEC_TO_MIN); LOG.info( "Processed " + numRowsFetched + " rows of Source: " + sourceInfo.getSourceName() + " in " + elapsedMin + " minutes"); return new EventReaderSummary( sourceInfo.getSourceId(), sourceInfo.getSourceName(), -1, numRowsFetched, totalEventSize, (timeEnd - timeStart), totProcessTime, 0, 0, 0); }