1N/A * See the file LICENSE for redistribution information. 1N/A * Copyright (c) 1996, 1997, 1998 1N/A * Sleepycat Software. All rights reserved. 1N/A * Copyright (c) 1995, 1996 1N/A * The President and Fellows of Harvard University. All rights reserved. 1N/A * This code is derived from software contributed to Berkeley by 1N/A * Redistribution and use in source and binary forms, with or without 1N/A * modification, are permitted provided that the following conditions 1N/A * 1. Redistributions of source code must retain the above copyright 1N/A * notice, this list of conditions and the following disclaimer. 1N/A * 2. Redistributions in binary form must reproduce the above copyright 1N/A * notice, this list of conditions and the following disclaimer in the 1N/A * documentation and/or other materials provided with the distribution. 1N/A * 3. All advertising materials mentioning features or use of this software 1N/A * must display the following acknowledgement: 1N/A * This product includes software developed by the University of 1N/A * California, Berkeley and its contributors. 1N/A * 4. Neither the name of the University nor the names of its contributors 1N/A * may be used to endorse or promote products derived from this software 1N/A * without specific prior written permission. 1N/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1N/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1N/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1N/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1N/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1N/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1N/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1N/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1N/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1N/A#
endif /* not lint */ 1N/A * This file contains the top level routines of the transaction library. 1N/A * It assumes that a lock manager and log manager that conform to the db_log(3) 1N/A * and db_lock(3) interfaces exist. 1N/A * Initialize a transaction region in shared memory. 1N/A * Return 0 on success, errno on failure. 1N/A /* maxtxns is already initialized. */ 1N/A * If we ever do more types of locking and logging, this changes. 1N/A /* Validate arguments. */ 1N/A /* Now, create the transaction manager structure and set its fields. */ 1N/A /* Initialize the transaction manager structure. */ 1N/A /* Fill in region-related fields. */ 1N/A /* Check if valid region. */ 1N/A * Since we only get here if threading is turned on, we 1N/A * know that we have spinlocks, so the offset is going 1N/A * to be ignored. We put 0 here as a valid placeholder. 1N/A * Panic a transaction region. 1N/A * PUBLIC: void __txn_panic __P((DB_ENV *)); 1N/A * This is a wrapper to the actual begin process. Normal txn_begin() 1N/A * allocates a DB_TXN structure for the caller, while txn_xa_begin() does 1N/A * not. Other than that, both call into the common __txn_begin code(). 1N/A * Internally, we use TXN_DETAIL structures, but the DB_TXN structure 1N/A * provides access to the transaction ID and the offset in the transaction 1N/A * region of the TXN_DETAIL structure. 1N/A * XA version of txn_begin. 1N/A * PUBLIC: int __txn_xa_begin __P((DB_ENV *, DB_TXN *)); 1N/A * Normal DB version of txn_begin. 1N/A * We do not have to write begin records (and if we do not, then we 1N/A * need never write records for read-only transactions). However, 1N/A * we do need to find the current LSN so that we can store it in the 1N/A * transaction structure, so we can know where to take checkpoints. 1N/A /* Make sure that last_txnid is not going to wrap around. */ 1N/A "Transaction ID wrapping.",
1N/A "Snapshot your database and start a new log.");
1N/A /* Allocate a new transaction detail structure. */ 1N/A /* Place transaction on active transaction list. */ 1N/A * Commit a transaction. 1N/A * If there are any log records, write a log record and sync 1N/A * the log, else do no log writes. If the commit is for a child 1N/A * transaction, we do not need to commit the child synchronously 1N/A * since if its parent aborts, it will abort too and its parent 1N/A * (or ultimate ancestor) will write synchronously. 1N/A * If this is the senior ancestor (i.e., it has no children), then we 1N/A * can release all the child transactions since everyone is committing. 1N/A * Then we can release this transaction. If this is not the ultimate 1N/A * ancestor, then we can neither free it or its children. 1N/A * Abort a transcation. 1N/A * Flush the log so a future commit is guaranteed to succeed. 1N/A * We indicate that a transaction is an XA transaction by putting 1N/A * a valid size in the xid.size fiels. XA requires that the transaction 1N/A * be either ENDED or SUSPENDED when prepare is called, so we know 1N/A * that if the xa_status isn't in one of those states, but we are 1N/A * calling prepare that we are not an XA transaction. 1N/A * Return the transaction ID associated with a particular transaction 1N/A * Close the transaction region, does not imply a checkpoint. 1N/A * This function had better only be called once per process 1N/A * (i.e., not per thread), so there should be no synchronization 1N/A * Remove the transaction region. 1N/A/* Internal routines. */ 1N/A * Return 0 if the txnp is reasonable, otherwise returns EINVAL. 1N/A * Child transactions could be marked committed which is OK. 1N/A /* Release the locks. */ 1N/A /* End the transaction. */ 1N/A * Child transactions that are committing cannot be released until 1N/A * the parent commits, since the parent may abort, causing the child 1N/A * If the transaction aborted, we can remove it from its parent links. 1N/A * If it committed, then we need to leave it on, since the parent can 1N/A /* Free the space. */ 1N/A * Undo the transaction with id txnid. Returns 0 on success and 1N/A * This is the simplest way to code this, but if the mallocs during 1N/A * recovery turn out to be a performance issue, we can do the 1N/A * allocation here and use DB_DBT_USERMEM. 1N/A * The dispatch routine returns the lsn of the record 1N/A * before the current one in the key_lsn argument. 1N/A * Transaction checkpoint. 1N/A * If either kbytes or minutes is non-zero, then we only take the checkpoint 1N/A * more than "minutes" minutes have passed since the last checkpoint or if 1N/A * more than "kbytes" of log data have been written since the last checkpoint. 1N/A * When taking a checkpoint, find the oldest active transaction and figure out 1N/A * its first LSN. This is the lowest LSN we can checkpoint, since any record 1N/A * written after since that point may be involved in a transaction and may 1N/A * therefore need to be undone in the case of an abort. 1N/A * Check if we need to run recovery. 1N/A * If we checked time and data and didn't go to checkpoint, 1N/A * We have to find an LSN such that all transactions begun 1N/A * before that LSN are complete. 1N/A * Look through the active transactions for the 1N/A * memp_sync may change the lsn you pass it, so don't pass it 1N/A * the actual ckp_lsn, pass it a temp instead. 1N/A * ret == DB_INCOMPLETE means that there are still buffers to 1N/A * flush, the checkpoint is not complete. Wait and try again. 1N/A "txn_checkpoint: system failure in memp_sync %s\n",
1N/A "txn_checkpoint: log failed at LSN [%ld %ld] %s\n",
1N/A * __txn_validate_region -- 1N/A * Called at every interface to verify if the region has changed size, 1N/A * and if so, to remap the region in and reset the process' pointers. 1N/A /* Reset region information. */ 1N/A /* Throw the new space on the free list. */ 1N/A * Allocate a bunch of extra active structures to handle any 1N/A * that have been created since we unlocked the region. 1N/A /* Free any children of this transaction. */ 1N/A /* Free the transaction detail in the region. */ 1N/A /* Now remove from its parent. */ 1N/A * __txn_is_ancestor -- 1N/A * Determine if a transaction is an ancestor of another transaction. 1N/A * This is used during lock promotion when we do not have the per-process 1N/A * data structures that link parents together. Instead, we'll have to 1N/A * follow the links in the transaction region. 1N/A * PUBLIC: int __txn_is_ancestor __P((DB_TXNMGR *, size_t, size_t));