@Override public synchronized DynamicPartitionMapImpl getMap() { ClosableIterator<RowResult<Value>> iterator = storage.getRange(PARTITION_MAP_TABLE, RangeRequest.all(), 1L); Map<Cell, byte[]> cells = Maps.newHashMap(); while (iterator.hasNext()) { RowResult<Value> row = iterator.next(); for (Entry<Cell, Value> entry : row.getCells()) { assert !cells.containsKey(entry.getKey()); cells.put(entry.getKey(), entry.getValue().getContents()); } } iterator.close(); return DynamicPartitionMapImpl.fromTable(cells); }
@Override public SweepResults run(String tableName, int batchSize, @Nullable byte[] startRow) { Preconditions.checkNotNull(tableName); Preconditions.checkState(!AtlasDbConstants.hiddenTables.contains(tableName)); if (tableName.startsWith(AtlasDbConstants.NAMESPACE_PREFIX)) { // this happens sometimes; I think it's because some places in the code can // start this sweeper without doing the full normally ordered KVSModule startup. // I did check and sweep.stats did contain the FQ table name for all of the tables, // so it is at least broken in some way that still allows namespaced tables to eventually be // swept. log.warn("The sweeper should not be run on tables passed through namespace mapping."); return SweepResults.EMPTY_SWEEP; } // Earliest start timestamp of any currently open transaction, with two caveats: // (1) unreadableTimestamps are calculated via wall-clock time, and so may not be correct // under pathological clock conditions // (2) immutableTimestamps do not account for locks have timed out after checking their locks; // such a transaction may have a start timestamp less than the immutableTimestamp, and it // could still get successfully committed (its commit timestamp may or may not be less than // the immutableTimestamp // Note that this is fine, because we'll either // (1) force old readers to abort (if they read a garbage collection sentinel), or // (2) force old writers to retry (note that we must roll back any uncommitted transactions that // we encounter SweepStrategy sweepStrategy = sweepStrategyManager.get().get(tableName); if (sweepStrategy == null) { sweepStrategy = SweepStrategy.CONSERVATIVE; } else if (sweepStrategy == SweepStrategy.NOTHING) { return SweepResults.EMPTY_SWEEP; } if (startRow == null) { startRow = new byte[0]; } RangeRequest rangeRequest = RangeRequest.builder().startRowInclusive(startRow).batchHint(batchSize).build(); long sweepTimestamp = getSweepTimestamp(sweepStrategy); ClosableIterator<RowResult<Value>> valueResults; if (sweepStrategy == SweepStrategy.CONSERVATIVE) { valueResults = ClosableIterators.wrap(ImmutableList.<RowResult<Value>>of().iterator()); } else { valueResults = keyValueService.getRange(tableName, rangeRequest, sweepTimestamp); } ClosableIterator<RowResult<Set<Long>>> rowResults = keyValueService.getRangeOfTimestamps(tableName, rangeRequest, sweepTimestamp); try { List<RowResult<Set<Long>>> rowResultTimestamps = ImmutableList.copyOf(Iterators.limit(rowResults, batchSize)); PeekingIterator<RowResult<Value>> peekingValues = Iterators.peekingIterator(valueResults); Set<Cell> sentinelsToAdd = Sets.newHashSet(); Multimap<Cell, Long> rowTimestamps = getTimestampsFromRowResults(rowResultTimestamps, sweepStrategy); Multimap<Cell, Long> cellTsPairsToSweep = getCellTsPairsToSweep( rowTimestamps, peekingValues, sweepTimestamp, sweepStrategy, sentinelsToAdd); sweepCells(tableName, cellTsPairsToSweep, sentinelsToAdd); byte[] nextRow = rowResultTimestamps.size() < batchSize ? null : RangeRequests.getNextStartRow( false, Iterables.getLast(rowResultTimestamps).getRowName()); return new SweepResults(nextRow, rowResultTimestamps.size(), cellTsPairsToSweep.size()); } finally { rowResults.close(); valueResults.close(); } }