Finally, let's look at the transaction sharing area. First, each process still has a Data Structure _ db_txnmgr {}: ** Thetransactionmanagerencapsulatesthetransactionsystem. Itcontains * referencestothelogandlockmanagersaswellasthestatethatkeeps * track
Finally, let's look at the transaction sharing area. First, there is still a Data Structure _ db_txnmgr {}:/** The transaction manager encapsulates the transaction system. it contains * references to the log and lock managers as well as the state that keeps * track
Finally, let's look at the transaction sharing area.
First, each process still has a Data Structure _ db_txnmgr {}:
/** The transaction manager encapsulates the transaction system. It contains* references to the log and lock managers as well as the state that keeps* track of the shared memory region.*/struct __db_txnmgr {/* These fields need to be protected for multi-threaded support. */ db_mutex_t *mutexp; /* Synchronization. */ /* list of active transactions */ TAILQ_HEAD(_chain, __db_txn) txn_chain;/* These fields are not protected. */ REGINFO reginfo; /* Region information. */ DB_ENV *dbenv; /* Environment. */ int (*recover) /* Recovery dispatch routine */ __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); u_int32_t flags; /* DB_TXN_NOSYNC, DB_THREAD */ DB_TXNREGION *region; /* address of shared memory region */ void *mem; /* address of the shalloc space */};
It also has a reginfo field pointing to the description of the shared area and a pointer mem pointing to the shared area.
/** Layout of the shared memory region.* The region consists of a DB_TXNREGION structure followed by a large* pool of shalloc'd memory which is used to hold TXN_DETAIL structures* and thread mutexes (which are dynamically allocated).*/struct __db_txnregion { RLAYOUT hdr; /* Shared memory region header. */ u_int32_t magic; /* transaction magic number */ u_int32_t version; /* version number */ u_int32_t maxtxns; /* maximum number of active txns */ u_int32_t last_txnid; /* last transaction id given out */ DB_LSN pending_ckp; /* last checkpoint did not finish */ DB_LSN last_ckp; /* lsn of the last checkpoint */ time_t time_ckp; /* time of last checkpoint */ u_int32_t logtype; /* type of logging */ u_int32_t locktype; /* lock type */ u_int32_t naborts; /* number of aborted transactions */ u_int32_t ncommits; /* number of committed transactions */ u_int32_t nbegins; /* number of begun transactions */ SH_TAILQ_HEAD(_active) active_txn; /* active transaction list */};
In the shared area, apart from a common header hdr field, the most important thing is that there is a list of active_txn fields for all active transactions.
Now let's take a look at the creation, opening, and initialization of these data structures and shared areas.
Call the txn_open () function in the db_appinit () function to open or connect to a transaction sharing region:
if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL, LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC), mode, dbenv, &dbenv->tx_info)) != 0) goto err;
Txn_open is defined as follows:
Inttxn_open (path, flags, mode, dbenv, mgrpp) const char * path; u_int32_t flags; int mode; DB_ENV * dbenv; DB_TXNMGR ** mgrpp; {DB_TXNMGR * tmgrp; u_int32_t maxtxns; int ret;/* Validate arguments. */verify the parameters first and then use malloc to create the transaction manager structure that each process has./* Now, create the transaction manager structure and set its fields. */if (ret = _ OS _calloc (1, sizeof (DB_TXNMGR), & tmgrp ))! = 0) return (ret); and Initialize the transaction manager structure/* Initialize the transaction manager structure. */tmgrp-> mutexp = NULL; tmgrp-> dbenv = dbenv; tmgrp-> recover = dbenv-> tx_recover = NULL? _ Db_dispatch: dbenv-> tx_recover; tmgrp-> flags = LF_ISSET (DB_TXN_NOSYNC | DB_THREAD); TAILQ_INIT (& tmgrp-> txn_chain ); now create or connect to a transaction sharing region/* Join/create the txn region. */fill in the region description information REGINFO {}, and then call the _ db_rattach () function to create or open a shared region tmgrp-> reginfo. dbenv = dbenv; tmgrp-> reginfo. appname = DB_APP_NONE; if (path = NULL) tmgrp-> reginfo. path = NULL; else if (ret = _ OS _strdup (path, & tmgrp-> reginfo. path ))! = 0) goto err; tmgrp-> reginfo. file = DEFAULT_TXN_FILE; tmgrp-> reginfo. mode = mode; tmgrp-> reginfo. size = TXN_REGION_SIZE (maxtxns); tmgrp-> reginfo. dbflags = flags; tmgrp-> reginfo. addr = NULL; tmgrp-> reginfo. fd =-1; tmgrp-> reginfo. flags = dbenv-> tx_max = 0? REGION_SIZEDEF: 0; if (ret = _ db_rattach (& tmgrp-> reginfo ))! = 0) goto err;/* Fill in region-related fields. */tmgrp-> region = tmgrp-> reginfo. addr; tmgrp-> mem = & tmgrp-> region [1]; if (F_ISSET (& tmgrp-> reginfo, REGION_CREATED) {tmgrp-> region-> maxtxns = maxtxns; if (ret = _ txn_init (tmgrp-> region ))! = 0) goto err;} else if (tmgrp-> region-> magic! = DB_TXNMAGIC) {/* Check if valid region. */_ db_err (dbenv, "txn_open: Bad magic number"); ret = EINVAL; goto err ;}// if this is a new transaction sharing region, initialize it. Like MPOOL, // use the _ shmalloc function to manage the memory in the shared area if (LF_ISSET (DB_THREAD) {if (ret = _ db_shalloc (tmgrp-> mem, sizeof (db_mutex_t), MUTEX_ALIGNMENT, & tmgrp-> mutexp) = 0)/** Since we only get here if threading is turned on, we * know that we have spinlocks, so the offset is going * to be ignored. we put 0 here as a valid placeholder. */_ db_mutex_init (tmgrp-> mutexp, 0); if (ret! = 0) goto err;} UNLOCK_TXNREGION (tmgrp); * mgrpp = tmgrp; return (0); err: if (tmgrp-> reginfo. addr! = NULL) {if (tmgrp-> mutexp! = NULL) _ db_shalloc_free (tmgrp-> mem, tmgrp-> mutexp); UNLOCK_TXNREGION (tmgrp); (void) _ db_rdetach (& tmgrp-> reginfo ); if (F_ISSET (& tmgrp-> reginfo, REGION_CREATED) (void) txn_unlink (path, 1, dbenv);} if (tmgrp-> reginfo. path! = NULL) _ OS _freestr (tmgrp-> reginfo. path); _ OS _free (tmgrp, sizeof (* tmgrp); return (ret );}
This function is the function called by txn_open () to initialize the transaction sharing region:
/** This file contains the top level routines of the transaction library.* It assumes that a lock manager and log manager that conform to the db_log(3)* and db_lock(3) interfaces exist.** Initialize a transaction region in shared memory.* Return 0 on success, errno on failure.*/static int__txn_init(txn_region) DB_TXNREGION *txn_region;{ time_t now; (void)time(&now); /* maxtxns is already initialized. */ txn_region->magic = DB_TXNMAGIC; txn_region->version = DB_TXNVERSION; txn_region->last_txnid = TXN_MINIMUM; /* * XXX * If we ever do more types of locking and logging, this changes. */ txn_region->logtype = 0; txn_region->locktype = 0; txn_region->time_ckp = now; ZERO_LSN(txn_region->last_ckp); ZERO_LSN(txn_region->pending_ckp); SH_TAILQ_INIT(&txn_region->active_txn); __db_shalloc_init((void *)&txn_region[1], TXN_REGION_SIZE(txn_region->maxtxns) - sizeof(DB_TXNREGION)); return (0);}
Where DB_TXN {} is the descriptor of each transaction (defined in the db_int.h file ):
/* The structure allocated for every transaction. */struct __db_txn { DB_TXNMGR *mgrp; /* Pointer to transaction manager. */ DB_TXN *parent; /* Pointer to transaction's parent. */ DB_LSN last_lsn; /* Lsn of last log write. */ u_int32_t txnid; /* Unique transaction id. */ size_t off; /* Detail structure within region. */ TAILQ_ENTRY(__db_txn) links; /* Links transactions off manager. */ TAILQ_HEAD(__kids, __db_txn) kids; /* Child transactions. */ TAILQ_ENTRY(__db_txn) klinks; /* Links child transactions. */#define TXN_MALLOC 0x01 /* Structure allocated by TXN system. */ u_int32_t flags;};typedef struct __txn_detail { u_int32_t txnid; /* current transaction id used to link free list also */ DB_LSN last_lsn; /* last lsn written for this txn */ DB_LSN begin_lsn; /* lsn of begin record */ size_t last_lock; /* offset in lock region of last lock for this transaction. */ size_t parent; /* Offset of transaction's parent. */#define TXN_UNALLOC 0#define TXN_RUNNING 1#define TXN_ABORTED 2#define TXN_PREPARED 3#define TXN_COMMITTED 4 u_int32_t status; /* status of the transaction */ SH_TAILQ_ENTRY links; /* free/active list */#define TXN_XA_ABORTED 1#define TXN_XA_DEADLOCKED 2#define TXN_XA_ENDED 3#define TXN_XA_PREPARED 4#define TXN_XA_STARTED 5#define TXN_XA_SUSPENDED 6 u_int32_t xa_status; /* XA status */ /* * XID (xid_t) structure: because these fields are logged, the * sizes have to be explicit. */ DB_XID xid; /* XA global transaction id */ u_int32_t bqual; /* bqual_length from XID */ u_int32_t gtrid; /* gtrid_length from XID */ int32_t format; /* XA format */} TXN_DETAIL;
Original article address: BDB transaction sharing region. Thank you for sharing it.