Search in sources :

Example 1 with SPSequence

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");
}
Also used : Path(io.questdb.std.str.Path) RingQueue(io.questdb.mp.RingQueue) SPSequence(io.questdb.mp.SPSequence) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) MicrosecondClock(io.questdb.std.datetime.microtime.MicrosecondClock) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SCSequence(io.questdb.mp.SCSequence) Test(org.junit.Test)

Example 2 with SPSequence

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);
    });
}
Also used : Path(io.questdb.std.str.Path) RingQueue(io.questdb.mp.RingQueue) SPSequence(io.questdb.mp.SPSequence) Rnd(io.questdb.std.Rnd) CyclicBarrier(java.util.concurrent.CyclicBarrier) SOCountDownLatch(io.questdb.mp.SOCountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SCSequence(io.questdb.mp.SCSequence) Test(org.junit.Test) AbstractGriffinTest(io.questdb.griffin.AbstractGriffinTest)

Aggregations

RingQueue (io.questdb.mp.RingQueue)2 SCSequence (io.questdb.mp.SCSequence)2 SOCountDownLatch (io.questdb.mp.SOCountDownLatch)2 SPSequence (io.questdb.mp.SPSequence)2 Path (io.questdb.std.str.Path)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 Test (org.junit.Test)2 AbstractGriffinTest (io.questdb.griffin.AbstractGriffinTest)1 Rnd (io.questdb.std.Rnd)1 MicrosecondClock (io.questdb.std.datetime.microtime.MicrosecondClock)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1