private void sealActiveChunk(RollingSegmentHandle handle) throws StreamSegmentException { SegmentHandle activeChunk = handle.getActiveChunkHandle(); SegmentChunk last = handle.lastChunk(); if (activeChunk != null && !last.isSealed()) { this.baseStorage.seal(activeChunk); handle.setActiveChunkHandle(null); last.markSealed(); log.debug("Sealed active SegmentChunk '{}' for '{}'.", activeChunk.getSegmentName(), handle.getSegmentName()); } }
private void unsealLastChunkIfNecessary(RollingSegmentHandle handle) throws StreamSegmentException { SegmentChunk last = handle.lastChunk(); if (last == null || !last.isSealed()) { // Nothing to do. return; } SegmentHandle activeChunk = handle.getActiveChunkHandle(); boolean needsHandleUpdate = activeChunk == null; if (needsHandleUpdate) { // We didn't have a pointer to the active chunk's Handle because the chunk was sealed before open-write. activeChunk = this.baseStorage.openWrite(last.getName()); } try { this.baseStorage.unseal(activeChunk); } catch (UnsupportedOperationException e) { log.warn("Unable to unseal SegmentChunk '{}' since base storage does not support unsealing.", last); return; } last.markUnsealed(); if (needsHandleUpdate) { activeChunk = this.baseStorage.openWrite(last.getName()); handle.setActiveChunkHandle(activeChunk); } log.debug("Unsealed active SegmentChunk '{}' for '{}'.", activeChunk.getSegmentName(), handle.getSegmentName()); }
@Override public void write(SegmentHandle handle, long offset, InputStream data, int length) throws StreamSegmentException { val h = asWritableHandle(handle); ensureNotDeleted(h); ensureNotSealed(h); ensureOffset(h, offset); long traceId = LoggerHelpers.traceEnter(log, "write", handle, offset, length); // We run this in a loop because we may have to split the write over multiple SegmentChunks in order to avoid exceeding // any SegmentChunk's maximum length. int bytesWritten = 0; while (bytesWritten < length) { if (h.getActiveChunkHandle() == null || h.lastChunk().getLength() >= h.getRollingPolicy().getMaxLength()) { rollover(h); } SegmentChunk last = h.lastChunk(); int writeLength = (int) Math.min(length - bytesWritten, h.getRollingPolicy().getMaxLength() - last.getLength()); assert writeLength > 0 : "non-positive write length"; long chunkOffset = offset + bytesWritten - last.getStartOffset(); this.baseStorage.write(h.getActiveChunkHandle(), chunkOffset, data, writeLength); last.increaseLength(writeLength); bytesWritten += writeLength; } LoggerHelpers.traceLeave(log, "write", traceId, handle, offset, bytesWritten); }
this.baseStorage.concat(target.getActiveChunkHandle(), target.lastChunk().getLength(), lastSource.getName()); target.lastChunk().increaseLength(lastSource.getLength()); if (source.getHeaderHandle() != null) {
/** * Tests the ability of the Handle to refresh based on information from another similar handle. */ @Test public void testRefresh() { val headerHandle = new TestHandle(HEADER_NAME, true); val target = new RollingSegmentHandle(headerHandle, DEFAULT_ROLLING_POLICY, Collections.singletonList(new SegmentChunk("s1", 0L))); val source = new RollingSegmentHandle(headerHandle, DEFAULT_ROLLING_POLICY, Arrays.asList( new SegmentChunk("s1", 0L), new SegmentChunk("s2", 100L))); source.chunks().get(0).setLength(100); source.markSealed(); source.setHeaderLength(1000); source.setActiveChunkHandle(new TestHandle(source.lastChunk().getName(), false)); target.refresh(source); Assert.assertEquals("Unexpected getHeaderLength()", source.getHeaderLength(), target.getHeaderLength()); AssertExtensions.assertListEquals("Unexpected chunks()", source.chunks(), target.chunks(), Object::equals); Assert.assertTrue("Unexpected isSealed.", target.isSealed()); Assert.assertNull("Not expecting any ActiveSegmentHandle to be copied.", target.getActiveChunkHandle()); }
ex -> ex instanceof IllegalArgumentException); Assert.assertEquals("Not expecting any SegmentChunks to be added.", 0, h.chunks().size()); Assert.assertNull("Not expecting the Active SegmentChunk handle to be set.", h.getActiveChunkHandle());
Assert.assertEquals("Unexpected value from getActiveChunkHandle.", activeHandle, h.getActiveChunkHandle());