Search in sources :

Example 1 with EntryLockedException

use of com.questdb.cairo.pool.ex.EntryLockedException in project questdb by bluestreak01.

the class ReaderPoolTest method testLockBusyReader.

@Test
public void testLockBusyReader() throws Exception {
    final int readerCount = 5;
    int threadCount = 2;
    final int iterations = 10000;
    Rnd dataRnd = new Rnd();
    StringSink sink = new StringSink();
    RecordSourcePrinter printer = new RecordSourcePrinter(sink);
    final String[] names = new String[readerCount];
    final String[] expectedRows = new String[readerCount];
    for (int i = 0; i < readerCount; i++) {
        names[i] = "x" + i;
        try (TableModel model = new TableModel(configuration, names[i], PartitionBy.NONE).col("ts", ColumnType.DATE)) {
            CairoTestUtils.create(model);
        }
        try (TableWriter w = new TableWriter(configuration, names[i])) {
            for (int k = 0; k < 10; k++) {
                TableWriter.Row r = w.newRow(0);
                r.putDate(0, dataRnd.nextLong());
                r.append();
            }
            w.commit();
        }
        sink.clear();
        try (TableReader r = new TableReader(configuration, names[i])) {
            printer.print(r.getCursor(), true, r.getMetadata());
        }
        expectedRows[i] = sink.toString();
    }
    LOG.info().$("testLockBusyReader BEGIN").$();
    assertWithPool(pool -> {
        final CyclicBarrier barrier = new CyclicBarrier(threadCount);
        final CountDownLatch halt = new CountDownLatch(threadCount);
        final AtomicInteger errors = new AtomicInteger();
        final LongList lockTimes = new LongList();
        final LongList workerTimes = new LongList();
        new Thread(() -> {
            Rnd rnd = new Rnd();
            try {
                barrier.await();
                String name;
                for (int i = 0; i < iterations; i++) {
                    name = names[rnd.nextPositiveInt() % readerCount];
                    while (true) {
                        if (pool.lock(name)) {
                            lockTimes.add(System.currentTimeMillis());
                            LockSupport.parkNanos(10L);
                            pool.unlock(name);
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                errors.incrementAndGet();
                e.printStackTrace();
            } finally {
                halt.countDown();
            }
        }).start();
        new Thread(() -> {
            Rnd rnd = new Rnd();
            try {
                workerTimes.add(System.currentTimeMillis());
                for (int i = 0; i < iterations; i++) {
                    int index = rnd.nextPositiveInt() % readerCount;
                    String name = names[index];
                    try (TableReader r = pool.get(name)) {
                        RecordCursor cursor = r.getCursor();
                        sink.clear();
                        printer.print(cursor, true, r.getMetadata());
                        TestUtils.assertEquals(expectedRows[index], sink);
                        if (name.equals(names[readerCount - 1]) && barrier.getNumberWaiting() > 0) {
                            barrier.await();
                        }
                        LockSupport.parkNanos(10L);
                    } catch (EntryLockedException | EntryUnavailableException ignored) {
                    } catch (Exception e) {
                        errors.incrementAndGet();
                        e.printStackTrace();
                        break;
                    }
                }
                workerTimes.add(System.currentTimeMillis());
            } finally {
                halt.countDown();
            }
        }).start();
        halt.await();
        Assert.assertEquals(0, halt.getCount());
        Assert.assertEquals(0, errors.get());
        // check that there are lock times between worker times
        int count = 0;
        // ensure that we have worker times
        Assert.assertEquals(2, workerTimes.size());
        long lo = workerTimes.get(0);
        long hi = workerTimes.get(1);
        Assert.assertTrue(lockTimes.size() > 0);
        for (int i = 0, n = lockTimes.size(); i < n; i++) {
            long t = lockTimes.getQuick(i);
            if (t > lo && t < hi) {
                count++;
            }
        }
        Assert.assertTrue(count > 0);
        LOG.info().$("testLockBusyReader END").$();
    });
}
Also used : RecordCursor(com.questdb.common.RecordCursor) RecordSourcePrinter(com.questdb.ql.RecordSourcePrinter) StringSink(com.questdb.std.str.StringSink) CountDownLatch(java.util.concurrent.CountDownLatch) EntryLockedException(com.questdb.cairo.pool.ex.EntryLockedException) EntryUnavailableException(com.questdb.cairo.pool.ex.EntryUnavailableException) PoolClosedException(com.questdb.cairo.pool.ex.PoolClosedException) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Test(org.junit.Test)

Example 2 with EntryLockedException

use of com.questdb.cairo.pool.ex.EntryLockedException in project questdb by bluestreak01.

the class WriterPoolTest method testLockUnlock.

@Test
public void testLockUnlock() throws Exception {
    try (TableModel model = new TableModel(configuration, "x", PartitionBy.NONE).col("ts", ColumnType.DATE)) {
        CairoTestUtils.create(model);
    }
    try (TableModel model = new TableModel(configuration, "y", PartitionBy.NONE).col("ts", ColumnType.DATE)) {
        CairoTestUtils.create(model);
    }
    assertWithPool(pool -> {
        TableWriter wy = pool.get("y");
        Assert.assertNotNull(wy);
        Assert.assertTrue(wy.isOpen());
        try {
            // check that lock is successful
            Assert.assertTrue(pool.lock("x"));
            // check that writer x is closed and writer y is open (lock must not spill out to other writers)
            Assert.assertTrue(wy.isOpen());
            // check that when name is locked writers are not created
            try {
                pool.get("x");
                Assert.fail();
            } catch (EntryLockedException ignored) {
            }
            final CountDownLatch done = new CountDownLatch(1);
            final AtomicBoolean result = new AtomicBoolean();
            // have new thread try to allocated this writer
            new Thread(() -> {
                try (TableWriter ignored = pool.get("x")) {
                    result.set(false);
                } catch (EntryUnavailableException ignored) {
                    result.set(true);
                } catch (CairoException e) {
                    e.printStackTrace();
                    result.set(false);
                }
                done.countDown();
            }).start();
            Assert.assertTrue(done.await(1, TimeUnit.SECONDS));
            Assert.assertTrue(result.get());
            pool.unlock("x");
            try (TableWriter wx = pool.get("x")) {
                Assert.assertNotNull(wx);
                Assert.assertTrue(wx.isOpen());
                try {
                    // unlocking writer that has not been locked must produce exception
                    // and not affect open writer
                    pool.unlock("x");
                    Assert.fail();
                } catch (CairoException ignored) {
                }
                Assert.assertTrue(wx.isOpen());
            }
        } finally {
            wy.close();
        }
    });
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) EntryUnavailableException(com.questdb.cairo.pool.ex.EntryUnavailableException) CountDownLatch(java.util.concurrent.CountDownLatch) EntryLockedException(com.questdb.cairo.pool.ex.EntryLockedException) Test(org.junit.Test)

Example 3 with EntryLockedException

use of com.questdb.cairo.pool.ex.EntryLockedException in project questdb by bluestreak01.

the class QueryModel method getTableMetadata.

public RecordMetadata getTableMetadata(CairoEngine engine, FlyweightCharSequence charSequence) throws ParserException {
    // table name must not contain quotes by now
    ExprNode readerNode = getTableName();
    int lo = 0;
    int hi = readerNode.token.length();
    if (Chars.startsWith(readerNode.token, NO_ROWID_MARKER)) {
        lo += NO_ROWID_MARKER.length();
    }
    if (lo == hi) {
        throw ParserException.$(readerNode.position, "come on, where is table name?");
    }
    int status = engine.getStatus(readerNode.token, lo, hi);
    if (status == TableUtils.TABLE_DOES_NOT_EXIST) {
        throw ParserException.$(readerNode.position, "table does not exist");
    }
    if (status == TableUtils.TABLE_RESERVED) {
        throw ParserException.$(readerNode.position, "table directory is of unknown format");
    }
    try (TableReader r = engine.getReader(charSequence.of(readerNode.token, lo, hi - lo))) {
        return r.getMetadata();
    } catch (EntryLockedException e) {
        throw ParserException.position(readerNode.position).put("table is locked: ").put(charSequence);
    } catch (CairoException e) {
        throw ParserException.position(readerNode.position).put(e);
    }
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode) CairoException(com.questdb.cairo.CairoException) TableReader(com.questdb.cairo.TableReader) EntryLockedException(com.questdb.cairo.pool.ex.EntryLockedException)

Aggregations

EntryLockedException (com.questdb.cairo.pool.ex.EntryLockedException)3 EntryUnavailableException (com.questdb.cairo.pool.ex.EntryUnavailableException)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 Test (org.junit.Test)2 CairoException (com.questdb.cairo.CairoException)1 TableReader (com.questdb.cairo.TableReader)1 PoolClosedException (com.questdb.cairo.pool.ex.PoolClosedException)1 RecordCursor (com.questdb.common.RecordCursor)1 ExprNode (com.questdb.griffin.common.ExprNode)1 RecordSourcePrinter (com.questdb.ql.RecordSourcePrinter)1 StringSink (com.questdb.std.str.StringSink)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1