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").$();
});
}
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();
}
});
}
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);
}
}
Aggregations