use of herddb.log.CommitLogResult in project herddb by diennea.
the class TableSpaceManager method beginTransactionAsync.
private CompletableFuture<StatementExecutionResult> beginTransactionAsync(StatementEvaluationContext context, boolean releaseLock) throws StatementExecutionException {
long id = newTransactionId.incrementAndGet();
LogEntry entry = LogEntryFactory.beginTransaction(id);
CommitLogResult pos;
boolean lockAcquired = false;
if (context.getTableSpaceLock() == 0) {
long lockStamp = acquireReadLock("begin transaction");
context.setTableSpaceLock(lockStamp);
lockAcquired = true;
}
pos = log.log(entry, false);
CompletableFuture<StatementExecutionResult> res = pos.logSequenceNumber.thenApplyAsync((lsn) -> {
apply(pos, entry, false);
return new TransactionResult(id, TransactionResult.OutcomeType.BEGIN);
}, callbacksExecutor);
if (lockAcquired && releaseLock) {
releaseReadLock(res, context.getTableSpaceLock(), "begin transaction");
}
return res;
}
use of herddb.log.CommitLogResult in project herddb by diennea.
the class TableSpaceManager method alterTable.
private StatementExecutionResult alterTable(AlterTableStatement statement, TransactionContext transactionContext, StatementEvaluationContext context) throws StatementExecutionException {
boolean lockAcquired = false;
if (context.getTableSpaceLock() == 0) {
long lockStamp = acquireWriteLock(statement);
context.setTableSpaceLock(lockStamp);
lockAcquired = true;
}
try {
if (transactionContext.transactionId > 0) {
Transaction transaction = transactions.get(transactionContext.transactionId);
if (transactionContext.transactionId > 0 && transaction == null) {
throw new StatementExecutionException("transaction " + transactionContext.transactionId + " does not exist on tablespace " + tableSpaceName);
}
if (transaction != null && !transaction.tableSpace.equals(tableSpaceName)) {
throw new StatementExecutionException("transaction " + transaction.transactionId + " is for tablespace " + transaction.tableSpace + ", not for " + tableSpaceName);
}
LOGGER.log(Level.INFO, "Implicitly committing transaction " + transactionContext.transactionId + " due to an ALTER TABLE statement in tablespace " + tableSpaceName);
try {
commitTransaction(new CommitTransactionStatement(tableSpaceName, transactionContext.transactionId), context).join();
} catch (CompletionException err) {
throw new StatementExecutionException(err);
}
transactionContext = TransactionContext.NO_TRANSACTION;
}
AbstractTableManager tableManager = tables.get(statement.getTable());
if (tableManager == null) {
throw new TableDoesNotExistException("no table " + statement.getTable() + " in tablespace " + tableSpaceName + "," + " only " + tables.keySet());
}
Table oldTable = tableManager.getTable();
Table[] childrenTables = collectChildrenTables(oldTable);
if (childrenTables != null) {
for (Table child : childrenTables) {
for (String col : statement.getDropColumns()) {
for (ForeignKeyDef fk : child.foreignKeys) {
if (fk.parentTableId.equals(oldTable.uuid)) {
if (Stream.of(fk.parentTableColumns).anyMatch(c -> c.equalsIgnoreCase(col))) {
throw new StatementExecutionException("Cannot drop column " + oldTable.name + "." + col + " because of foreign key constraint " + fk.name + " on table " + child.name);
}
}
}
}
}
}
Table newTable;
try {
newTable = tableManager.getTable().applyAlterTable(statement);
} catch (IllegalArgumentException error) {
throw new StatementExecutionException(error);
}
validateAlterTable(newTable, context);
LogEntry entry = LogEntryFactory.alterTable(newTable, null);
try {
CommitLogResult pos = log.log(entry, entry.transactionId <= 0);
apply(pos, entry, false);
} catch (Exception err) {
throw new StatementExecutionException(err);
}
// Here transactionId is always 0, because transaction is implicitly committed
return new DDLStatementExecutionResult(transactionContext.transactionId);
} finally {
if (lockAcquired) {
releaseWriteLock(context.getTableSpaceLock(), statement);
context.setTableSpaceLock(0);
}
}
}
use of herddb.log.CommitLogResult in project herddb by diennea.
the class TableManager method executeTruncate.
private StatementExecutionResult executeTruncate(TruncateTableStatement truncate, Transaction transaction, StatementEvaluationContext context) throws StatementExecutionException, DataStorageManagerException {
if (transaction != null) {
throw new StatementExecutionException("TRUNCATE TABLE cannot be executed within the context of a Transaction");
}
try {
long estimatedSize = keyToPage.size();
LOGGER.log(Level.INFO, "TRUNCATING TABLE {0} with approx {1} records", new Object[] { table.name, estimatedSize });
LogEntry entry = LogEntryFactory.truncate(table, null);
CommitLogResult pos = log.log(entry, entry.transactionId <= 0);
apply(pos, entry, false);
return new DMLStatementExecutionResult(0, estimatedSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) estimatedSize, null, null);
} catch (LogNotAvailableException | DataStorageManagerException error) {
LOGGER.log(Level.SEVERE, "Error during TRUNCATE table " + table.tablespace + "." + table.name, error);
throw new StatementExecutionException(error);
}
}
use of herddb.log.CommitLogResult in project herddb by diennea.
the class FileCommitLogTest method testMaxBatchSizeBytes.
@Test
public void testMaxBatchSizeBytes() throws Exception {
TestStatsProvider testStatsProvider = new TestStatsProvider();
TestStatsProvider.TestStatsLogger statsLogger = testStatsProvider.getStatsLogger("test");
try (FileCommitLogManager manager = new FileCommitLogManager(folder.newFolder().toPath(), ServerConfiguration.PROPERTY_MAX_LOG_FILE_SIZE_DEFAULT, // no flush by batch size
Integer.MAX_VALUE, // flush after 2 writes
LogEntryFactory.beginTransaction(0).serialize().length * 2 - 1, // no flush by time
Integer.MAX_VALUE, true, /* require fsync */
false, /* O_DIRECT */
ServerConfiguration.PROPERTY_DEFERRED_SYNC_PERIOD_DEFAULT, statsLogger)) {
manager.start();
int writeCount = 0;
final long _startWrite = System.currentTimeMillis();
try (FileCommitLog log = manager.createCommitLog("tt", "aa", "nodeid")) {
log.startWriting(1);
CopyOnWriteArrayList<LogSequenceNumber> completed = new CopyOnWriteArrayList<>();
CommitLogResult future = log.log(LogEntryFactory.beginTransaction(0), true);
future.logSequenceNumber.thenAccept(completed::add);
assertFalse(future.logSequenceNumber.isDone());
CommitLogResult future2 = log.log(LogEntryFactory.beginTransaction(0), true);
future2.logSequenceNumber.thenAccept(completed::add);
future.logSequenceNumber.get(10, TimeUnit.SECONDS);
future2.logSequenceNumber.get(10, TimeUnit.SECONDS);
TestUtils.waitForCondition(() -> {
return completed.size() == 2;
}, NOOP, 100);
writeCount = completed.size();
assertTrue(completed.get(1).after(completed.get(0)));
}
final long _endWrite = System.currentTimeMillis();
AtomicInteger readCount = new AtomicInteger();
try (CommitLog log = manager.createCommitLog("tt", "aa", "nodeid")) {
log.recovery(LogSequenceNumber.START_OF_TIME, new BiConsumer<LogSequenceNumber, LogEntry>() {
@Override
public void accept(LogSequenceNumber t, LogEntry u) {
readCount.incrementAndGet();
}
}, true);
}
final long _endRead = System.currentTimeMillis();
assertEquals(writeCount, readCount.get());
System.out.println("Write time: " + (_endWrite - _startWrite) + " ms");
System.out.println("Read time: " + (_endRead - _endWrite) + " ms");
}
}
Aggregations