@Override public SegmentHandle openRead(String segmentName) throws StreamSegmentException { long traceId = LoggerHelpers.traceEnter(log, "openRead", segmentName); val handle = openHandle(segmentName, true); LoggerHelpers.traceLeave(log, "openRead", traceId, handle); return handle; }
private void rollover(RollingSegmentHandle handle) throws StreamSegmentException { Preconditions.checkArgument(handle.getHeaderHandle() != null, "Cannot rollover a Segment with no header."); Preconditions.checkArgument(!handle.isReadOnly(), "Cannot rollover using a read-only handle."); Preconditions.checkArgument(!handle.isSealed(), "Cannot rollover a Sealed Segment."); log.debug("Rolling over '{}'.", handle); sealActiveChunk(handle); try { createChunk(handle); } catch (StreamSegmentExistsException ex) { // It may be possible that a concurrent rollover request using a different handle (either from this instance // or another) has already created the new chunk. Refresh the handle and try again. This is usually the case // with concurrent Storage instances trying to modify the same segment at the same time. int chunkCount = handle.chunks().size(); handle.refresh(openHandle(handle.getSegmentName(), false)); if (chunkCount == handle.chunks().size()) { // Nothing changed; re-throw the exception. throw ex; } else { // We've just refreshed the handle and picked up the latest chunk. Move on. log.warn("Aborted rollover due to concurrent rollover detected ('{}').", handle); } } }
private void ensureOffset(RollingSegmentHandle handle, long offset) throws StreamSegmentException { if (offset != handle.length()) { // Force-refresh the handle to make sure it is still in sync with reality. Make sure we open a read handle // so that we don't force any sort of fencing during this process. val refreshedHandle = openHandle(handle.getSegmentName(), true); handle.refresh(refreshedHandle); log.debug("Handle refreshed: {}.", handle); if (offset != handle.length()) { // Still in disagreement; throw exception. throw new BadOffsetException(handle.getSegmentName(), handle.length(), offset); } } }
@Override public SegmentHandle openWrite(String segmentName) throws StreamSegmentException { long traceId = LoggerHelpers.traceEnter(log, "openWrite", segmentName); val handle = openHandle(segmentName, false); // Finally, open the Active SegmentChunk for writing. SegmentChunk last = handle.lastChunk(); if (last != null && !last.isSealed()) { val activeHandle = this.baseStorage.openWrite(last.getName()); handle.setActiveChunkHandle(activeHandle); } LoggerHelpers.traceLeave(log, "openWrite", traceId, handle); return handle; }