protected TracedIOOperation(ILSMIOOperation ioOp, ITracer tracer, long traceCategory) { this.ioOp = ioOp; this.tracer = tracer; this.ioOpType = ioOp.getIOOpertionType(); this.traceCategory = traceCategory; }
@Override public void scheduleOperation(ILSMIOOperation operation) { switch (operation.getIOOpertionType()) { case FLUSH: scheduleFlush(operation); break; case MERGE: executor.submit(operation); break; case NOOP: return; default: // this should never happen // just guard here to avoid silent failures in case of future extensions throw new IllegalArgumentException("Unknown operation type " + operation.getIOOpertionType()); } }
@Override public void operationFailed(ILSMIOOperation operation, Throwable t) { LOGGER.error("Operation {} has failed", operation, t); if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { ExitUtil.halt(ExitUtil.EC_FLUSH_FAILED); } } }
private void before(ILSMIOOperation operation) throws InterruptedException { String id = operation.getIndexIdentifier(); if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { synchronized (runningFlushOperations) { while (true) { if (failedGroups.containsKey(id)) { operation.setStatus(LSMIOOperationStatus.FAILURE); operation.setFailure(new RuntimeException("Operation group " + id + " has permanently failed", failedGroups.get(id))); return; } if (runningFlushOperations.containsKey(id)) { runningFlushOperations.wait(); } else { runningFlushOperations.put(id, operation); break; } } } } } }
@Override public void afterFinalize(ILSMIOOperation operation) throws HyracksDataException { if (operation.getStatus() == LSMIOOperationStatus.FAILURE) { return; } if (operation.getIOOpertionType() != LSMIOOperationType.LOAD && operation.getAccessor().getOpContext().getOperation() == IndexOperation.DELETE_COMPONENTS) { deleteComponentsFromCheckpoint(operation); } else if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH || operation.getIOOpertionType() == LSMIOOperationType.LOAD) { addComponentToCheckpoint(operation); } }
@Override public synchronized void scheduled(ILSMIOOperation operation) throws HyracksDataException { dsInfo.declareActiveIOOperation(); if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { pendingFlushes++; FlushOperation flush = (FlushOperation) operation; Map<String, Object> map = operation.getAccessor().getOpContext().getParameters(); Long flushLsn = (Long) map.get(KEY_FLUSH_LOG_LSN); map.put(KEY_FIRST_LSN, firstLsnForCurrentMemoryComponent); map.put(KEY_FLUSHED_COMPONENT_ID, flush.getFlushingComponent().getId()); componentIds.add((ILSMComponentId) map.get(KEY_NEXT_COMPONENT_ID)); firstLsnForCurrentMemoryComponent = flushLsn; // Advance the first lsn for new component } }
private void doAfterExecute(ILSMIOOperation executedOp, Throwable t) throws HyracksDataException { final boolean failed = (t != null) || (executedOp.getStatus() == LSMIOOperationStatus.FAILURE); if (failed) { fail(executedOp, t != null ? t : executedOp.getFailure()); } if (!failed || executedOp.getIOOpertionType() != LSMIOOperationType.FLUSH) { executedOp.complete(); // destroy if merge or successful flush } if (executedOp.getIOOpertionType() == LSMIOOperationType.FLUSH) { String id = executedOp.getIndexIdentifier(); synchronized (this) { runningFlushOperations.remove(id); if (waitingFlushOperations.containsKey(id)) { ILSMIOOperation op = waitingFlushOperations.get(id).poll(); if (op != null) { scheduler.scheduleOperation(op); } else { waitingFlushOperations.remove(id); } } } } }
private void fail(ILSMIOOperation executedOp, Throwable t) throws HyracksDataException { callback.operationFailed(executedOp, t); if (executedOp.getIOOpertionType() == LSMIOOperationType.FLUSH) { executedOp.complete(); // Doesn't make sense to process further flush requests... Mark the operation group permanently failed // Fail other scheduled operations synchronized (this) { String id = executedOp.getIndexIdentifier(); failedGroups.put(id, t); runningFlushOperations.remove(id); if (waitingFlushOperations.containsKey(id)) { Deque<ILSMIOOperation> ops = waitingFlushOperations.remove(id); ILSMIOOperation next = ops.poll(); while (next != null) { next.setFailure(new RuntimeException("Operation group " + id + " has permanently failed", t)); next.setStatus(LSMIOOperationStatus.FAILURE); next.complete(); next = ops.poll(); } } } } } }
private void deleteComponentsFromCheckpoint(ILSMIOOperation operation) throws HyracksDataException { // component was deleted... if a flush, do nothing.. if a merge, must update the checkpoint file if (operation.getIOOpertionType() == LSMIOOperationType.MERGE) { // Get component id of the last disk component LSMComponentId mostRecentComponentId = getMostRecentComponentId(operation.getAccessor().getOpContext().getComponentsToBeMerged()); // Update the checkpoint file FileReference target = operation.getTarget(); final ResourceReference ref = ResourceReference.of(target.getAbsolutePath()); indexCheckpointManagerProvider.get(ref).setLastComponentId(mostRecentComponentId.getMaxId()); } else if (operation.getIOOpertionType() != LSMIOOperationType.FLUSH) { throw new IllegalStateException("Unexpected IO operation: " + operation.getIOOpertionType()); } }
private void after(ILSMIOOperation operation) { if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { synchronized (runningFlushOperations) { runningFlushOperations.remove(operation.getIndexIdentifier()); if (operation.getStatus() == LSMIOOperationStatus.FAILURE) { failedGroups.putIfAbsent(operation.getIndexIdentifier(), operation.getFailure()); } operation.complete(); runningFlushOperations.notifyAll(); } } else { operation.complete(); } }
@Override public synchronized void completed(ILSMIOOperation operation) { if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { pendingFlushes--; if (operation.getStatus() == LSMIOOperationStatus.SUCCESS) { Map<String, Object> map = operation.getAccessor().getOpContext().getParameters(); persistenceLsn = pendingFlushes == 0 ? firstLsnForCurrentMemoryComponent : (Long) map.get(KEY_FLUSH_LOG_LSN); } } dsInfo.undeclareActiveIOOperation(); }
private void addComponentToCheckpoint(ILSMIOOperation operation) throws HyracksDataException { // will always update the checkpoint file even if no new component was created FileReference target = operation.getTarget(); Map<String, Object> map = operation.getParameters(); final Long lsn = operation.getIOOpertionType() == LSMIOOperationType.FLUSH ? (Long) map.get(KEY_FLUSH_LOG_LSN) : 0L; final LSMComponentId id = (LSMComponentId) map.get(KEY_FLUSHED_COMPONENT_ID); final ResourceReference ref = ResourceReference.of(target.getAbsolutePath()); final long componentSequence = IndexComponentFileReference.of(ref.getName()).getSequenceEnd(); indexCheckpointManagerProvider.get(ref).flushed(componentSequence, lsn, id.getMaxId()); }
@Override public LSMIOOperationStatus call() throws HyracksDataException { final String name = getTarget().getRelativePath(); final long tid = tracer.durationB(name, traceCategory, null); try { return ioOp.call(); } finally { tracer.durationE(ioOp.getIOOpertionType().name().toLowerCase(), traceCategory, tid, "{\"size\":" + getTarget().getFile().length() + ", \"path\": \"" + ioOp.getTarget().getRelativePath() + "\"}"); } }
public static ILSMIOOperation wrap(final ILSMIOOperation ioOp, final ITracer tracer) { final String ioOpName = ioOp.getIOOpertionType().name().toLowerCase(); final long traceCategory = tracer.getRegistry().get(TraceUtils.INDEX_IO_OPERATIONS); if (tracer.isEnabled(traceCategory)) { tracer.instant("schedule-" + ioOpName, traceCategory, Scope.p, "{\"path\": \"" + ioOp.getTarget().getRelativePath() + "\"}"); return new TracedIOOperation(ioOp, tracer, traceCategory); } return ioOp; }
@Override public void afterFinalize(ILSMIOOperation op) throws HyracksDataException { lsmBtree.afterIoFinalizeCalled(); super.afterFinalize(op); synchronized (TestLsmIoOpCallbackFactory.this) { if (op.getNewComponent() != null) { if (op.getNewComponent() == EmptyComponent.INSTANCE) { if (op.getIOOpertionType() == LSMIOOperationType.FLUSH) { rollbackFlushes++; } else { rollbackMerges++; } } else { if (op.getIOOpertionType() == LSMIOOperationType.FLUSH) { completedFlushes++; } else { completedMerges++; } } } else { recordFailure(op.getIOOpertionType()); } TestLsmIoOpCallbackFactory.this.notifyAll(); } lsmBtree.afterIoFinalizeReturned(); }
@Override public void afterOperation(ILSMIOOperation operation) throws HyracksDataException { if (operation.getStatus() == LSMIOOperationStatus.FAILURE) { return; } if (operation.getIOOpertionType() == LSMIOOperationType.LOAD) { Map<String, Object> map = operation.getParameters(); putComponentIdIntoMetadata(operation.getNewComponent(), (LSMComponentId) map.get(KEY_FLUSHED_COMPONENT_ID)); } else if (operation.getIOOpertionType() == LSMIOOperationType.FLUSH) { Map<String, Object> map = operation.getParameters(); putLSNIntoMetadata(operation.getNewComponent(), (Long) map.get(KEY_FLUSH_LOG_LSN)); putComponentIdIntoMetadata(operation.getNewComponent(), ((FlushOperation) operation).getFlushingComponent().getId()); } else if (operation.getIOOpertionType() == LSMIOOperationType.MERGE) { List<ILSMDiskComponent> mergedComponents = operation.getAccessor().getOpContext().getComponentsToBeMerged(); putLSNIntoMetadata(operation.getNewComponent(), mergedComponents); putComponentIdIntoMetadata(operation.getNewComponent(), mergedComponents); LongPointable markerLsn = LongPointable.FACTORY.createPointable(ComponentUtils.getLong(mergedComponents.get(0).getMetadata(), ComponentUtils.MARKER_LSN_KEY, ComponentUtils.NOT_FOUND, buffer)); operation.getNewComponent().getMetadata().put(ComponentUtils.MARKER_LSN_KEY, markerLsn); } }
@Override public ChainedLSMDiskComponentBulkLoader createBulkLoader(ILSMIOOperation operation, float fillFactor, boolean verifyInput, long numElementsHint, boolean checkIfEmptyIndex, boolean withFilter, boolean cleanupEmptyComponent) throws HyracksDataException { ChainedLSMDiskComponentBulkLoader chainedBulkLoader = new ChainedLSMDiskComponentBulkLoader(operation, this, cleanupEmptyComponent); if (withFilter && getLsmIndex().getFilterFields() != null) { chainedBulkLoader.addBulkLoader(createFilterBulkLoader()); } IChainedComponentBulkLoader indexBulkloader = operation.getIOOpertionType() == LSMIOOperationType.MERGE ? createMergeIndexBulkLoader(fillFactor, verifyInput, numElementsHint, checkIfEmptyIndex) : createIndexBulkLoader(fillFactor, verifyInput, numElementsHint, checkIfEmptyIndex); chainedBulkLoader.addBulkLoader(indexBulkloader); return chainedBulkLoader; }
public void doIo(ILSMIOOperation operation) { try { operation.getCallback().beforeOperation(operation); ILSMDiskComponent newComponent = operation.getIOOpertionType() == LSMIOOperationType.FLUSH ? lsmIndex.flush(operation) : lsmIndex.merge(operation); operation.setNewComponent(newComponent); operation.setFailure(e); if (LOGGER.isErrorEnabled()) { LOGGER.log(Level.ERROR, "{} operation failed on {}", operation.getIOOpertionType(), lsmIndex, e); operation.setFailure(th); if (LOGGER.isErrorEnabled()) { LOGGER.log(Level.ERROR, "{} operation.afterFinalize failed on {}", operation.getIOOpertionType(), lsmIndex, th);