/** * Performs the compaction. * * @param scanner Where to read from. * @param writer Where to write to. * @param smallestReadPoint Smallest read point. * @param cleanSeqId When true, remove seqId(used to be mvcc) value which is <= smallestReadPoint * @return Whether compaction ended; false if it was interrupted for some reason. */ protected boolean performCompaction( InternalScanner scanner, CellSink writer, long smallestReadPoint, boolean cleanSeqId) throws IOException { int bytesWritten = 0; // Since scanner.next() can return 'false' but still be delivering data, // we have to use a do/while loop. List<Cell> kvs = new ArrayList<Cell>(); int closeCheckInterval = HStore.getCloseCheckInterval(); long lastMillis; if (LOG.isDebugEnabled()) { lastMillis = System.currentTimeMillis(); } else { lastMillis = 0; } boolean hasMore; do { hasMore = scanner.next(kvs, compactionKVMax); // output to writer: for (Cell c : kvs) { KeyValue kv = KeyValueUtil.ensureKeyValue(c); if (cleanSeqId && kv.getSequenceId() <= smallestReadPoint) { kv.setSequenceId(0); } writer.append(kv); ++progress.currentCompactedKVs; progress.totalCompactedSize += kv.getLength(); // check periodically to see if a system stop is requested if (closeCheckInterval > 0) { bytesWritten += kv.getLength(); if (bytesWritten > closeCheckInterval) { // Log the progress of long running compactions every minute if // logging at DEBUG level if (LOG.isDebugEnabled()) { long now = System.currentTimeMillis(); if ((now - lastMillis) >= 60 * 1000) { LOG.debug( "Compaction progress: " + progress + String.format( ", rate=%.2f kB/sec", (bytesWritten / 1024.0) / ((now - lastMillis) / 1000.0))); lastMillis = now; } } bytesWritten = 0; if (!store.areWritesEnabled()) { progress.cancel(); return false; } } } } kvs.clear(); } while (hasMore); progress.complete(); return true; }