private void installCompactionResults(CompactionState compact) throws IOException { Preconditions.checkState(mutex.isHeldByCurrentThread()); // Add compaction outputs compact.compaction.addInputDeletions(compact.compaction.getEdit()); int level = compact.compaction.getLevel(); for (FileMetaData output : compact.outputs) { compact.compaction.getEdit().addFile(level + 1, output); pendingOutputs.remove(output.getNumber()); } try { versions.logAndApply(compact.compaction.getEdit()); deleteObsoleteFiles(); } catch (IOException e) { // Compaction failed for some reason. Simply discard the work and try again later. // Discard any files we may have created during this failed compaction for (FileMetaData output : compact.outputs) { File file = new File(databaseDir, Filename.tableFileName(output.getNumber())); file.delete(); } compact.outputs.clear(); } }
private void cleanupCompaction(CompactionState compactionState) { Preconditions.checkState(mutex.isHeldByCurrentThread()); if (compactionState.builder != null) { compactionState.builder.abandon(); } else { Preconditions.checkArgument(compactionState.outfile == null); } for (FileMetaData output : compactionState.outputs) { pendingOutputs.remove(output.getNumber()); } }
private void deleteObsoleteFiles() { Preconditions.checkState(mutex.isHeldByCurrentThread()); // Make a set of all of the live files List<Long> live = newArrayList(this.pendingOutputs); for (FileMetaData fileMetaData : versions.getLiveFiles()) { live.add(fileMetaData.getNumber()); } for (File file : Filename.listFiles(databaseDir)) { FileInfo fileInfo = Filename.parseFileName(file); if (fileInfo == null) continue; long number = fileInfo.getFileNumber(); boolean keep = true; switch (fileInfo.getFileType()) { case LOG: keep = ((number >= versions.getLogNumber()) || (number == versions.getPrevLogNumber())); break; case DESCRIPTOR: // Keep my manifest file, and any newer incarnations' // (in case there is a race that allows other incarnations) keep = (number >= versions.getManifestFileNumber()); break; case TABLE: keep = live.contains(number); break; case TEMP: // Any temp files that are currently being written to must // be recorded in pending_outputs_, which is inserted into "live" keep = live.contains(number); break; case CURRENT: case DB_LOCK: case INFO_LOG: keep = true; break; } if (!keep) { if (fileInfo.getFileType() == FileType.TABLE) { tableCache.evict(number); } // todo info logging system needed // Log(options_.info_log, "Delete type=%d #%lld\n", // int(type), // static_cast < unsigned long long>(number)); file.delete(); } } }
private void backgroundCompaction() throws IOException { Preconditions.checkState(mutex.isHeldByCurrentThread()); compactMemTableInternal(); Compaction compaction; if (manualCompaction != null) { compaction = versions.compactRange( manualCompaction.level, new InternalKey(manualCompaction.begin, MAX_SEQUENCE_NUMBER, ValueType.VALUE), new InternalKey(manualCompaction.end, 0, ValueType.DELETION)); } else { compaction = versions.pickCompaction(); } if (compaction == null) { // no compaction } else if (manualCompaction == null && compaction.isTrivialMove()) { // Move file to next level Preconditions.checkState(compaction.getLevelInputs().size() == 1); FileMetaData fileMetaData = compaction.getLevelInputs().get(0); compaction.getEdit().deleteFile(compaction.getLevel(), fileMetaData.getNumber()); compaction.getEdit().addFile(compaction.getLevel() + 1, fileMetaData); versions.logAndApply(compaction.getEdit()); // log } else { CompactionState compactionState = new CompactionState(compaction); doCompactionWork(compactionState); cleanupCompaction(compactionState); } // manual compaction complete if (manualCompaction != null) { manualCompaction = null; } }