# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2009 Gerald W. Britton # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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 for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id: bsddbtxn.py 12786 2009-07-11 15:32:37Z gbritton $ """ BSDDBTxn class: Wrapper for BSDDB transaction-oriented methods """ #------------------------------------------------------------------------- # # BSDDBTxn # #------------------------------------------------------------------------- class BSDDBTxn(object): """ Wrapper for BSDDB methods that set up and manage transactions. Implements context management functionality allowing constructs like: with BSDDBTxn(env) as txn: DB.get(txn=txn) DB.put(txn=txn) DB.delete(txn=txn) and other transaction-oriented DB access methods, where "env" is a BSDDB DBEnv object and "DB" is a BSDDB database object. Transactions are automatically begun when the "with" statement is executed and automatically committed when control flows off the end of the "with" statement context, either implicitly by reaching the end of the indentation level or explicity if a "return" statement is encountered or an exception is raised. """ __slots__ = ['env', 'db', 'txn', 'parent'] def __init__(self, env, db=None): """ Initialize transaction instance """ self.env = env self.db = db self.txn = None # Context manager methods def __enter__(self, parent=None, **kwargs): """ Context manager entry method Begin the transaction """ self.txn = self.begin(parent, **kwargs) self.parent = parent return self def __exit__(self, exc_type, exc_val, exc_tb): """ Context manager exit function Commit the transaction if no exception occurred """ if exc_type is not None: return False if self.txn: self.commit() return True # Methods implementing txn_ methods in DBEnv def begin(self, *args, **kwargs): """ Create and begin a new transaction. A DBTxn object is returned """ self.txn = self.env.txn_begin(*args, **kwargs) return self.txn def checkpoint(self, *args, **kwargs): """ Flush the underlying memory pool, write a checkpoint record to the log and then flush the log """ if self.env: self.env.txn_checkpoint(*args, **kwargs) def stat(self): """ Return a dictionary of transaction statistics """ if self.env: return self.env.txn_stat() def recover(self): """ Returns a list of tuples (GID, TXN) of transactions prepared but still unresolved """ if self.env: return self.env.txn_recover() # Methods implementing DBTxn methods def abort(self): """ Abort the transaction """ if self.txn: self.txn.abort() self.txn = None def commit(self, flags=0): """ End the transaction, committing any changes to the databases """ if self.txn: self.txn.commit(flags) self.txn = None def id(self): """ Return the unique transaction id associated with the specified transaction """ if self.txn: return self.txn.id() def prepare(self, gid): """ Initiate the beginning of a two-phase commit """ if self.txn: self.txn.prepare(gid) def discard(self): """ Release all the per-process resources associated with the specified transaction, neither committing nor aborting the transaction """ if self.txn: self.txn.discard() self.txn = None # Methods implementing DB methods within the transaction context def get(self, key, default=None, txn=None, **kwargs): """ Returns the data object associated with key """ if txn == None: txn = self.txn return self.db.get(key, default, txn, **kwargs) def pget(self, key, default=None, txn=None, **kwargs): """ Returns the primary key, given the secondary one, and associated data """ if txn == None: txn = self.txn return self.db.pget(key, default, txn, **kwargs) def put(self, key, data, txn=None, **kwargs): """ Stores the key/data pair in the database """ if txn == None: txn = self.txn return self.db.put(key, data, txn, **kwargs) def delete(self, key, txn=None, **kwargs): """ Removes a key/data pair from the database """ if txn == None: txn = self.txn self.db.delete(key, txn, **kwargs) # test code if __name__ == "__main__": print "1" from bsddb import db, dbshelve print "2" x = db.DBEnv() print "3" x.open('/tmp', db.DB_CREATE | db.DB_PRIVATE |\ db.DB_INIT_MPOOL | db.DB_INIT_LOCK |\ db.DB_INIT_LOG | db.DB_INIT_TXN | db.DB_THREAD) print "4" d = dbshelve.DBShelf(x) print "5" #from tran import BSDDBTxn as T print "6" T = BSDDBTxn with T(x) as tx: print "stat", tx.stat() print "id", tx.id() tx.checkpoint()