All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mckoi.database.TransactionJournal Maven / Gradle / Ivy

Go to download

A full SQL database system with JDBC driver that can be embedded in a Java application or operate as a stand-alone server with clients connecting via TCP/IP.

The newest version!
/**
 * com.mckoi.database.TransactionJournal  19 Nov 2000
 *
 * Mckoi SQL Database ( http://www.mckoi.com/database )
 * Copyright (C) 2000, 2001, 2002  Diehl and Associates, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License Version 2 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * Version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Change Log:
 * 
 * 
 */

package com.mckoi.database;

import com.mckoi.util.IntegerVector;
import com.mckoi.util.BlockIntegerList;
import java.util.ArrayList;

/**
 * The list of all primitive operations to the database that a transaction
 * performed.  It includes the list of all rows added or removed to all tables,
 * and the tables created and dropped and any table that had constraint
 * modifications.
 * 

* This journal is updated inside a Transaction. When the transaction is * completed, this journal is used both to determine if the transaction * can be committed, and also to update the changes to the data that a * transaction has made. *

* THREADING: The journal update commands are synchronized because they need * to be atomic operations and can be accessed by multiple threads. * * @author Tobias Downer */ final class TransactionJournal { /** * Journal commands. */ static byte TABLE_ADD = 1; // Add a row to a table. // (params: table_id, row_index) static byte TABLE_REMOVE = 2; // Remove a row from a table. // (params: table_id, row_index) static byte TABLE_CREATE = 3; // Create a new table. // (params: table_id) static byte TABLE_DROP = 4; // Drop a table. // (params: table_id) static byte TABLE_CONSTRAINT_ALTER = 5; // Alter constraints of a table. // (params: table_id) /** * The number of entries in this journal. */ private int journal_entries; /** * The list of table's that have been touched by this transaction. A table * is touched if the 'getTable' method in the transaction is used to * get the table. This means even if a table is just read from, the * journal will record that the table was touched. *

* This object records the 'table_id' of the touched tables in a sorted * list. */ private IntegerVector touched_tables; /** * A byte[] array that represents the set of commands a transaction * performed on a table. */ private byte[] command_journal; /** * An IntegerVector that is filled with parameters from the command journal. * For example, a 'TABLE_ADD' journal log will have as parameters the * table id the row was added to, and the row_index that was added. */ private IntegerVector command_parameters; /** * Optimization, these flags are set to true when various types of journal * entries are made to the transaction journal. */ private boolean has_added_table_rows, has_removed_table_rows, has_created_tables, has_dropped_tables, has_constraint_alterations; /** * Constructs a blank journal. */ TransactionJournal() { journal_entries = 0; command_journal = new byte[16]; command_parameters = new IntegerVector(32); touched_tables = new IntegerVector(8); has_added_table_rows = false; has_removed_table_rows = false; has_created_tables = false; has_dropped_tables = false; has_constraint_alterations = false; } /** * Adds a command to the journal. */ private void addCommand(byte command) { if (journal_entries >= command_journal.length) { // Resize command array. int grow_size = Math.min(4000, journal_entries); byte[] new_command_journal = new byte[journal_entries + grow_size]; System.arraycopy(command_journal, 0, new_command_journal, 0, journal_entries); command_journal = new_command_journal; } command_journal[journal_entries] = command; ++journal_entries; } /** * Adds a parameter to the journal command parameters. */ private void addParameter(int param) { command_parameters.addInt(param); } /** * Logs in this journal that the transaction touched the given table id. */ synchronized void entryAddTouchedTable(int table_id) { int pos = touched_tables.sortedIndexOf(table_id); // If table_id already in the touched table list. if (pos < touched_tables.size() && touched_tables.intAt(pos) == table_id) { return; } // If position to insert >= size of the touched tables set then add to // the end of the set. if (pos >= touched_tables.size()) { touched_tables.addInt(table_id); } else { // Otherwise, insert into sorted order. touched_tables.insertIntAt(table_id, pos); } } /** * Makes a journal entry that a table entry has been added to the table with * the given id. */ synchronized void entryAddTableRow(int table_id, int row_index) { // has_added_table_rows = true; addCommand(TABLE_ADD); addParameter(table_id); addParameter(row_index); } /** * Makes a journal entry that a table entry has been removed from the table * with the given id. */ synchronized void entryRemoveTableRow(int table_id, int row_index) { // has_removed_table_rows = true; addCommand(TABLE_REMOVE); addParameter(table_id); addParameter(row_index); } /** * Makes a journal entry that a table with the given 'table_id' has been * created by this transaction. */ synchronized void entryTableCreate(int table_id) { has_created_tables = true; addCommand(TABLE_CREATE); addParameter(table_id); } /** * Makes a journal entry that a table with the given 'table_id' has been * dropped by this transaction. */ synchronized void entryTableDrop(int table_id) { has_dropped_tables = true; addCommand(TABLE_DROP); addParameter(table_id); } /** * Makes a journal entry that a table with the given 'table_id' has been * altered by this transaction. */ synchronized void entryTableConstraintAlter(int table_id) { has_constraint_alterations = true; addCommand(TABLE_CONSTRAINT_ALTER); addParameter(table_id); } /** * Generates an array of MasterTableJournal objects that specify the * changes that occur to each table affected by this transaction. Each array * element represents a change to an individual table in the conglomerate * that changed as a result of this transaction. *

* This is used when a transaction successfully commits and we need to log * the transaction changes with the master table. *

* If no changes occurred to a table, then no entry is returned here. */ MasterTableJournal[] makeMasterTableJournals() { ArrayList table_journals = new ArrayList(); int param_index = 0; MasterTableJournal master_journal = null; for (int i = 0 ; i < journal_entries; ++i) { byte c = command_journal[i]; if (c == TABLE_ADD || c == TABLE_REMOVE) { int table_id = command_parameters.intAt(param_index); int row_index = command_parameters.intAt(param_index + 1); param_index += 2; // Do we already have this table journal? if (master_journal == null || master_journal.getTableID() != table_id) { // Try to find the journal in the list. int size = table_journals.size(); master_journal = null; for (int n = 0; n < size && master_journal == null; ++n) { MasterTableJournal test_journal = (MasterTableJournal) table_journals.get(n); if (test_journal.getTableID() == table_id) { master_journal = test_journal; } } // Not found so add to list. if (master_journal == null) { master_journal = new MasterTableJournal(table_id); table_journals.add(master_journal); } } // Add this change to the table journal. master_journal.addEntry(c, row_index); } else if (c == TABLE_CREATE || c == TABLE_DROP || c == TABLE_CONSTRAINT_ALTER) { param_index += 1; } else { throw new Error("Unknown journal command."); } } // Return the array. return (MasterTableJournal[]) table_journals.toArray( new MasterTableJournal[table_journals.size()]); } /** * Returns the list of tables id's that were dropped by this journal. */ IntegerVector getTablesDropped() { IntegerVector dropped_tables = new IntegerVector(); // Optimization, quickly return empty set if we know there are no tables. if (!has_dropped_tables) { return dropped_tables; } int param_index = 0; for (int i = 0 ; i < journal_entries; ++i) { byte c = command_journal[i]; if (c == TABLE_ADD || c == TABLE_REMOVE) { param_index += 2; } else if (c == TABLE_CREATE || c == TABLE_CONSTRAINT_ALTER) { param_index += 1; } else if (c == TABLE_DROP) { dropped_tables.addInt(command_parameters.intAt(param_index)); param_index += 1; } else { throw new Error("Unknown journal command."); } } return dropped_tables; } /** * Returns the list of tables id's that were created by this journal. */ IntegerVector getTablesCreated() { IntegerVector created_tables = new IntegerVector(); // Optimization, quickly return empty set if we know there are no tables. if (!has_created_tables) { return created_tables; } int param_index = 0; for (int i = 0 ; i < journal_entries; ++i) { byte c = command_journal[i]; if (c == TABLE_ADD || c == TABLE_REMOVE) { param_index += 2; } else if (c == TABLE_DROP || c == TABLE_CONSTRAINT_ALTER) { param_index += 1; } else if (c == TABLE_CREATE) { created_tables.addInt(command_parameters.intAt(param_index)); param_index += 1; } else { throw new Error("Unknown journal command."); } } return created_tables; } /** * Returns the list of tables id's that were constraint altered by this * journal. */ IntegerVector getTablesConstraintAltered() { IntegerVector caltered_tables = new IntegerVector(); // Optimization, quickly return empty set if we know there are no tables. if (!has_constraint_alterations) { return caltered_tables; } int param_index = 0; for (int i = 0 ; i < journal_entries; ++i) { byte c = command_journal[i]; if (c == TABLE_ADD || c == TABLE_REMOVE) { param_index += 2; } else if (c == TABLE_DROP || c == TABLE_CREATE) { param_index += 1; } else if (c == TABLE_CONSTRAINT_ALTER) { caltered_tables.addInt(command_parameters.intAt(param_index)); param_index += 1; } else { throw new Error("Unknown journal command."); } } return caltered_tables; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy