use of net.openhft.chronicle.wire.DocumentContext in project Chronicle-Queue by OpenHFT.
the class AppenderLockOnlyAppliesToFileTest method concurrentLockItUp.
/*
Failed tests:
AppenderLockOnlyAppliesToFileTest.concurrentLockItUp:59 Writer thread completed before timeout
*/
@Ignore("fails too often")
@Test
public void concurrentLockItUp() throws InterruptedException {
final AtomicReference<String> writerQueueFile = new AtomicReference<>();
final File path = DirectoryUtils.tempDir(this.getClass().getSimpleName());
final SingleChronicleQueueBuilder builder = ChronicleQueueBuilder.single(path).sourceId(1).rollCycle(ROLL_CYCLE).timeoutMS(TIMEOUT_MS);
final String initialFile;
final DocumentContext initialContext = builder.build().acquireAppender().writingDocument();
initialContext.wire().writeText("abcd");
initialFile = getFilename(initialContext);
// don't close context
final long afterInitialWrite = System.currentTimeMillis();
final CountDownLatch writerStarted = new CountDownLatch(1);
final CountDownLatch writerFinished = new CountDownLatch(1);
Thread writerThread = new Thread(() -> {
ExcerptAppender appender = builder.build().acquireAppender();
writerStarted.countDown();
// wait for less than timeout and more than roll
Jvm.pause(WAIT_FOR_ROLL_MS);
try (@NotNull DocumentContext context = appender.writingDocument()) {
// should not have been held up by locking
writerQueueFile.set(getFilename(context));
Wire wire = context.wire();
wire.writeText("hello");
writerFinished.countDown();
}
});
writerThread.start();
assertTrue("Writer thread not started", writerStarted.await(1, TimeUnit.SECONDS));
assertTrue("Writer thread completed before timeout", writerFinished.await(WAIT_FOR_ROLL_MS + 50, TimeUnit.MILLISECONDS));
assertFalse("Threads wrote to different queue cycles, so no locking occurred", initialFile.equals(writerQueueFile.get()));
assertTrue("We are within timeout", System.currentTimeMillis() < afterInitialWrite + TIMEOUT_MS);
ExcerptTailer tailer = builder.build().createTailer();
// this call to readingDocument waits for timeout and logs out ".... resetting header after timeout ...."
try (DocumentContext rd = tailer.readingDocument()) {
assertFalse("We are outside timeout", System.currentTimeMillis() < afterInitialWrite + TIMEOUT_MS);
assertTrue("Something was written", rd.isPresent());
String value = rd.wire().readText();
assertEquals("the first (locked) write is lost", "hello", value);
}
try (DocumentContext rd = tailer.readingDocument()) {
assertFalse("Should be only one message in the queue", rd.isPresent());
}
try {
initialContext.close();
fail("close should have thrown");
} catch (IllegalStateException e) {
// expected for close to throw
}
}
use of net.openhft.chronicle.wire.DocumentContext in project Chronicle-Queue by OpenHFT.
the class DetectNotReadyEntriesTest method testDeadEntries.
@Test
public void testDeadEntries() throws FileNotFoundException {
// TODO FIX.
if (OS.isWindows())
return;
File dir = new File(OS.TARGET, getClass().getSimpleName() + "-" + System.nanoTime());
dir.mkdir();
MappedBytes bytes = MappedBytes.mappedBytes(new File(dir, "19700101" + SingleChronicleQueue.SUFFIX), 64 << 10);
Wire wire = new BinaryWire(bytes);
try (DocumentContext dc = wire.writingDocument(true)) {
dc.wire().writeEventName(() -> "header").typePrefix(SingleChronicleQueueStore.class).marshallable(w -> {
w.write(() -> "wireType").object(WireType.BINARY);
w.write(() -> "writePosition").int64forBinding(288 + 4 + 17);
w.write(() -> "roll").typedMarshallable(new SCQRoll(RollCycles.DAILY, 0));
w.write(() -> "indexing").typedMarshallable(new SCQIndexing(WireType.BINARY, 32 << 10, 32));
w.write(() -> "lastAcknowledgedIndexReplicated").int64forBinding(0);
});
}
long pos = wire.bytes().writePosition();
try (DocumentContext dc = wire.writingDocument(false)) {
dc.wire().write("test").text("Hello World");
}
assertEquals(17, wire.bytes().readInt(pos));
// make it incomplete, note that the length is removed,
// since writing a length into an incomplete excerpt is not allowed
wire.bytes().writeInt(pos, Wires.NOT_COMPLETE);
assertEquals("--- !!meta-data #binary\n" + "header: !SCQStore {\n" + " wireType: !WireType BINARY,\n" + " writePosition: 309,\n" + " roll: !SCQSRoll {\n" + " length: !int 86400000,\n" + " format: yyyyMMdd,\n" + " epoch: 0\n" + " },\n" + " indexing: !SCQSIndexing {\n" + " indexCount: !int 32768,\n" + " indexSpacing: 32,\n" + " index2Index: 0,\n" + " lastIndex: 0\n" + " },\n" + " lastAcknowledgedIndexReplicated: 0\n" + "}\n" + "# position: 288, header: -1 or 0\n" + "--- !!not-ready-data! #binary\n" + "...\n" + "# 17 bytes remaining\n", Wires.fromSizePrefixedBlobs(bytes.readPosition(0)));
bytes.release();
try (SingleChronicleQueue queue = SingleChronicleQueueBuilder.binary(dir).testBlockSize().build()) {
queue.acquireAppender().writeText("Bye for now");
}
try {
IOTools.shallowDeleteDirWithFiles(dir.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
use of net.openhft.chronicle.wire.DocumentContext in project Chronicle-Queue by OpenHFT.
the class DocumentOrderingTest method multipleThreadsMustWaitUntilPreviousCycleFileIsCompleted.
@Test
public void multipleThreadsMustWaitUntilPreviousCycleFileIsCompleted() throws Exception {
Assume.assumeFalse("ordering/atomicity is not guaranteed when using progressOnContention = true," + "as multiple threads can be concurrently executing within a queue's " + "document context when the queue head is contented", progressOnContention);
final File dir = DirectoryUtils.tempDir("document-ordering");
// must be different instances of queue to work around synchronization on acquireStore()
try (final SingleChronicleQueue queue = builder(dir, 5_000L).build();
final SingleChronicleQueue queue2 = builder(dir, 5_000L).build();
final SingleChronicleQueue queue3 = builder(dir, 5_000L).build();
final SingleChronicleQueue queue4 = builder(dir, 5_000L).build()) {
final ExcerptAppender excerptAppender = queue.acquireAppender();
final Future<RecordInfo> firstWriter;
final Future<RecordInfo> secondWriter;
final Future<RecordInfo> thirdWriter;
try (final DocumentContext documentContext = excerptAppender.writingDocument()) {
// move time to beyond the next cycle
clock.addAndGet(TimeUnit.SECONDS.toMillis(2L));
// add some jitter to allow threads to race
firstWriter = attemptToWriteDocument(queue2);
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10L));
secondWriter = attemptToWriteDocument(queue3);
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10L));
thirdWriter = attemptToWriteDocument(queue4);
// stall this thread, other threads should not be able to advance,
// since this DocumentContext is still open
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2L));
documentContext.wire().getValueOut().int32(counter.getAndIncrement());
}
firstWriter.get(5L, TimeUnit.SECONDS);
secondWriter.get(5L, TimeUnit.SECONDS);
thirdWriter.get(5L, TimeUnit.SECONDS);
final ExcerptTailer tailer = queue.createTailer();
expectValue(0, tailer);
expectValue(1, tailer);
expectValue(2, tailer);
expectValue(3, tailer);
}
}
use of net.openhft.chronicle.wire.DocumentContext in project Chronicle-Queue by OpenHFT.
the class DocumentOrderingTest method queuedWriteInPreviousCycleShouldRespectTotalOrdering.
@Test
public void queuedWriteInPreviousCycleShouldRespectTotalOrdering() throws Exception {
try (final SingleChronicleQueue queue = builder(DirectoryUtils.tempDir("document-ordering"), 1_000L).build()) {
Assume.assumeFalse("ordering/atomicity is not guaranteed when using progressOnContention = true," + "as multiple threads can be concurrently executing within a queue's " + "document context when the queue head is contented", progressOnContention);
final ExcerptAppender excerptAppender = queue.acquireAppender();
// write initial document
excerptAppender.writeDocument("foo", ValueOut::text);
// begin a record in the first cycle file
final DocumentContext firstOpenDocument = excerptAppender.writingDocument();
firstOpenDocument.wire().getValueOut().int32(counter.getAndIncrement());
// start another record in the first cycle file
// this may be written to either the first or the second cycle file
final Future<RecordInfo> secondDocumentInFirstCycle = attemptToWriteDocument(queue);
// move time to beyond the next cycle
clock.addAndGet(TimeUnit.SECONDS.toMillis(2L));
final Future<RecordInfo> otherDocumentWriter = attemptToWriteDocument(queue);
firstOpenDocument.close();
secondDocumentInFirstCycle.get(5L, TimeUnit.SECONDS);
final ExcerptTailer tailer = queue.createTailer();
// discard first record
tailer.readingDocument().close();
// assert that records are committed in order
expectValue(0, tailer);
expectValue(1, tailer);
expectValue(2, tailer);
assertThat(tailer.readingDocument().isPresent(), is(false));
}
}
use of net.openhft.chronicle.wire.DocumentContext in project Chronicle-Queue by OpenHFT.
the class DocumentOrderingTest method expectValue.
private static void expectValue(final int expectedValue, final ExcerptTailer tailer) {
try (final DocumentContext documentContext = tailer.readingDocument()) {
assertTrue(documentContext.isPresent());
assertEquals(expectedValue, documentContext.wire().getValueIn().int32());
}
}
Aggregations