@Override public long toIndex(int cycle, long sequenceNumber) { return delegate.toIndex(cycle, sequenceNumber); }
private long nextIndexWithinFoundCycle(int nextCycle) { state = FOUND_CYCLE; if (direction == FORWARD) return queue.rollCycle().toIndex(nextCycle, 0); if (direction == BACKWARD) { try { long lastSequenceNumber0 = store().lastSequenceNumber(this); return queue.rollCycle().toIndex(nextCycle, lastSequenceNumber0); } catch (Exception e) { throw new AssertionError(e); } } else { throw new IllegalStateException("direction=" + direction); } }
@Override public long firstIndex() { // TODO - as discussed, peter is going find another way to do this as this solution // currently breaks tests in chronicle engine - see net.openhft.chronicle.engine.queue.LocalQueueRefTest int cycle = firstCycle(); if (cycle == Integer.MAX_VALUE) return Long.MAX_VALUE; return rollCycle().toIndex(cycle, 0); }
private static long findCycleLinearSearch(@NotNull NavigableSet<Long> cycles, Wire key, @NotNull Comparator<Wire> c, @NotNull ExcerptTailer tailer, @NotNull final ChronicleQueue queue) { final Iterator<Long> iterator = cycles.iterator(); if (!iterator.hasNext()) return -1; final RollCycle rollCycle = queue.rollCycle(); long prevIndex = iterator.next(); while (iterator.hasNext()) { final Long current = iterator.next(); final boolean b = tailer.moveToIndex(rollCycle.toIndex((int) (long) current, 0)); if (!b) return prevIndex; try (final DocumentContext dc = tailer.readingDocument()) { final int compare = c.compare(dc.wire(), key); if (compare == 0) return current; else if (compare > 0) return prevIndex; prevIndex = current; } } return prevIndex; }
private boolean tryWindBack(int cycle) { long count = queue.exceptsPerCycle(cycle); if (count <= 0) return false; RollCycle rollCycle = queue.rollCycle(); moveToIndexInternal(rollCycle.toIndex(cycle, count - 1)); this.state = FOUND_CYCLE; return true; }
@Override public long lastIndexAppended() { if (lastIndex != Long.MIN_VALUE) return lastIndex; if (lastPosition == Long.MIN_VALUE || wire == null) { throw new IllegalStateException("nothing has been appended, so there is no last index"); } try { long sequenceNumber = store.sequenceForPosition(this, lastPosition, true); long index = queue.rollCycle().toIndex(lastCycle, sequenceNumber); lastIndex(index); return index; } catch (Exception e) { throw Jvm.rethrow(e); } }
public long exceptsPerCycle(int cycle) { StoreTailer tailer = acquireTailer(); try { long index = rollCycle.toIndex(cycle, 0); if (tailer.moveToIndex(index)) { assert tailer.store != null && tailer.store.refCount() > 0; return tailer.store.lastSequenceNumber(tailer) + 1; } else { return -1; } } catch (StreamCorruptedException e) { throw new IllegalStateException(e); } finally { tailer.release(); } }
private void windBackCycle(int cycle) { if (tryWindBack(cycle - 1)) return; cycle--; for (long first = queue.firstCycle(); cycle >= first; cycle--) { if (tryWindBack(cycle)) return; } this.index(queue.rollCycle().toIndex(cycle, -1)); this.state = BEYOND_START_OF_CYCLE; }
private long approximateLastIndex(int cycle, SingleChronicleQueue queue, SingleChronicleQueueExcerpts.StoreTailer tailer) { try { WireStore wireStore = queue.storeForCycle(cycle, queue.epoch(), false); if (wireStore == null) { return noIndex; } long baseIndex = rollCycle.toIndex(cycle, 0); tailer.moveToIndex(baseIndex); long seq = wireStore.sequenceForPosition(tailer, Long.MAX_VALUE, false); long sequenceNumber = seq + 1; long index = rollCycle.toIndex(cycle, sequenceNumber); int cycleOfIndex = rollCycle.toCycle(index); if (cycleOfIndex != cycle) { throw new IllegalStateException( "Expected cycle " + cycle + " but got " + cycleOfIndex); } return index; } catch (StreamCorruptedException | UnrecoverableTimeoutException e) { throw new IllegalStateException(e); } }
private void resetPosition() throws UnrecoverableTimeoutException { try { if (store == null || wire == null) return; position(store.writePosition()); assert position == 0 || Wires.isReadyData(wire.bytes().readVolatileInt(position)); final long headerNumber = store.lastSequenceNumber(this); wire.headerNumber(queue.rollCycle().toIndex(cycle, headerNumber + 1) - 1); assert wire.headerNumber() != -1 || checkIndex(wire.headerNumber(), position); } catch (@NotNull BufferOverflowException | StreamCorruptedException e) { throw new AssertionError(e); } assert checkWritePositionHeaderNumber(); }
private long writeHeader(@NotNull Wire wire, int safeLength) { Bytes<?> bytes = wire.bytes(); // writePosition points at the last record in the queue, so we can just skip it and we're ready for write long pos = position; long lastPos = store.writePosition(); if (pos < lastPos) { // queue moved since we last touched it - recalculate header number try { wire.headerNumber(queue.rollCycle().toIndex(cycle, store.lastSequenceNumber(this))); } catch (StreamCorruptedException ex) { Jvm.warn().on(getClass(), "Couldn't find last sequence", ex); } } int header = bytes.readVolatileInt(lastPos); assert header != NOT_INITIALIZED; lastPos += lengthOf(bytes.readVolatileInt(lastPos)) + SPB_HEADER_SIZE; bytes.writePosition(lastPos); return wire.enterHeader(safeLength); }
@PackageLocal void incrementIndex() { RollCycle rollCycle = queue.rollCycle(); long index = this.index(); long seq = rollCycle.toSequenceNumber(index); int cycle = rollCycle.toCycle(index); seq += direction.add(); switch (direction) { case NONE: break; case FORWARD: // if it runs out of seq number it will flow over to tomorrows cycle file if (rollCycle.toSequenceNumber(seq) < seq) { cycle(cycle + 1); LOG.warn("we have run out of sequence numbers, so will start to write to " + "the next .cq4 file, the new cycle=" + cycle); seq = 0; } break; case BACKWARD: if (seq < 0) { windBackCycle(cycle); return; } break; } index0(rollCycle.toIndex(cycle, seq)); }
@NotNull @Override public final ExcerptTailer toStart() { assert direction != BACKWARD; final int firstCycle = queue.firstCycle(); if (firstCycle == Integer.MAX_VALUE) { state = UNINITIALISED; return this; } if (firstCycle != this.cycle) { // moves to the expected cycle boolean found = cycle(firstCycle); assert found || store == null; if (found) state = FOUND_CYCLE; } index(queue.rollCycle().toIndex(cycle, 0)); state = FOUND_CYCLE; if (wire() != null) { wire().bytes().readPosition(0); address = wire().bytes().addressForRead(0); } return this; }
@Override public long index() throws IORuntimeException { if (this.wire.headerNumber() == Long.MIN_VALUE) { try { wire.headerNumber(queue.rollCycle().toIndex(cycle, store.lastSequenceNumber(StoreAppender.this))); long headerNumber0 = wire.headerNumber(); assert (((AbstractWire) this.wire).isInsideHeader()); return isMetaData() ? headerNumber0 : headerNumber0 + 1; } catch (IOException e) { throw new IORuntimeException(e); } } return isMetaData() ? Long.MIN_VALUE : this.wire.headerNumber() + 1; }
private boolean beyondStartOfCycleBackward() throws StreamCorruptedException { // give the position of the last entry and // flag we want to count it even though we don't know if it will be meta data or not. boolean foundCycle = cycle(queue.rollCycle().toCycle(index())); if (foundCycle) { long lastSequenceNumberInThisCycle = store().sequenceForPosition(this, Long.MAX_VALUE, false); long nextIndex = queue.rollCycle().toIndex(this.cycle, lastSequenceNumberInThisCycle); moveToIndexInternal(nextIndex); state = FOUND_CYCLE; return true; } int cycle = queue.rollCycle().toCycle(index()); long nextIndex = nextIndexWithNextAvailableCycle(cycle); if (nextIndex != Long.MIN_VALUE) { moveToIndexInternal(nextIndex); state = FOUND_CYCLE; return true; } state = BEYOND_START_OF_CYCLE; return false; }
@Test public void testHeaderIndexReadAtIndex() { try (final ChronicleQueue queue = builder(getTmpDir(), this.wireType) .build()) { final ExcerptAppender appender = queue.acquireAppender(); final int cycle = appender.cycle(); // create 100 documents for (int i = 0; i < 100; i++) { final int j = i; appender.writeDocument(wire -> wire.write(() -> "key").text("value=" + j)); } final ExcerptTailer tailer = queue.createTailer(); assertTrue(tailer.moveToIndex(queue.rollCycle().toIndex(cycle, 0))); StringBuilder sb = new StringBuilder(); tailer.readDocument(wire -> wire.read(() -> "key").text(sb)); Assert.assertEquals("value=0", sb.toString()); } }
private boolean inACycleNotForward() { Jvm.optionalSafepoint(); if (!moveToIndexInternal(index())) { try { Jvm.optionalSafepoint(); // after toEnd() call, index is past the end of the queue // so try to go back one (to the last record in the queue) if ((int) queue.rollCycle().toSequenceNumber(index()) < 0) { long lastSeqNum = store.lastSequenceNumber(this); if (lastSeqNum == -1) { windBackCycle(cycle); return moveToIndexInternal(index()); } return moveToIndexInternal(queue.rollCycle().toIndex(cycle, lastSeqNum)); } if (!moveToIndexInternal(index() - 1)) { Jvm.optionalSafepoint(); return false; } } catch (Exception e) { // can happen if index goes negative Jvm.optionalSafepoint(); return false; } } Jvm.optionalSafepoint(); return true; }
@Test public void test() throws IOException { try (final RollingChronicleQueue queue = SingleChronicleQueueBuilder .binary(getTmpDir()) .testBlockSize() .wireType(this.wireType) .build()) { final ExcerptAppender appender = queue.acquireAppender(); for (int i = 0; i < 5; i++) { final int n = i; appender.writeDocument( w -> w.write(TestKey.test).int32(n)); final int cycle = queue.lastCycle(); long index0 = queue.rollCycle().toIndex(cycle, n); long indexA = appender.lastIndexAppended(); accessHexEquals(index0, indexA); } } }
@Test public void testAppendAndReadAtIndex() { try (final ChronicleQueue queue = builder(getTmpDir(), this.wireType) .rollCycle(TEST2_DAILY) .build()) { final ExcerptAppender appender = queue.acquireAppender(); appender.cycle(); for (int i = 0; i < 5; i++) { final int n = i; appender.writeDocument(w -> w.write(TestKey.test).int32(n)); assertEquals(i, queue.rollCycle().toSequenceNumber(appender.lastIndexAppended())); } final ExcerptTailer tailer = queue.createTailer(); for (int i = 0; i < 5; i++) { final long index = queue.rollCycle().toIndex(appender.cycle(), i); assertTrue(tailer.moveToIndex(index)); final int n = i; assertTrue(tailer.readDocument(r -> assertEquals(n, queue.rollCycle().toSequenceNumber(r.read(TestKey.test) .int32())))); long index2 = tailer.index(); long sequenceNumber = queue.rollCycle().toSequenceNumber(index2); assertEquals(n + 1, sequenceNumber); } } }
@Test public void testAppendAndRead() { try (final ChronicleQueue queue = builder(getTmpDir(), this.wireType) .build()) { final ExcerptAppender appender = queue.acquireAppender(); final int cycle = appender.cycle(); for (int i = 0; i < 10; i++) { final int n = i; appender.writeDocument(w -> w.write(TestKey.test).int32(n)); assertEquals(n, queue.rollCycle().toSequenceNumber(appender.lastIndexAppended())); } final ExcerptTailer tailer = queue.createTailer(); // Sequential read for (int i = 0; i < 10; i++) { final int n = i; assertTrue(tailer.readDocument(r -> assertEquals(n, r.read(TestKey.test).int32()))); assertEquals(n + 1, queue.rollCycle().toSequenceNumber(tailer.index())); } // Random read for (int i = 0; i < 10; i++) { final int n = i; assertTrue("n: " + n, tailer.moveToIndex(queue.rollCycle().toIndex(cycle, n))); assertTrue("n: " + n, tailer.readDocument(r -> assertEquals(n, r.read(TestKey.test).int32()))); assertEquals(n + 1, queue.rollCycle().toSequenceNumber(tailer.index())); } } }