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 writeLevel0Table(MemTable mem, VersionEdit edit, Version base) throws IOException { Preconditions.checkState(mutex.isHeldByCurrentThread()); // skip empty mem table if (mem.isEmpty()) { return; } // write the memtable to a new sstable long fileNumber = versions.getNextFileNumber(); pendingOutputs.add(fileNumber); mutex.unlock(); FileMetaData meta; try { meta = buildTable(mem, fileNumber); } finally { mutex.lock(); } pendingOutputs.remove(fileNumber); // Note that if file size is zero, the file has been deleted and // should not be added to the manifest. int level = 0; if (meta != null && meta.getFileSize() > 0) { Slice minUserKey = meta.getSmallest().getUserKey(); Slice maxUserKey = meta.getLargest().getUserKey(); if (base != null) { level = base.pickLevelForMemTableOutput(minUserKey, maxUserKey); } edit.addFile(level, meta); } }
private FileMetaData getFileContentInfo(File file) { try { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("redirect", "meta"); ClientResponse resp = getRootApiWebResource() .path("files") .path(String.valueOf(file.getId())) .path("content") .queryParams(queryParams) .accept(MediaType.APPLICATION_OCTET_STREAM) .accept(MediaType.TEXT_HTML) .accept(MediaType.APPLICATION_XHTML_XML) .get(ClientResponse.class); String sResp = resp.getEntity(String.class); FileMetaData fileInfo = mapper.readValue( mapper.readValue(sResp, JsonNode.class).findPath(RESPONSE).toString(), FileMetaData.class); logger.info(fileInfo.toString()); return fileInfo; } catch (BaseSpaceException bs) { throw bs; } catch (Throwable t) { throw new RuntimeException(t); } }
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 InputStream getInputStreamInternal(File file, long start, long end, boolean refreshMeta) { try { FileMetaData fileInfo = fileToUriMap.get(file.getId()); if (refreshMeta || (fileInfo == null || new Date().after(fileInfo.getExpires()))) { fileInfo = getFileContentInfo(file); fileToUriMap.put(file.getId(), fileInfo); } InputStream in = getClient() .resource(new URI(fileInfo.getHrefContent())) .accept(MediaType.APPLICATION_OCTET_STREAM) .accept(MediaType.TEXT_HTML) .accept(MediaType.APPLICATION_XHTML_XML) .header("Range", "bytes=" + start + "-" + end) .get(InputStream.class); return in; } catch (BaseSpaceException bs) { throw bs; } catch (Throwable t) { throw new RuntimeException(t); } }
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; } }