Search in sources :

Example 36 with Transaction

use of herddb.model.Transaction 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);
        }
    }
}
Also used : Table(herddb.model.Table) CommitTransactionStatement(herddb.model.commands.CommitTransactionStatement) CommitLogResult(herddb.log.CommitLogResult) DDLStatementExecutionResult(herddb.model.DDLStatementExecutionResult) StatementExecutionException(herddb.model.StatementExecutionException) HDBException(herddb.client.HDBException) IndexAlreadyExistsException(herddb.model.IndexAlreadyExistsException) LogNotAvailableException(herddb.log.LogNotAvailableException) ClientSideMetadataProviderException(herddb.client.ClientSideMetadataProviderException) TableSpaceDoesNotExistException(herddb.model.TableSpaceDoesNotExistException) IndexDoesNotExistException(herddb.model.IndexDoesNotExistException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) FullRecoveryNeededException(herddb.log.FullRecoveryNeededException) TableAlreadyExistsException(herddb.model.TableAlreadyExistsException) TimeoutException(java.util.concurrent.TimeoutException) DataStorageManagerException(herddb.storage.DataStorageManagerException) TableDoesNotExistException(herddb.model.TableDoesNotExistException) DDLException(herddb.model.DDLException) StatementExecutionException(herddb.model.StatementExecutionException) CompletionException(java.util.concurrent.CompletionException) EOFException(java.io.EOFException) MetadataStorageManagerException(herddb.metadata.MetadataStorageManagerException) DataScannerException(herddb.model.DataScannerException) TableDoesNotExistException(herddb.model.TableDoesNotExistException) Transaction(herddb.model.Transaction) CompletionException(java.util.concurrent.CompletionException) ForeignKeyDef(herddb.model.ForeignKeyDef) LogEntry(herddb.log.LogEntry) DumpedLogEntry(herddb.backup.DumpedLogEntry)

Example 37 with Transaction

use of herddb.model.Transaction in project herddb by diennea.

the class TableSpaceManager method processAbandonedTransactions.

void processAbandonedTransactions() {
    if (!leader) {
        return;
    }
    long now = System.currentTimeMillis();
    long timeout = dbmanager.getAbandonedTransactionsTimeout();
    if (timeout <= 0) {
        return;
    }
    long abandonedTransactionTimeout = now - timeout;
    for (Transaction t : transactions.values()) {
        if (t.isAbandoned(abandonedTransactionTimeout)) {
            LOGGER.log(Level.SEVERE, "forcing rollback of abandoned transaction {0}," + " created locally at {1}," + " last activity locally at {2}", new Object[] { t.transactionId, new java.sql.Timestamp(t.localCreationTimestamp), new java.sql.Timestamp(t.lastActivityTs) });
            try {
                if (!validateTransactionBeforeTxCommand(t.transactionId, false)) {
                    // Continue to check next transaction
                    continue;
                }
            } catch (StatementExecutionException e) {
                LOGGER.log(Level.SEVERE, "Failed to validate transaction {0}: {1}", new Object[] { t.transactionId, e.getMessage() });
                // Continue to check next transaction
                continue;
            } catch (RuntimeException e) {
                LOGGER.log(Level.SEVERE, "Failed to validate transaction {0}", new Object[] { t.transactionId, e });
                // Continue to check next transaction
                continue;
            }
            long lockStamp = acquireReadLock("forceRollback" + t.transactionId);
            try {
                forceTransactionRollback(t.transactionId);
            } finally {
                releaseReadLock(lockStamp, "forceRollback" + t.transactionId);
            }
        }
    }
}
Also used : Transaction(herddb.model.Transaction) StatementExecutionException(herddb.model.StatementExecutionException)

Example 38 with Transaction

use of herddb.model.Transaction in project herddb by diennea.

the class BookKeeperDataStorageManager method writeTransactionsAtCheckpoint.

@Override
public Collection<PostCheckpointAction> writeTransactionsAtCheckpoint(String tableSpace, LogSequenceNumber sequenceNumber, Collection<Transaction> transactions) throws DataStorageManagerException {
    if (sequenceNumber.isStartOfTime() && !transactions.isEmpty()) {
        throw new DataStorageManagerException("impossible to write a non empty transactions list at start-of-time");
    }
    String checkPointFile = getTablespaceTransactionsFile(tableSpace, sequenceNumber);
    LOGGER.log(Level.FINE, "writeTransactionsAtCheckpoint for tableSpace {0} sequenceNumber {1} to {2}, active transactions {3}", new Object[] { tableSpace, sequenceNumber, checkPointFile, transactions.size() });
    try (VisibleByteArrayOutputStream buffer = new VisibleByteArrayOutputStream();
        ExtendedDataOutputStream dout = new ExtendedDataOutputStream(buffer)) {
        // version
        dout.writeVLong(1);
        // flags for future implementations
        dout.writeVLong(0);
        dout.writeUTF(tableSpace);
        dout.writeZLong(sequenceNumber.ledgerId);
        dout.writeZLong(sequenceNumber.offset);
        dout.writeInt(transactions.size());
        for (Transaction t : transactions) {
            t.serialize(dout);
        }
        dout.flush();
        writeZNodeEnforceOwnership(tableSpace, checkPointFile, buffer.toByteArray(), null);
    } catch (IOException err) {
        throw new DataStorageManagerException(err);
    }
    Collection<PostCheckpointAction> result = new ArrayList<>();
    String tableSpaceDirectory = getTableSpaceZNode(tableSpace);
    List<String> stream = zkGetChildren(tableSpaceDirectory);
    for (String p : stream) {
        if (isTransactionsFile(p)) {
            try {
                byte[] content = readZNode(checkPointFile, new Stat());
                if (content != null) {
                    LogSequenceNumber logPositionInFile = readLogSequenceNumberFromTransactionsFile(tableSpace, content, p);
                    if (sequenceNumber.after(logPositionInFile)) {
                        LOGGER.log(Level.FINEST, "transactions metadata file " + p + ". will be deleted after checkpoint end");
                        result.add(new DeleteZNodeAction(tableSpace, "transactions", "delete transactions file " + p, p));
                    }
                }
            } catch (DataStorageManagerException ignore) {
                LOGGER.log(Level.SEVERE, "Unparsable transactions file " + p, ignore);
                result.add(new DeleteZNodeAction(tableSpace, "transactions", "delete unparsable transactions file " + p, p));
            }
        }
    }
    return result;
}
Also used : DataStorageManagerException(herddb.storage.DataStorageManagerException) ArrayList(java.util.ArrayList) VisibleByteArrayOutputStream(herddb.utils.VisibleByteArrayOutputStream) LogSequenceNumber(herddb.log.LogSequenceNumber) IOException(java.io.IOException) ExtendedDataOutputStream(herddb.utils.ExtendedDataOutputStream) PostCheckpointAction(herddb.core.PostCheckpointAction) Stat(org.apache.zookeeper.data.Stat) Transaction(herddb.model.Transaction)

Example 39 with Transaction

use of herddb.model.Transaction in project herddb by diennea.

the class BookKeeperDataStorageManager method loadTransactions.

@Override
public void loadTransactions(LogSequenceNumber sequenceNumber, String tableSpace, Consumer<Transaction> consumer) throws DataStorageManagerException {
    try {
        String file = getTablespaceTransactionsFile(tableSpace, sequenceNumber);
        byte[] content = readZNode(file, new Stat());
        boolean exists = content != null;
        LOGGER.log(Level.INFO, "loadTransactions " + sequenceNumber + " for tableSpace " + tableSpace + " from file " + file + " (exists: " + exists + ")");
        if (!exists) {
            return;
        }
        try (InputStream input = new ByteArrayInputStream(content);
            ExtendedDataInputStream din = new ExtendedDataInputStream(input)) {
            // version
            long version = din.readVLong();
            // flags for future implementations
            long flags = din.readVLong();
            if (version != 1 || flags != 0) {
                throw new DataStorageManagerException("corrupted transaction list file " + file);
            }
            String readname = din.readUTF();
            if (!readname.equals(tableSpace)) {
                throw new DataStorageManagerException("file " + file + " is not for spablespace " + tableSpace);
            }
            long ledgerId = din.readZLong();
            long offset = din.readZLong();
            if (ledgerId != sequenceNumber.ledgerId || offset != sequenceNumber.offset) {
                throw new DataStorageManagerException("file " + file + " is not for sequence number " + sequenceNumber);
            }
            int numTransactions = din.readInt();
            for (int i = 0; i < numTransactions; i++) {
                Transaction tx = Transaction.deserialize(tableSpace, din);
                consumer.accept(tx);
            }
        }
    } catch (IOException err) {
        throw new DataStorageManagerException(err);
    }
}
Also used : ExtendedDataInputStream(herddb.utils.ExtendedDataInputStream) DataStorageManagerException(herddb.storage.DataStorageManagerException) Stat(org.apache.zookeeper.data.Stat) Transaction(herddb.model.Transaction) ByteArrayInputStream(java.io.ByteArrayInputStream) SimpleByteArrayInputStream(herddb.utils.SimpleByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ExtendedDataInputStream(herddb.utils.ExtendedDataInputStream) SimpleByteArrayInputStream(herddb.utils.SimpleByteArrayInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException)

Example 40 with Transaction

use of herddb.model.Transaction in project herddb by diennea.

the class SimpleScanTest method testCloseResultSetsOnCloseConnection.

@Test
public void testCloseResultSetsOnCloseConnection() throws Exception {
    try (Server server = new Server(herddb.jdbc.TestUtils.newServerConfigurationWithAutoPort(folder.newFolder().toPath()))) {
        server.start();
        server.waitForStandaloneBoot();
        try (HDBClient client = new HDBClient(new ClientConfiguration(folder.newFolder().toPath()))) {
            client.setClientSideMetadataProvider(new StaticClientSideMetadataProvider(server));
            try (BasicHerdDBDataSource dataSource = new BasicHerdDBDataSource(client)) {
                try (Connection con = dataSource.getConnection();
                    Statement statement = con.createStatement()) {
                    statement.execute("CREATE TABLE mytable (k1 string primary key, n1 int, l1 long, t1 timestamp, nu string, b1 bool, d1 double)");
                }
                try (Connection con = dataSource.getConnection();
                    PreparedStatement statement = con.prepareStatement("INSERT INTO mytable(k1,n1,l1,t1,nu,b1,d1) values(?,?,?,?,?,?,?)")) {
                    for (int n = 0; n < 10; ++n) {
                        int i = 1;
                        statement.setString(i++, "mykey_" + n);
                        statement.setInt(i++, n);
                        statement.setLong(i++, n);
                        statement.setTimestamp(i++, new java.sql.Timestamp(System.currentTimeMillis()));
                        statement.setString(i++, null);
                        statement.setBoolean(i++, true);
                        statement.setDouble(i++, n + 0.5);
                        statement.addBatch();
                    }
                    int[] batches = statement.executeBatch();
                    Assert.assertEquals(10, batches.length);
                    for (int batch : batches) {
                        Assert.assertEquals(1, batch);
                    }
                }
                try (Connection con = dataSource.getConnection()) {
                    con.setAutoCommit(false);
                    Transaction tx;
                    try (Statement s = con.createStatement()) {
                        // force the creation of the transaction, by issuing a DML command
                        s.executeUpdate("UPDATE mytable set n1=1 where k1 ='aaa'");
                    }
                    try (PreparedStatement statement = con.prepareStatement("SELECT n1, k1 FROM mytable")) {
                        statement.setFetchSize(1);
                        ResultSet rs = statement.executeQuery();
                        assertTrue(rs.next());
                        List<Transaction> transactions = server.getManager().getTableSpaceManager(TableSpace.DEFAULT).getTransactions();
                        assertEquals(1, transactions.size());
                        tx = transactions.get(0);
                        assertEquals(1, tx.getRefCount());
                    }
                    // close statement -> close result set -> transaction refcount = 0
                    // closing of scanners is non blocking, we have to wait
                    TestUtils.waitForCondition(() -> tx.getRefCount() == 0, NOOP, 100);
                }
                Transaction tx;
                try (Connection con = dataSource.getConnection()) {
                    con.setAutoCommit(false);
                    try (Statement s = con.createStatement()) {
                        // force the creation of the transaction, by issuing a DML command
                        s.executeUpdate("UPDATE mytable set n1=1 where k1 ='aaa'");
                    }
                    PreparedStatement statement = con.prepareStatement("SELECT n1, k1 FROM mytable");
                    statement.setFetchSize(1);
                    ResultSet rs = statement.executeQuery();
                    assertTrue(rs.next());
                    List<Transaction> transactions = server.getManager().getTableSpaceManager(TableSpace.DEFAULT).getTransactions();
                    assertEquals(1, transactions.size());
                    tx = transactions.get(0);
                    assertEquals(1, tx.getRefCount());
                }
                // close connection -> close statement -> close result set -> transaction refcount = 0 (and rolled back)
                TestUtils.waitForCondition(() -> tx.getRefCount() == 0, NOOP, 100);
            }
        }
    }
}
Also used : Server(herddb.server.Server) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) StaticClientSideMetadataProvider(herddb.server.StaticClientSideMetadataProvider) HDBClient(herddb.client.HDBClient) Transaction(herddb.model.Transaction) ResultSet(java.sql.ResultSet) ClientConfiguration(herddb.client.ClientConfiguration) Test(org.junit.Test)

Aggregations

Transaction (herddb.model.Transaction)43 DataStorageManagerException (herddb.storage.DataStorageManagerException)29 StatementExecutionException (herddb.model.StatementExecutionException)25 ArrayList (java.util.ArrayList)23 LogSequenceNumber (herddb.log.LogSequenceNumber)22 Table (herddb.model.Table)21 DDLException (herddb.model.DDLException)19 DataScanner (herddb.model.DataScanner)19 TransactionContext (herddb.model.TransactionContext)19 CommitLogResult (herddb.log.CommitLogResult)18 LogEntry (herddb.log.LogEntry)18 LogNotAvailableException (herddb.log.LogNotAvailableException)18 Index (herddb.model.Index)18 StatementExecutionResult (herddb.model.StatementExecutionResult)18 List (java.util.List)18 HashMap (java.util.HashMap)17 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)17 Map (java.util.Map)16 DataScannerException (herddb.model.DataScannerException)15 ScanStatement (herddb.model.commands.ScanStatement)15