@Override public int currentCycle(final RollCycle rollCycle, final TimeProvider timeProvider, final long offsetMillis) { return rollCycle.current(timeProvider, offsetMillis); } }
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); } }
@NotNull @Override public String toString() { long index = index(); return "StoreTailer{" + "index sequence=" + queue.rollCycle().toSequenceNumber(index) + ", index cycle=" + queue.rollCycle().toCycle(index) + ", store=" + store + ", queue=" + queue + '}'; }
@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)); }
@Override public long toIndex(int cycle, long sequenceNumber) { return delegate.toIndex(cycle, sequenceNumber); }
@Override public int toCycle(long index) { return delegate.toCycle(index); } }
@NotNull final RollingChronicleQueue chronicleQueue = (RollingChronicleQueue) this.chronicleQueue; RollCycle rollCycle = chronicleQueue.rollCycle(); int currentIndex = rollCycle.current(SystemTimeProvider.INSTANCE, 0); final int cycle = rollCycle.toCycle(currentIndex); fromIndex0 = rollCycle.toIndex(cycle, 0); } else if (fromIndex0 == 0) { fromIndex0 = endIndex;
@Override public long toSequenceNumber(long index) { return delegate.toSequenceNumber(index); }
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; }
@Override public int defaultIndexSpacing() { return delegate.defaultIndexSpacing(); }
/** * @param rollCycle the current rollCycle * @param wireType the wire type that is being used * @param mappedBytes used to mapped the data store file * @param indexCount the number of entries in each index. * @param indexSpacing the spacing between indexed entries. */ public SingleChronicleQueueStore(@NotNull RollCycle rollCycle, @NotNull final WireType wireType, @NotNull MappedBytes mappedBytes, int indexCount, int indexSpacing) { this.mappedBytes = mappedBytes; this.mappedFile = mappedBytes.mappedFile(); this.refCount = ReferenceCounter.onReleased(this::onCleanup); indexCount = Maths.nextPower2(indexCount, 8); indexSpacing = Maths.nextPower2(indexSpacing, 1); this.indexing = new SCQIndexing(wireType, indexCount, indexSpacing); this.indexing.writePosition = this.writePosition = wireType.newTwoLongReference().get(); this.indexing.sequence = this.sequence = new RollCycleEncodeSequence(writePosition, rollCycle.defaultIndexCount(), rollCycle.defaultIndexSpacing()); }
@Test public void testSomeMessages() { try (ChronicleQueue chronicle = builder(getTmpDir(), wireType) .rollCycle(TEST2_DAILY) .build()) { ExcerptAppender appender = chronicle.acquireAppender(); ExcerptTailer tailer = chronicle.createTailer(); int entries = chronicle.rollCycle().defaultIndexSpacing() * 2 + 2; for (long i = 0; i < entries; i++) { long finalI = i; appender.writeDocument(w -> w.writeEventName("hello").int64(finalI)); long seq = chronicle.rollCycle().toSequenceNumber(appender.lastIndexAppended()); assertEquals(i, seq); // System.out.println(chronicle.dump()); tailer.readDocument(w -> w.read().int64(finalI, (a, b) -> Assert.assertEquals((long) a, b))); } } }
@Override public int length() { return delegate.length(); }
@Override public int defaultIndexCount() { return delegate.defaultIndexCount(); }
private void validateRollCycle(File metapath) { if (!metapath.exists()) { // no metadata, so we need to check if there're cq4 files and if so try to validate roll cycle // the code is slightly brutal and crude but should work for most cases. It will NOT work if files were created with // the following cycles: LARGE_HOURLY_SPARSE LARGE_HOURLY_XSPARSE LARGE_DAILY XLARGE_DAILY HUGE_DAILY HUGE_DAILY_XSPARSE // for such cases user MUST use correct roll cycle when creating the queue String[] list = path.list((d, name) -> name.endsWith(SingleChronicleQueue.SUFFIX)); if (list != null && list.length > 0) { String filename = list[0]; if (rollCycle().format().length() + 4 != filename.length()) { // probably different roll cycle used overrideRollCycleForFileNameLength(filename.length() - 4); } } } }
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); } }
long sequenceNotSet = rollCycle.toSequenceNumber(-1); if (rollCycle.toSequenceNumber(fromIndex) == sequenceNotSet) { result++; fromIndex++; if (rollCycle.toSequenceNumber(toIndex) == sequenceNotSet) { result--; toIndex++; int lowerCycle = rollCycle.toCycle(fromIndex); int upperCycle = rollCycle.toCycle(toIndex); long upperSeqNum = rollCycle.toSequenceNumber(toIndex); long lowerSeqNum = rollCycle.toSequenceNumber(fromIndex);
private boolean indexIsCloseToAndAheadOfLastIndexMove( final long index, final TailerState state, final TailerDirection direction, final ChronicleQueue queue) { return lastMovedToIndex != Long.MIN_VALUE && index - lastMovedToIndex < INDEXING_LINEAR_SCAN_THRESHOLD && state == FOUND_CYCLE && direction == directionAtLastMoveTo && queue.rollCycle().toCycle(index) == queue.rollCycle().toCycle(lastMovedToIndex) && index > lastMovedToIndex; }