Add function decorator to catch dabatase errors
svn: r13163
This commit is contained in:
		@@ -202,6 +202,20 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        self.secondary_connected = False
 | 
			
		||||
        self.has_changed = False
 | 
			
		||||
 | 
			
		||||
    def catch_db_error(func):
 | 
			
		||||
        """
 | 
			
		||||
        Decorator function for catching database errors.  If *func* throws
 | 
			
		||||
        one of the exceptions in DBERRS, the error is logged and a DbError
 | 
			
		||||
        exception is raised.
 | 
			
		||||
        """
 | 
			
		||||
        def try_(*args, **kwargs):
 | 
			
		||||
            try:
 | 
			
		||||
                return func(*args, **kwargs)
 | 
			
		||||
            except DBERRS, msg:
 | 
			
		||||
                self.__log_error()
 | 
			
		||||
                raise Errors.DbError(msg)
 | 
			
		||||
        return try_
 | 
			
		||||
 | 
			
		||||
    def __open_db(self, file_name, table_name, dbtype=db.DB_HASH, flags=0):
 | 
			
		||||
        dbmap = db.DB(self.env)
 | 
			
		||||
        dbmap.set_pagesize(DBPAGE)
 | 
			
		||||
@@ -248,48 +262,34 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
    # the referenced_handle index: the referenced_handle
 | 
			
		||||
    # the main index is unique, the others allow duplicate entries.
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def get_reference_map_cursor(self):
 | 
			
		||||
        """
 | 
			
		||||
        Returns a reference to a cursor over the reference map
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            return GrampsDBDirAssocCursor(self.reference_map, self.txn)
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        return GrampsDBDirAssocCursor(self.reference_map, self.txn)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def get_reference_map_primary_cursor(self):
 | 
			
		||||
        """
 | 
			
		||||
        Returns a reference to a cursor over the reference map primary map
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            return GrampsDBDirAssocCursor(self.reference_map_primary_map, 
 | 
			
		||||
        return GrampsDBDirAssocCursor(self.reference_map_primary_map, 
 | 
			
		||||
                                        self.txn)
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def get_reference_map_referenced_cursor(self):
 | 
			
		||||
        """
 | 
			
		||||
        Returns a reference to a cursor over the reference map referenced map
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            return GrampsDBDirAssocCursor(self.reference_map_referenced_map, 
 | 
			
		||||
        return GrampsDBDirAssocCursor(self.reference_map_referenced_map, 
 | 
			
		||||
                                        self.txn)
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
 | 
			
		||||
    # These are overriding the GrampsDbRead'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):
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def set_default_person_handle(self, handle):
 | 
			
		||||
        """Set the default Person to the passed instance."""
 | 
			
		||||
        if not self.readonly:
 | 
			
		||||
            # Start transaction
 | 
			
		||||
@@ -297,14 +297,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
                txn.put('default', str(handle))
 | 
			
		||||
            self.emit('home-person-changed')
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    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):
 | 
			
		||||
        """Return the default Person of the database."""
 | 
			
		||||
        person = self.get_person_from_handle(self.get_default_handle())
 | 
			
		||||
        if person:
 | 
			
		||||
@@ -328,33 +322,15 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
            with BSDDBTxn(self.env, self.metadata) as txn:
 | 
			
		||||
                txn.put(name, col_list)   
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def version_supported(self):
 | 
			
		||||
        try:
 | 
			
		||||
            dbversion = self.metadata.get('version', default=0)
 | 
			
		||||
            return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
    
 | 
			
		||||
        dbversion = self.metadata.get('version', default=0)
 | 
			
		||||
        return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def need_upgrade(self):
 | 
			
		||||
        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=DBMODE_W):
 | 
			
		||||
        try:
 | 
			
		||||
            if self.__check_readonly(name):
 | 
			
		||||
                mode = DBMODE_R
 | 
			
		||||
            else:
 | 
			
		||||
                write_lock_file(name)
 | 
			
		||||
            return self.__load(name, callback, mode)
 | 
			
		||||
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        dbversion = self.metadata.get('version', default=0)
 | 
			
		||||
        return not self.readonly and dbversion < _DBVERSION
 | 
			
		||||
 | 
			
		||||
    def __check_readonly(self, name):
 | 
			
		||||
        """
 | 
			
		||||
@@ -376,7 +352,13 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        # All tests passed.  Inform caller that we are NOT read only
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def __load(self, name, callback, mode=DBMODE_W):
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def load(self, name, callback, mode=DBMODE_W):
 | 
			
		||||
 | 
			
		||||
        if self.__check_readonly(name):
 | 
			
		||||
            mode = DBMODE_R
 | 
			
		||||
        else:
 | 
			
		||||
            write_lock_file(name)        
 | 
			
		||||
 | 
			
		||||
        if self.db_is_open:
 | 
			
		||||
            self.close()
 | 
			
		||||
@@ -519,17 +501,17 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
 | 
			
		||||
    def __close_undodb(self):
 | 
			
		||||
        if not self.readonly:
 | 
			
		||||
            self.undodb.close()
 | 
			
		||||
            try:
 | 
			
		||||
                self.undodb.close()
 | 
			
		||||
            except db.DBNoSuchFileError:
 | 
			
		||||
                pass                
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def load_from(self, other_database, filename, callback):
 | 
			
		||||
        try:
 | 
			
		||||
            self.load(filename, callback)
 | 
			
		||||
            from gen.utils import db_copy
 | 
			
		||||
            db_copy(other_database, self, callback)
 | 
			
		||||
            return 1
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        self.load(filename, callback)
 | 
			
		||||
        from gen.utils import db_copy
 | 
			
		||||
        db_copy(other_database, self, callback)
 | 
			
		||||
        return 1
 | 
			
		||||
 | 
			
		||||
    def __load_metadata(self):
 | 
			
		||||
        # name display formats
 | 
			
		||||
@@ -645,14 +627,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        self.rmap_index = len(self.repository_map)
 | 
			
		||||
        self.nmap_index = len(self.note_map)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@@ -692,14 +668,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        if callback:
 | 
			
		||||
            callback(12)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    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.
 | 
			
		||||
        
 | 
			
		||||
@@ -896,14 +866,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
            transaction.add(REFERENCE_KEY, TXNADD, str(key), None, data)
 | 
			
		||||
            #transaction.reference_add.append((str(key), data))
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    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.
 | 
			
		||||
        
 | 
			
		||||
@@ -1035,18 +999,9 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
              "version of GRAMPS.\nPlease upgrade to the "
 | 
			
		||||
              "corresponding version or use XML for porting "
 | 
			
		||||
              "data between different database versions."))
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def close(self):
 | 
			
		||||
        try:
 | 
			
		||||
            self.__close()
 | 
			
		||||
            clear_lock_file(self.get_save_path())
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        except IOError:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def __close(self):
 | 
			
		||||
        if not self.db_is_open:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
@@ -1079,11 +1034,7 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        self.media_map.close()
 | 
			
		||||
        self.event_map.close()
 | 
			
		||||
        self.env.close()
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.__close_undodb()
 | 
			
		||||
        except db.DBNoSuchFileError:
 | 
			
		||||
            pass
 | 
			
		||||
        self.__close_undodb()
 | 
			
		||||
 | 
			
		||||
        self.person_map     = None
 | 
			
		||||
        self.family_map     = None
 | 
			
		||||
@@ -1099,6 +1050,11 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        self.metadata       = None
 | 
			
		||||
        self.db_is_open     = False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            clear_lock_file(self.get_save_path())
 | 
			
		||||
        except IOError:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def create_id(self):
 | 
			
		||||
        return "%08x%08x" % ( int(time.time()*10000), 
 | 
			
		||||
                              self.rand.randint(0, maxint))
 | 
			
		||||
@@ -1310,18 +1266,19 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        self.__do_remove(handle, transaction, self.note_map, 
 | 
			
		||||
                              NOTE_KEY)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def set_name_group_mapping(self, name, group):
 | 
			
		||||
        """
 | 
			
		||||
        Make name group under the value of group.
 | 
			
		||||
        
 | 
			
		||||
        If group =None, the old grouping is deleted. 
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            self.__set_name_group_mapping(name, group)
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
            
 | 
			
		||||
        if not self.readonly:
 | 
			
		||||
            # Start transaction
 | 
			
		||||
            with BSDDBTxn(self.env, self.name_group) as txn:
 | 
			
		||||
                name = str(name)
 | 
			
		||||
                data = txn.get(name)
 | 
			
		||||
                if data is not None:
 | 
			
		||||
                    txn.delete(name)
 | 
			
		||||
                if group is not None:
 | 
			
		||||
                    txn.put(name, group)
 | 
			
		||||
            self.emit('person-rebuild')
 | 
			
		||||
 | 
			
		||||
    def __set_name_group_mapping(self, name, group):
 | 
			
		||||
        if not self.readonly:
 | 
			
		||||
            # Start transaction
 | 
			
		||||
@@ -1337,12 +1294,9 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
    def sort_surname_list(self):
 | 
			
		||||
        self.surname_list.sort(key=locale.strxfrm)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def build_surname_list(self):
 | 
			
		||||
        try:
 | 
			
		||||
            self.surname_list = sorted(map(unicode, set(self.surnames.keys())), key=locale.strxfrm)
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        self.surname_list = sorted(map(unicode, set(self.surnames.keys())), key=locale.strxfrm)
 | 
			
		||||
 | 
			
		||||
    def add_to_surname_list(self, person, batch_transaction):
 | 
			
		||||
        if batch_transaction:
 | 
			
		||||
@@ -1355,6 +1309,7 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        else:
 | 
			
		||||
            self.surname_list.insert(i, name)
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def remove_from_surname_list(self, person):
 | 
			
		||||
        """
 | 
			
		||||
        Check whether there are persons with the same surname left in
 | 
			
		||||
@@ -1373,9 +1328,6 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
                del self.surname_list[i-1]
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            pass
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        finally:
 | 
			
		||||
            cursor.close()
 | 
			
		||||
        
 | 
			
		||||
@@ -1601,14 +1553,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
            return newobj
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    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):
 | 
			
		||||
        """
 | 
			
		||||
        Create a new Transaction tied to the current UNDO database. 
 | 
			
		||||
        
 | 
			
		||||
@@ -1638,7 +1584,8 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
                _db = db.DB(self.env)
 | 
			
		||||
                _db.remove(_mkname(self.full_name, REF_REF), REF_REF)
 | 
			
		||||
        return transaction
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    @catch_db_error
 | 
			
		||||
    def transaction_commit(self, transaction, msg):
 | 
			
		||||
        if self._LOG_ALL:
 | 
			
		||||
            LOG.debug("%s: Transaction commit '%s'\n"
 | 
			
		||||
@@ -1647,14 +1594,10 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
 | 
			
		||||
        if self.readonly:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            transaction.commit(msg)
 | 
			
		||||
            self.undodb.commit(transaction, msg)
 | 
			
		||||
            self.__after_commit(transaction, msg)
 | 
			
		||||
            self.has_changed = True
 | 
			
		||||
        except DBERRS, msg:
 | 
			
		||||
            self.__log_error()
 | 
			
		||||
            raise Errors.DbError(msg)
 | 
			
		||||
        transaction.commit(msg)
 | 
			
		||||
        self.undodb.commit(transaction, msg)
 | 
			
		||||
        self.__after_commit(transaction, msg)
 | 
			
		||||
        self.has_changed = True
 | 
			
		||||
 | 
			
		||||
    def __after_commit(self, transaction, msg):
 | 
			
		||||
        """
 | 
			
		||||
@@ -1832,10 +1775,25 @@ def write_lock_file(name):
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
 | 
			
		||||
    import sys
 | 
			
		||||
    import os, sys, pdb
 | 
			
		||||
    
 | 
			
		||||
    d = GrampsDBDir()
 | 
			
		||||
    d.load(sys.argv[1], lambda x: x)
 | 
			
		||||
    if len(sys.argv) > 1:
 | 
			
		||||
        db_name = sys.argv[1]
 | 
			
		||||
    else:
 | 
			
		||||
        db_home = os.path.join(os.environ['HOME'], '.gramps','grampsdb')
 | 
			
		||||
        for dir in os.listdir(db_home):
 | 
			
		||||
            db_path = os.path.join(db_home, dir)
 | 
			
		||||
            db_fn = os.path.join(db_path, 'name.txt')
 | 
			
		||||
            if os.stat(db_fn):
 | 
			
		||||
                f = open(db_fn)
 | 
			
		||||
                db_name = f.read()
 | 
			
		||||
                if db_name == 'Small Example':
 | 
			
		||||
                    break
 | 
			
		||||
    print "loading", db_path
 | 
			
		||||
    d.load(db_path, lambda x: x)
 | 
			
		||||
 | 
			
		||||
    print d.get_default_person()
 | 
			
		||||
 | 
			
		||||
    with d.get_person_cursor() as c:
 | 
			
		||||
        for key, data in c:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user