use of com.questdb.store.factory.configuration.JournalStructure in project questdb by bluestreak01.
the class CachingReaderFactoryTest method testConcurrentOpenAndClose.
@Test
public void testConcurrentOpenAndClose() throws Exception {
final int readerCount = 5;
int threadCount = 2;
final int iterations = 1000;
// create journals to read
final JournalMetadata<?>[] meta = new JournalMetadata[readerCount];
for (int i = 0; i < readerCount; i++) {
final JournalMetadata<?> m = new JournalStructure("x" + i).$date("ts").$().build();
((WriterFactory) getFactory()).writer(m).close();
meta[i] = m;
}
try (final CachingReaderFactory rf = new CachingReaderFactory(factoryContainer.getConfiguration(), 1000, 2)) {
final CyclicBarrier barrier = new CyclicBarrier(threadCount);
final CountDownLatch halt = new CountDownLatch(threadCount);
final AtomicInteger errors = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
final int x = i;
new Thread(() -> {
Rnd rnd = new Rnd(x, -x);
try {
barrier.await();
for (int i1 = 0; i1 < iterations; i1++) {
JournalMetadata<?> m = meta[rnd.nextPositiveInt() % readerCount];
try (Journal ignored = rf.reader(m)) {
LockSupport.parkNanos(100);
}
}
} catch (Exception e) {
e.printStackTrace();
errors.incrementAndGet();
} finally {
halt.countDown();
}
}).start();
}
halt.await();
Assert.assertEquals(0, errors.get());
}
}
use of com.questdb.store.factory.configuration.JournalStructure in project questdb by bluestreak01.
the class CachingReaderFactoryTest method testLockUnlock.
@Test
public void testLockUnlock() throws Exception {
// create journals
final JournalMetadata<?> m1 = new JournalStructure("x").$date("ts").$().build();
((WriterFactory) getFactory()).writer(m1).close();
final JournalMetadata<?> m2 = new JournalStructure("y").$date("ts").$().build();
((WriterFactory) getFactory()).writer(m2).close();
Journal x, y;
try (final CachingReaderFactory rf = new CachingReaderFactory(factoryContainer.getConfiguration(), 1000, 2)) {
x = rf.reader(m1);
Assert.assertNotNull(x);
y = rf.reader(m2);
Assert.assertNotNull(y);
// expect lock to fail because we have "x" open
try {
rf.lock(m1.getName());
Assert.fail();
} catch (RetryLockException ignore) {
}
x.close();
// expect lock to succeed after we closed "x"
rf.lock(m1.getName());
// expect "x" to be physically closed
Assert.assertFalse(x.isOpen());
// "x" is locked, expect this to fail
try {
Assert.assertNull(rf.reader(m1));
} catch (JournalLockedException ignored) {
}
rf.unlock(m1.getName());
x = rf.reader(m1);
Assert.assertNotNull(x);
x.close();
Assert.assertTrue(x.isOpen());
}
Assert.assertTrue(y.isOpen());
y.close();
Assert.assertFalse(y.isOpen());
// "x" was not busy and should be closed by factory
Assert.assertFalse(x.isOpen());
}
use of com.questdb.store.factory.configuration.JournalStructure in project questdb by bluestreak01.
the class CachingWriterFactoryTest method testLockUnlock.
@Test
public void testLockUnlock() throws Exception {
final JournalMetadata<?> x = new JournalStructure("x").$date("ts").$().build();
final JournalMetadata<?> y = new JournalStructure("y").$date("ts").$().build();
JournalWriter wx = wf.writer(x);
Assert.assertNotNull(wx);
Assert.assertTrue(wx.isOpen());
JournalWriter wy = wf.writer(y);
Assert.assertNotNull(wy);
Assert.assertTrue(wy.isOpen());
try {
// check that lock is successful
wf.lock(x.getName());
// check that writer x is closed and writer y is open (lock must not spill out to other writers)
Assert.assertFalse(wx.isOpen());
Assert.assertTrue(wy.isOpen());
// check that when name is locked writers are not created
try {
wf.writer(x);
} catch (JournalLockedException ignored) {
}
final CountDownLatch done = new CountDownLatch(1);
final AtomicBoolean result = new AtomicBoolean();
// have new thread try to allocated this writers
new Thread(() -> {
try (JournalWriter ignored = wf.writer(x)) {
result.set(false);
} catch (WriterBusyException ignored) {
result.set(true);
} catch (JournalException e) {
e.printStackTrace();
result.set(false);
}
done.countDown();
}).start();
Assert.assertTrue(done.await(1, TimeUnit.SECONDS));
Assert.assertTrue(result.get());
wf.unlock(x.getName());
wx = wf.writer(x);
Assert.assertNotNull(wx);
Assert.assertTrue(wx.isOpen());
try {
// unlocking writer that has not been locked must produce exception
// and not affect open writer
wf.unlock(wx.getName());
Assert.fail();
} catch (IllegalStateException ignored) {
}
Assert.assertTrue(wx.isOpen());
} finally {
wx.close();
wy.close();
}
}
use of com.questdb.store.factory.configuration.JournalStructure in project questdb by bluestreak01.
the class CachingWriterFactoryTest method testNewLock.
@Test
public void testNewLock() throws Exception {
final JournalMetadata<?> m = new JournalStructure("x").$date("ts").$().build();
wf.lock("x");
try {
wf.writer(m);
Assert.fail();
} catch (JournalException ignored) {
}
wf.unlock("x");
}
use of com.questdb.store.factory.configuration.JournalStructure in project questdb by bluestreak01.
the class QueryParser method parseCreateJournal.
private ParsedModel parseCreateJournal() throws ParserException {
ExprNode name = exprNodePool.next();
name.token = Chars.stripQuotes(tok().toString());
name.position = lexer.position();
name.type = ExprNode.LITERAL;
CharSequence tok = tok();
final JournalStructure struct;
final QueryModel queryModel;
if (Chars.equals(tok, '(')) {
queryModel = null;
struct = new JournalStructure(name.token);
lexer.unparse();
parseJournalFields(struct);
} else if (Chars.equals(tok, "as")) {
expectTok('(');
queryModel = parseQuery(true);
struct = null;
expectTok(')');
} else {
throw QueryError.position(lexer.position()).$("Unexpected token").$();
}
CreateJournalModel model = createJournalModelPool.next();
model.setStruct(struct);
model.setQueryModel(queryModel);
model.setName(name);
tok = lexer.optionTok();
while (tok != null && Chars.equals(tok, ',')) {
int pos = lexer.position();
tok = tok();
if (Chars.equals(tok, "index")) {
expectTok('(');
ColumnIndexModel columnIndexModel = columnIndexModelPool.next();
columnIndexModel.setName(expectLiteral());
pos = lexer.position();
tok = tok();
if (Chars.equals(tok, "buckets")) {
try {
columnIndexModel.setBuckets(Numbers.ceilPow2(Numbers.parseInt(tok())) - 1);
} catch (NumericException e) {
throw QueryError.$(pos, "Int constant expected");
}
pos = lexer.position();
tok = tok();
}
expectTok(tok, pos, ')');
model.addColumnIndexModel(columnIndexModel);
tok = lexer.optionTok();
} else if (Chars.equals(tok, "cast")) {
expectTok('(');
ColumnCastModel columnCastModel = columnCastModelPool.next();
columnCastModel.setName(expectLiteral());
expectTok(tok(), "as");
ExprNode node = expectLiteral();
int type = ColumnType.columnTypeOf(node.token);
if (type == -1) {
throw QueryError.$(node.position, "invalid type");
}
columnCastModel.setType(type, node.position);
if (type == ColumnType.SYMBOL) {
tok = lexer.optionTok();
pos = lexer.position();
if (Chars.equals(tok, "count")) {
try {
columnCastModel.setCount(Numbers.parseInt(tok()));
tok = tok();
} catch (NumericException e) {
throw QueryError.$(pos, "int value expected");
}
}
} else {
pos = lexer.position();
tok = tok();
}
expectTok(tok, pos, ')');
if (!model.addColumnCastModel(columnCastModel)) {
throw QueryError.$(columnCastModel.getName().position, "duplicate cast");
}
tok = lexer.optionTok();
} else {
throw QueryError.$(pos, "Unexpected token");
}
}
ExprNode timestamp = parseTimestamp(tok);
if (timestamp != null) {
model.setTimestamp(timestamp);
tok = lexer.optionTok();
}
ExprNode partitionBy = parsePartitionBy(tok);
if (partitionBy != null) {
model.setPartitionBy(partitionBy);
tok = lexer.optionTok();
}
ExprNode hint = parseRecordHint(tok);
if (hint != null) {
model.setRecordHint(hint);
tok = lexer.optionTok();
}
if (tok != null) {
throw QueryError.$(lexer.position(), "Unexpected token");
}
return model;
}
Aggregations