use of io.questdb.mp.SPSequence in project questdb by bluestreak01.
the class LogFactoryTest method testRollingFileWriterBySize.
@Test
public void testRollingFileWriterBySize() throws Exception {
String base = temp.getRoot().getAbsolutePath() + Files.SEPARATOR;
String logFile = base + "mylog-${date:yyyy-MM-dd}.log";
String expectedLogFile = base + "mylog-2015-05-03.log";
final MicrosecondClock clock = new TestMicrosecondClock(TimestampFormatUtils.parseTimestamp("2015-05-03T10:35:00.000Z"), 1);
try (Path path = new Path()) {
// create rogue file that would be in a way of logger rolling existing files
path.of(base);
Assert.assertTrue(Files.touch(path.concat("mylog-2015-05-03.log.2").$()));
}
RingQueue<LogRecordSink> queue = new RingQueue<>(LogRecordSink::new, 1024, 1024, MemoryTag.NATIVE_DEFAULT);
SPSequence pubSeq = new SPSequence(queue.getCycle());
SCSequence subSeq = new SCSequence();
pubSeq.then(subSeq).then(pubSeq);
try (final LogRollingFileWriter writer = new LogRollingFileWriter(FilesFacadeImpl.INSTANCE, clock, queue, subSeq, LogLevel.LOG_LEVEL_INFO)) {
writer.setLocation(logFile);
writer.setRollSize("1m");
writer.setBufferSize("64k");
writer.bindProperties();
AtomicBoolean running = new AtomicBoolean(true);
SOCountDownLatch halted = new SOCountDownLatch();
halted.setCount(1);
new Thread(() -> {
while (running.get()) {
writer.runSerially();
}
// noinspection StatementWithEmptyBody
while (writer.runSerially()) ;
halted.countDown();
}).start();
// now publish
int published = 0;
int toPublish = 100_000;
while (published < toPublish) {
long cursor = pubSeq.next();
if (cursor < 0) {
LockSupport.parkNanos(1);
continue;
}
final long available = pubSeq.available();
while (cursor < available && published < toPublish) {
LogRecordSink sink = queue.get(cursor++);
sink.setLevel(LogLevel.LOG_LEVEL_INFO);
sink.put("test");
published++;
}
pubSeq.done(cursor - 1);
}
running.set(false);
halted.await();
}
assertFileLength(expectedLogFile);
assertFileLength(expectedLogFile + ".1");
}
use of io.questdb.mp.SPSequence in project questdb by bluestreak01.
the class SymbolCacheTest method testConcurrency.
@Test
public void testConcurrency() throws Exception {
assertMemoryLeak(() -> {
final Rnd rndCache = new Rnd();
final int N = 1_000_000;
long ts = TimestampFormatUtils.parseTimestamp("2020-09-10T20:00:00.000000Z");
final long incrementUs = 10000;
final String constValue = "hello";
compiler.compile("create table x(a symbol, c int, b symbol capacity 10000000, ts timestamp) timestamp(ts) partition by DAY", sqlExecutionContext);
try (SymbolCache symbolCache = new SymbolCache(new DefaultLineTcpReceiverConfiguration());
Path path = new Path()) {
path.of(configuration.getRoot()).concat("x");
symbolCache.of(configuration, path, "b", 1);
final CyclicBarrier barrier = new CyclicBarrier(2);
final SOCountDownLatch haltLatch = new SOCountDownLatch(1);
final AtomicBoolean cacheInError = new AtomicBoolean(false);
RingQueue<Holder> wheel = new RingQueue<Holder>(Holder::new, 256);
SPSequence pubSeq = new SPSequence(wheel.getCycle());
SCSequence subSeq = new SCSequence();
pubSeq.then(subSeq).then(pubSeq);
new Thread(() -> {
try {
barrier.await();
for (int i = 0; i < N; i++) {
// All keys should not be found, but we keep looking them up because
// we pretend we don't know this upfront. The aim is to cause
// race condition between lookup and table writer
final CharSequence value2 = rndCache.nextString(5);
symbolCache.getSymbolKey(constValue);
symbolCache.getSymbolKey(value2);
final long cursor = pubSeq.nextBully();
final Holder h = wheel.get(cursor);
// publish the value2 to the table writer
h.value1 = constValue;
h.value2 = Chars.toString(value2);
pubSeq.done(cursor);
}
} catch (Throwable e) {
cacheInError.set(true);
e.printStackTrace();
} finally {
haltLatch.countDown();
}
}).start();
try (TableWriter w = engine.getWriter(sqlExecutionContext.getCairoSecurityContext(), "x", "test")) {
barrier.await();
OUT: for (int i = 0; i < N; i++) {
long cursor;
while (true) {
cursor = subSeq.next();
if (cursor < 0) {
// due to random generator producing duplicate strings
if (haltLatch.getCount() < 1) {
break OUT;
}
} else {
break;
}
}
Holder h = wheel.get(cursor);
TableWriter.Row r = w.newRow(ts);
r.putSym(0, h.value1);
r.putInt(1, 0);
r.putSym(2, h.value2);
r.append();
subSeq.done(cursor);
if (i % 256 == 0) {
w.commit();
}
ts += incrementUs;
}
w.commit();
} finally {
haltLatch.await();
}
Assert.assertFalse(cacheInError.get());
}
compiler.compile("drop table x", sqlExecutionContext);
});
}
Aggregations