#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""
BSDDBTxn class: Wrapper for BSDDB transaction-oriented methods
"""
#-------------------------------------------------------------------------
#
# BSDDBTxn
#
#-------------------------------------------------------------------------
from __future__ import print_function, with_statement
[docs]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
[docs] 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
[docs] 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)
[docs] def stat(self):
"""
Return a dictionary of transaction statistics
"""
if self.env:
return self.env.txn_stat()
[docs] 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
[docs] def abort(self):
"""
Abort the transaction
"""
if self.txn:
self.txn.abort()
self.txn = None
[docs] def commit(self, flags=0):
"""
End the transaction, committing any changes to the databases
"""
if self.txn:
self.txn.commit(flags)
self.txn = None
[docs] def id(self):
"""
Return the unique transaction id associated with the specified
transaction
"""
if self.txn:
return self.txn.id()
[docs] def prepare(self, gid):
"""
Initiate the beginning of a two-phase commit
"""
if self.txn:
self.txn.prepare(gid)
[docs] 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
[docs] def get(self, key, default=None, txn=None, **kwargs):
"""
Returns the data object associated with key
"""
return self.db.get(key, default, txn or self.txn, **kwargs)
[docs] def pget(self, key, default=None, txn=None, **kwargs):
"""
Returns the primary key, given the secondary one, and associated data
"""
return self.db.pget(key, default, txn or self.txn, **kwargs)
[docs] def put(self, key, data, txn=None, **kwargs):
"""
Stores the key/data pair in the database
"""
return self.db.put(key, data, txn or self.txn, **kwargs)
[docs] def delete(self, key, txn=None, **kwargs):
"""
Removes a key/data pair from the database
"""
self.db.delete(key, txn or self.txn, **kwargs)
# test code
if __name__ == "__main__":
print("1")
from ..config import config
import sys
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
from bsddb3 import db, dbshelve
else:
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_LOG | db.DB_INIT_TXN)
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()