2007-06-12 Don Allingham <don@gramps-project.org>

* src/ViewManager.py: detection and recovery from db errors
	* src/GrampsDb/_GrampsDBDir.py: detection and recovery from db errors
	* src/GrampsDb/_GrampsBSDDB.py: detection and recovery from db errors
	* src/DbManager.py: detection and recovery from db errors
	* src/DbState.py: detection and recovery from db errors
	* src/ArgHandler.py: detection and recovery from db errors



svn: r8539
This commit is contained in:
Don Allingham 2007-06-12 23:31:40 +00:00
parent e05e6b4edd
commit c730a8f5c4
7 changed files with 319 additions and 167 deletions

View File

@ -1,3 +1,11 @@
2007-06-12 Don Allingham <don@gramps-project.org>
* src/ViewManager.py: detection and recovery from db errors
* src/GrampsDb/_GrampsDBDir.py: detection and recovery from db errors
* src/GrampsDb/_GrampsBSDDB.py: detection and recovery from db errors
* src/DbManager.py: detection and recovery from db errors
* src/DbState.py: detection and recovery from db errors
* src/ArgHandler.py: detection and recovery from db errors
2007-06-11 Don Allingham <don@gramps-project.org>
* src/ViewManager.py: Improve backup strategy
* src/GrampsDb/_GrampsDBDir.py: Improve backup strategy

View File

@ -449,7 +449,8 @@ class ArgHandler:
filetype = Mime.get_type(rf)
self.vm.read_recent_file(rf, filetype)
elif os.path.isdir(rf):
if os.path.isfile(os.path.join(rf, "name.txt")):
if os.path.isfile(os.path.join(rf, "name.txt")) and \
not os.path.isfile(os.path.join(rf,"need_recover"):
self.vm.read_recent_file(rf, 'x-directory/normal')
#-------------------------------------------------------------------------

View File

@ -160,7 +160,7 @@ class DbManager:
if not node:
self.connect.set_sensitive(False)
self.rename.set_sensitive(False)
self.repair.set_sensitive(False)
self.repair.hide()
self.remove.set_sensitive(False)
else:
if store.get_value(node, OPEN_COL):
@ -168,7 +168,15 @@ class DbManager:
else:
self.connect.set_sensitive(True)
self.rename.set_sensitive(True)
self.repair.set_sensitive(True)
if store.get_value(node, STOCK_COL) == gtk.STOCK_DIALOG_ERROR:
path = store.get_value(node, PATH_COL)
if os.path.isfile(os.path.join(path,"person.gbkp")):
self.repair.show()
else:
self.repair.hide()
else:
self.repair.hide()
self.remove.set_sensitive(True)
def build_interface(self):
@ -349,6 +357,8 @@ class DbManager:
db.load(dirname, None)
GrampsDbUtils.Backup.restore(db)
db.close()
self.dbstate.no_database()
self.populate()
def new_db(self, obj):
"""
@ -436,6 +446,8 @@ def icon_values(dirpath, active):
"""
if dirpath == active:
return (True, gtk.STOCK_OPEN)
if os.path.isfile(os.path.join(dirpath,"need_recover")):
return (True, gtk.STOCK_DIALOG_ERROR)
else:
return (False, "")

View File

@ -45,9 +45,10 @@ class DbState(GrampsDBCallback):
just a place holder until a real DB is assigned.
"""
GrampsDBCallback.__init__(self)
self.db = GrampsDbBase()
self.open = False
self.active = None
self.db = GrampsDbBase()
self.open = False
self.active = None
self.sighndl = None
def change_active_person(self, person):
"""

View File

@ -760,10 +760,11 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
> result_list = [i for i in find_backlink_handles(handle)]
"""
# Use the secondary index to locate all the reference_map entries
# that include a reference to the object we are looking for.
print "FIND BACKLINK"
referenced_cur = self.get_reference_map_referenced_cursor()
print "refcur", referenced_cur
try:
ret = referenced_cur.set(handle)
@ -772,6 +773,7 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
while (ret is not None):
(key, data) = ret
print key, data
# data values are of the form:
# ((primary_object_class_name, primary_object_handle),
@ -794,8 +796,6 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
referenced_cur.close()
return
def __delete_primary_from_reference_map(self, hndl, transaction, txn=None):
"""
Remove all references to the primary object from the reference_map.

View File

@ -53,6 +53,7 @@ import _GrampsDbConst as const
from _GrampsDbExceptions import FileVersionError
from BasicUtils import UpdateCallback
from _GrampsCursor import GrampsCursor
import Errors
_MINVERSION = 9
_DBVERSION = 13
@ -82,6 +83,9 @@ REF_MAP = "reference_map"
REF_PRI = "primary_map"
REF_REF = "referenced_map"
DBERRS = (db.DBRunRecoveryError, db.DBAccessError, db.DBPageNotFoundError, db.DBInvalidArgError)
def find_surname(key,data):
return str(data[3][5])
@ -197,104 +201,130 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
dbmap.open(fname, table_name, dbtype, self.__open_flags(), 0666)
return dbmap
def _all_handles(self,table):
def __all_handles(self,table):
return table.keys(self.txn)
def __log_error(self):
mypath = os.path.join(self.get_save_path(),"need_recover")
ofile = open(mypath, "w")
ofile.close()
def __get_cursor(self, table):
try:
return GrampsDBDirCursor(table, self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def get_person_cursor(self):
return GrampsDBDirCursor(self.person_map, self.txn)
return self.__get_cursor(self.person_map)
def get_family_cursor(self):
return GrampsDBDirCursor(self.family_map, self.txn)
return self.__get_cursor(self.family_map)
def get_event_cursor(self):
return GrampsDBDirCursor(self.event_map, self.txn)
return self.__get_cursor(self.event_map)
def get_place_cursor(self):
return GrampsDBDirCursor(self.place_map, self.txn)
return self.__get_cursor(self.place_map)
def get_source_cursor(self):
return GrampsDBDirCursor(self.source_map, self.txn)
return self.__get_cursor(self.source_map)
def get_media_cursor(self):
return GrampsDBDirCursor(self.media_map, self.txn)
return self.__get_cursor(self.media_map)
def get_repository_cursor(self):
return GrampsDBDirCursor(self.repository_map, self.txn)
return self.__get_cursor(self.repository_map)
def get_note_cursor(self):
return GrampsDBDirCursor(self.note_map, self.txn)
return self.__get_cursor(self.note_map)
def has_person_handle(self,handle):
def __has_handle(self, table, handle):
try:
return table.get(str(handle), txn=self.txn) != None
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def has_person_handle(self, handle):
"""
returns True if the handle exists in the current Person database.
"""
return self.person_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.person_map, handle)
def has_family_handle(self,handle):
"""
returns True if the handle exists in the current Family database.
"""
return self.family_map.get(str(handle),txn=self.txn) != None
return self.__has_handle(self.family_map, handle)
def has_object_handle(self,handle):
"""
returns True if the handle exists in the current MediaObjectdatabase.
"""
return self.media_map.get(str(handle),txn=self.txn) != None
return self.__has_handle(self.media_map, handle)
def has_repository_handle(self,handle):
"""
returns True if the handle exists in the current Repository database.
"""
return self.repository_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.repository_map, handle)
def has_note_handle(self,handle):
"""
returns True if the handle exists in the current Note database.
"""
return self.note_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.note_map, handle)
def has_event_handle(self,handle):
"""
returns True if the handle exists in the current Repository database.
"""
return self.event_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.event_map, handle)
def has_place_handle(self,handle):
"""
returns True if the handle exists in the current Repository database.
"""
return self.place_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.place_map, handle)
def has_source_handle(self,handle):
def has_source_handle(self, handle):
"""
returns True if the handle exists in the current Repository database.
"""
return self.source_map.get(str(handle), txn=self.txn) != None
return self.__has_handle(self.source_map, handle)
def get_raw_person_data(self,handle):
return self.person_map.get(str(handle), txn=self.txn)
def __get_raw_data(self, table, handle):
try:
return table.get(str(handle), txn=self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def get_raw_person_data(self, handle):
return self.__get_raw_data(self.person_map, handle)
def get_raw_family_data(self,handle):
return self.family_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.family_map, handle)
def get_raw_object_data(self,handle):
return self.media_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.media_map, handle)
def get_raw_place_data(self,handle):
return self.place_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.place_map, handle)
def get_raw_event_data(self,handle):
return self.event_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.event_map, handle)
def get_raw_source_data(self,handle):
return self.source_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.source_map, handle)
def get_raw_repository_data(self,handle):
return self.repository_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.repository_map, handle)
def get_raw_note_data(self,handle):
return self.note_map.get(str(handle), txn=self.txn)
return self.__get_raw_data(self.note_map, handle)
# cursors for lookups in the reference_map for back reference
# lookups. The reference_map has three indexes:
@ -304,17 +334,36 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
# the main index is unique, the others allow duplicate entries.
def get_reference_map_cursor(self):
return GrampsDBDirAssocCursor(self.reference_map, self.txn)
try:
return GrampsDBDirAssocCursor(self.reference_map, self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def get_reference_map_primary_cursor(self):
return GrampsDBDirDupCursor(self.reference_map_primary_map, self.txn)
try:
return GrampsDBDirDupCursor(self.reference_map_primary_map, self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def get_reference_map_referenced_cursor(self):
return GrampsDBDirDupCursor(self.reference_map_referenced_map, self.txn)
try:
return GrampsDBDirDupCursor(self.reference_map_referenced_map, self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
# These are overriding the GrampsDbBase's methods of saving metadata
# because we now have txn-capable metadata table
def set_default_person_handle(self, handle):
try:
return self.__set_default_person_handle(handle)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __set_default_person_handle(self, handle):
"""sets the default Person to the passed instance"""
if not self.readonly:
if self.UseTXN:
@ -329,6 +378,13 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.metadata.sync()
def get_default_person(self):
try:
return self.__get_default_person()
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __get_default_person(self):
"""returns the default Person of the database"""
person = self.get_person_from_handle(self.get_default_handle())
if person:
@ -346,7 +402,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.metadata.sync()
return None
def _set_column_order(self, col_list, name):
def __set_column_order(self, col_list, name):
if self.metadata and not self.readonly:
if self.UseTXN:
# Start transaction if needed
@ -360,14 +416,29 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.metadata.sync()
def version_supported(self):
dbversion = self.metadata.get('version',default=0)
return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
try:
dbversion = self.metadata.get('version',default=0)
return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def need_upgrade(self):
dbversion = self.metadata.get('version',default=0)
return not self.readonly and dbversion < _DBVERSION
try:
dbversion = self.metadata.get('version',default=0)
return not self.readonly and dbversion < _DBVERSION
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def load(self, name, callback, mode="w"):
try:
return self.__load(name, callback, mode)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __load(self, name, callback, mode="w"):
if self.db_is_open:
self.close()
@ -380,6 +451,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
callback(12)
self.full_name = os.path.abspath(name)
self.path = self.full_name
self.brief_name = os.path.basename(name)
self.env = db.DBEnv()
@ -417,7 +489,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
# If we cannot work with this DB version,
# it makes no sense to go further
if not self.version_supported:
self._close_early()
self.__close_early()
self.family_map = self.__open_table(self.full_name, FAMILY_TBL)
self.place_map = self.__open_table(self.full_name, PLACES_TBL)
@ -490,9 +562,13 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
return 1
def load_from(self, other_database, filename, callback):
self.load(filename,callback)
db_copy(other_database,self,callback)
return 1
try:
self.load(filename,callback)
db_copy(other_database,self,callback)
return 1
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __load_metadata(self):
# name display formats
@ -660,7 +736,14 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.rmap_index = len(self.repository_map)
self.nmap_index = len(self.note_map)
def rebuild_secondary(self,callback=None):
def rebuild_secondary(self, callback=None):
try:
self.__rebuild_secondary(callback)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __rebuild_secondary(self, callback=None):
if self.readonly:
return
@ -683,8 +766,8 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
( self.reference_map_referenced_map, REF_REF),
]
for (db, name) in items:
db.close()
for (database, name) in items:
database.close()
env = db.DB(self.env)
env.remove(_mkname(self.full_name, name), name)
if callback:
@ -702,6 +785,13 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
callback(12)
def find_backlink_handles(self, handle, include_classes=None):
try:
return self.__find_backlink_handles(handle, include_classes)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __find_backlink_handles(self, handle, include_classes=None):
"""
Find all objects that hold a reference to the object handle.
Returns an interator over a list of (class_name,handle) tuples.
@ -752,8 +842,6 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
referenced_cur.close()
return
def __delete_primary_from_reference_map(self,handle,transaction,txn=None):
"""
Remove all references to the primary object from the reference_map.
@ -789,9 +877,9 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
# Now that the cursor is closed, we can remove things
for main_key in remove_list:
self._remove_reference(main_key,transaction,txn)
self.__remove_reference(main_key,transaction,txn)
def _update_reference_map(self, obj, transaction, txn=None):
def __update_reference_map(self, obj, transaction, txn=None):
"""
If txn is given, then changes are written right away using txn.
"""
@ -859,17 +947,17 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
for (ref_class_name,ref_handle) in new_references:
data = ((CLASS_TO_KEY_MAP[obj.__class__.__name__],handle),
(CLASS_TO_KEY_MAP[ref_class_name],ref_handle),)
self._add_reference((handle,ref_handle),data,transaction,txn)
self.__add_reference((handle,ref_handle),data,transaction,txn)
# handle deletion of old references
for (ref_class_name,ref_handle) in no_longer_required_references:
try:
self._remove_reference((handle,ref_handle),transaction,txn)
self.__remove_reference((handle,ref_handle),transaction,txn)
except:
# ignore missing old reference
pass
def _remove_reference(self,key,transaction,txn=None):
def __remove_reference(self,key,transaction,txn=None):
"""
Removes the reference specified by the key,
preserving the change in the passed transaction.
@ -884,7 +972,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
transaction.add(REFERENCE_KEY,str(key),old_data,None)
transaction.reference_del.append(str(key))
def _add_reference(self,key,data,transaction,txn=None):
def __add_reference(self,key,data,transaction,txn=None):
"""
Adds the reference specified by the key and the data,
preserving the change in the passed transaction.
@ -902,6 +990,13 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
transaction.reference_add.append((str(key),data))
def reindex_reference_map(self,callback):
try:
self.__reindex_reference_map(callback)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __reindex_reference_map(self,callback):
"""
Reindex all primary records in the database.
This will be a slow process for large databases.
@ -981,7 +1076,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
the_txn = self.env.txn_begin()
else:
the_txn = None
self._update_reference_map(obj,transaction,the_txn)
self.__update_reference_map(obj,transaction,the_txn)
if not self.UseTXN:
self.reference_map.sync()
if the_txn:
@ -1002,9 +1097,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
find_referenced_handle,open_flags)
callback(6)
return
def _close_metadata(self):
def __close_metadata(self):
if not self.readonly:
if self.UseTXN:
# Start transaction if needed
@ -1077,7 +1170,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.metadata.close()
def _close_early(self):
def __close_early(self):
"""
Bail out if the incompatible version is discovered:
* close cleanly to not damage data/env
@ -1095,13 +1188,20 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
"data between different database versions.")
def close(self):
try:
self.__close()
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __close(self):
if not self.db_is_open:
return
if self.UseTXN:
self.env.txn_checkpoint()
self._close_metadata()
self.__close_metadata()
self.name_group.close()
self.surnames.close()
self.id_trans.close()
@ -1126,16 +1226,6 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.source_map.close()
self.media_map.close()
self.event_map.close()
# Attempt to clear log sequence numbers, to make database portable
# This will only work for python2.5 and higher
# Comment this our because it causes crashes.
# To reproduce the crash, create a new DB, import example.gramps, open and close the db a few times.
# try:
# self.env.lsn_reset(self.full_name)
# except AttributeError:
# pass
self.env.close()
try:
@ -1219,7 +1309,14 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
if not self.UseTXN:
self.event_map.sync()
def set_name_group_mapping(self,name,group):
def set_name_group_mapping(self, name, group):
try:
self.__set_name_group_mapping(name, group)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __set_name_group_mapping(self, name, group):
if not self.readonly:
if self.UseTXN:
# Start transaction if needed
@ -1239,8 +1336,12 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.emit('person-rebuild')
def build_surname_list(self):
self.surname_list = list(set(self.surnames.keys()))
self.sort_surname_list()
try:
self.surname_list = list(set(self.surnames.keys()))
self.sort_surname_list()
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def remove_from_surname_list(self,person):
"""
@ -1254,90 +1355,97 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.surname_list.remove(unicode(name))
except ValueError:
pass
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def _get_obj_from_gramps_id(self,val,tbl,class_init,prim_tbl):
if tbl.has_key(str(val)):
data = tbl.get(str(val),txn=self.txn)
obj = class_init()
### FIXME: this is a dirty hack that works without no
### sensible explanation. For some reason, for a readonly
### database, secondary index returns a primary table key
### corresponding to the data, not the data.
if self.readonly:
tuple_data = prim_tbl.get(data,txn=self.txn)
def __get_obj_from_gramps_id(self,val,tbl,class_init,prim_tbl):
try:
if tbl.has_key(str(val)):
data = tbl.get(str(val),txn=self.txn)
obj = class_init()
### FIXME: this is a dirty hack that works without no
### sensible explanation. For some reason, for a readonly
### database, secondary index returns a primary table key
### corresponding to the data, not the data.
if self.readonly:
tuple_data = prim_tbl.get(data,txn=self.txn)
else:
tuple_data = pickle.loads(data)
obj.unserialize(tuple_data)
return obj
else:
tuple_data = pickle.loads(data)
obj.unserialize(tuple_data)
return obj
else:
return None
return None
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def get_person_from_gramps_id(self,val):
"""
Finds a Person in the database from the passed gramps' ID.
If no such Person exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.id_trans,Person,
self.person_map)
return self.__get_obj_from_gramps_id(val, self.id_trans, Person,
self.person_map)
def get_family_from_gramps_id(self,val):
"""
Finds a Family in the database from the passed gramps' ID.
If no such Family exists, None is return.
"""
return self._get_obj_from_gramps_id(val,self.fid_trans,Family,
self.family_map)
return self.__get_obj_from_gramps_id(val, self.fid_trans, Family,
self.family_map)
def get_event_from_gramps_id(self,val):
"""
Finds an Event in the database from the passed gramps' ID.
If no such Family exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.eid_trans,Event,
self.event_map)
return self.__get_obj_from_gramps_id(val, self.eid_trans,Event,
self.event_map)
def get_place_from_gramps_id(self,val):
"""
Finds a Place in the database from the passed gramps' ID.
If no such Place exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.pid_trans,Place,
self.place_map)
return self.__get_obj_from_gramps_id(val, self.pid_trans, Place,
self.place_map)
def get_source_from_gramps_id(self,val):
"""
Finds a Source in the database from the passed gramps' ID.
If no such Source exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.sid_trans,Source,
self.source_map)
return self.__get_obj_from_gramps_id(val,self.sid_trans,Source,
self.source_map)
def get_object_from_gramps_id(self,val):
"""
Finds a MediaObject in the database from the passed gramps' ID.
If no such MediaObject exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.oid_trans,MediaObject,
self.media_map)
return self.__get_obj_from_gramps_id(val,self.oid_trans,MediaObject,
self.media_map)
def get_repository_from_gramps_id(self,val):
"""
Finds a Repository in the database from the passed gramps' ID.
If no such Repository exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.rid_trans,Repository,
self.repository_map)
return self.__get_obj_from_gramps_id(val,self.rid_trans,Repository,
self.repository_map)
def get_note_from_gramps_id(self,val):
"""
Finds a Note in the database from the passed gramps' ID.
If no such Note exists, None is returned.
"""
return self._get_obj_from_gramps_id(val,self.nid_trans,Note,
self.note_map)
return self.__get_obj_from_gramps_id(val,self.nid_trans,Note,
self.note_map)
def __commit_base(self, obj, data_map, key, update_list, add_list,
transaction, change_time):
transaction, change_time):
"""
Commits the specified object to the database, storing the changes
as part of the transaction.
@ -1356,7 +1464,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
the_txn = self.env.txn_begin()
else:
the_txn = None
self._update_reference_map(obj,transaction,txn=the_txn)
self.__update_reference_map(obj,transaction,txn=the_txn)
data_map.put(handle,obj.serialize(),txn=the_txn)
if not self.UseTXN:
data_map.sync()
@ -1364,7 +1472,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
the_txn.commit()
old_data = None
else:
self._update_reference_map(obj,transaction)
self.__update_reference_map(obj,transaction)
old_data = data_map.get(handle,txn=self.txn)
new_data = obj.serialize()
transaction.add(key,handle,old_data,new_data)
@ -1383,7 +1491,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
retlist.append(str(handle))
return retlist
def _get_from_handle(self, handle, class_type, data_map):
def __get_from_handle(self, handle, class_type, data_map):
try:
data = data_map.get(str(handle),txn=self.txn)
except:
@ -1398,7 +1506,7 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
return newobj
return None
def _find_from_handle(self,handle,transaction,class_type,dmap,add_func):
def __find_from_handle(self, handle, transaction, class_type, dmap, add_func):
obj = class_type()
handle = str(handle)
if dmap.has_key(handle):
@ -1409,7 +1517,14 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
add_func(obj,transaction)
return obj
def transaction_begin(self,msg="",batch=False,no_magic=False):
def transaction_begin(self, msg="", batch=False, no_magic=False):
try:
return self.__transaction_begin(msg, batch, no_magic)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __transaction_begin(self, msg="", batch=False, no_magic=False):
"""
Creates a new Transaction tied to the current UNDO database. The
transaction has no effect until it is committed using the
@ -1441,7 +1556,14 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
return transaction
def transaction_commit(self,transaction,msg):
def transaction_commit(self, transaction, msg):
try:
self.__transaction_commit(transaction, msg)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def __transaction_commit(self, transaction, msg):
# Start BSD DB transaction -- DBTxn
if self.UseTXN:
@ -1496,49 +1618,63 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
self.txn = None
def undo(self,update_history=True):
print "Undoing it"
if self.UseTXN:
self.txn = self.env.txn_begin()
status = GrampsDbBase.undo(self,update_history)
if self.UseTXN:
if status:
self.txn.commit()
else:
self.txn.abort()
self.txn = None
return status
try:
if self.UseTXN:
self.txn = self.env.txn_begin()
status = GrampsDbBase.undo(self,update_history)
if self.UseTXN:
if status:
self.txn.commit()
else:
self.txn.abort()
self.txn = None
return status
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def redo(self,update_history=True):
print "Redoing it"
if self.UseTXN:
self.txn = self.env.txn_begin()
status = GrampsDbBase.redo(self,update_history)
if self.UseTXN:
if status:
self.txn.commit()
else:
self.txn.abort()
self.txn = None
return status
try:
if self.UseTXN:
self.txn = self.env.txn_begin()
status = GrampsDbBase.redo(self,update_history)
if self.UseTXN:
if status:
self.txn.commit()
else:
self.txn.abort()
self.txn = None
return status
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def undo_reference(self,data,handle):
if data == None:
self.reference_map.delete(handle,txn=self.txn)
else:
self.reference_map.put(handle,data,txn=self.txn)
try:
if data == None:
self.reference_map.delete(handle,txn=self.txn)
else:
self.reference_map.put(handle,data,txn=self.txn)
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def undo_data(self,data,handle,db_map,signal_root):
if data == None:
self.emit(signal_root + '-delete',([handle],))
db_map.delete(handle,txn=self.txn)
else:
ex_data = db_map.get(handle,txn=self.txn)
if ex_data:
signal = signal_root + '-update'
try:
if data == None:
self.emit(signal_root + '-delete',([handle],))
db_map.delete(handle,txn=self.txn)
else:
signal = signal_root + '-add'
db_map.put(handle,data,txn=self.txn)
self.emit(signal,([handle],))
ex_data = db_map.get(handle,txn=self.txn)
if ex_data:
signal = signal_root + '-update'
else:
signal = signal_root + '-add'
db_map.put(handle,data,txn=self.txn)
self.emit(signal,([handle],))
except DBERRS, msg:
self.__log_error()
raise Errors.DbError(msg)
def gramps_upgrade(self,callback=None):
UpdateCallback.__init__(self,callback)
@ -1556,8 +1692,8 @@ class GrampsDBDir(GrampsDbBase,UpdateCallback):
class BdbTransaction(Transaction):
def __init__(self,msg,db,batch=False,no_magic=False):
Transaction.__init__(self,msg,db,batch,no_magic)
def __init__(self, msg, db, batch=False, no_magic=False):
Transaction.__init__(self, msg, db, batch, no_magic)
self.reference_del = []
self.reference_add = []

View File

@ -81,9 +81,6 @@ import GrampsDisplay
from GrampsDb import ProgressMonitor
import ProgressDialog
from bsddb.db import DBRunRecoveryError, DBAccessError, \
DBPageNotFoundError, DBInvalidArgError
def show_url(dialog, link, user_data):
"""
Sets the about dialog callback for showing the URL. Call the GrampsDisplay
@ -900,7 +897,7 @@ class ViewManager:
self.post_load()
def import_data(self, obj):
if self.state.db.db_is_open:
if self.state.db.is_open():
self.db_loader.import_file()
self.post_load()
@ -972,7 +969,7 @@ class ViewManager:
os.chdir(os.path.dirname(filename))
except:
print "could not change directory"
except DBRunRecoveryError, msg:
except Errors.DbError, msg:
QuestionDialog.ErrorDialog(
_("Low level database corruption detected"),
_("GRAMPS has detected a problem in the underlying "
@ -981,18 +978,15 @@ class ViewManager:
"the next time you open this database. If this "
"problem persists, create a new database, import "
"from a backup database, and report the problem to "
"gramps-bugs@lists.sourceforge.net."))
except (DBAccessError, DBPageNotFoundError, DBInvalidArgError), msg:
QuestionDialog.ErrorDialog(
_("Could not open file: %s") % filename,
str(msg[1]))
"gramps-bugs@lists.sourceforge.net.") + "\n\n" + str(msg.value))
self.state.no_database()
except Exception:
LOG.error("Failed to open database.", exc_info=True)
return True
def save_as_activate(self, obj):
if self.state.db.db_is_open:
if self.state.db.is_open():
(filename, filetype) = self.db_loader.save_as()
self.post_load_newdb(filename, filetype)