Implement locking for dbapi backends
This commit is contained in:
parent
0f7e8e73b9
commit
e3300cd55d
@ -45,7 +45,8 @@ from . import (DbReadBase, DbWriteBase, DbUndo, DBLOGNAME, DBUNDOFN,
|
|||||||
KEY_TO_CLASS_MAP, REFERENCE_KEY, PERSON_KEY, FAMILY_KEY,
|
KEY_TO_CLASS_MAP, REFERENCE_KEY, PERSON_KEY, FAMILY_KEY,
|
||||||
CITATION_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY,
|
CITATION_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY,
|
||||||
REPOSITORY_KEY, NOTE_KEY, TAG_KEY, TXNADD, TXNUPD, TXNDEL,
|
REPOSITORY_KEY, NOTE_KEY, TAG_KEY, TXNADD, TXNUPD, TXNDEL,
|
||||||
KEY_TO_NAME_MAP)
|
KEY_TO_NAME_MAP, DBMODE_R, DBMODE_W)
|
||||||
|
from .utils import write_lock_file, clear_lock_file
|
||||||
from ..errors import HandleError
|
from ..errors import HandleError
|
||||||
from ..utils.callback import Callback
|
from ..utils.callback import Callback
|
||||||
from ..updatecallback import UpdateCallback
|
from ..updatecallback import UpdateCallback
|
||||||
@ -581,7 +582,25 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def load(self, directory, callback=None, mode=None,
|
def __check_readonly(self, name):
|
||||||
|
"""
|
||||||
|
Return True if we don't have read/write access to the database,
|
||||||
|
otherwise return False (that is, we DO have read/write access)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# See if we write to the target directory at all?
|
||||||
|
if not os.access(name, os.W_OK):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# See if we lack write access to the database file
|
||||||
|
path = os.path.join(name, 'sqlite.db')
|
||||||
|
if os.path.isfile(path) and not os.access(path, os.W_OK):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# All tests passed. Inform caller that we are NOT read only
|
||||||
|
return False
|
||||||
|
|
||||||
|
def load(self, directory, callback=None, mode=DBMODE_W,
|
||||||
force_schema_upgrade=False,
|
force_schema_upgrade=False,
|
||||||
force_bsddb_upgrade=False,
|
force_bsddb_upgrade=False,
|
||||||
force_bsddb_downgrade=False,
|
force_bsddb_downgrade=False,
|
||||||
@ -592,6 +611,14 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
|||||||
"""
|
"""
|
||||||
If update is False: then don't update any files
|
If update is False: then don't update any files
|
||||||
"""
|
"""
|
||||||
|
if self.__check_readonly(directory):
|
||||||
|
mode = DBMODE_R
|
||||||
|
|
||||||
|
self.readonly = mode == DBMODE_R
|
||||||
|
|
||||||
|
if not self.readonly:
|
||||||
|
write_lock_file(directory)
|
||||||
|
|
||||||
# run backend-specific code:
|
# run backend-specific code:
|
||||||
self._initialize(directory, username, password)
|
self._initialize(directory, username, password)
|
||||||
|
|
||||||
@ -735,6 +762,12 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
|||||||
self._set_metadata('nmap_index', self.nmap_index)
|
self._set_metadata('nmap_index', self.nmap_index)
|
||||||
|
|
||||||
self._close()
|
self._close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
clear_lock_file(self.get_save_path())
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.db_is_open = False
|
self.db_is_open = False
|
||||||
self._directory = None
|
self._directory = None
|
||||||
|
|
||||||
|
@ -39,8 +39,9 @@ import logging
|
|||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
from ..plug import BasePluginManager
|
from ..plug import BasePluginManager
|
||||||
from ..const import PLUGINS_DIR, USER_PLUGINS
|
from ..const import PLUGINS_DIR, USER_PLUGINS
|
||||||
|
from ..constfunc import win, get_env_var
|
||||||
from ..config import config
|
from ..config import config
|
||||||
from .dbconst import DBLOGNAME
|
from .dbconst import DBLOGNAME, DBLOCKFN
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -179,3 +180,35 @@ def __index_surname(surn_list):
|
|||||||
else:
|
else:
|
||||||
surn = ""
|
surn = ""
|
||||||
return surn
|
return surn
|
||||||
|
|
||||||
|
def clear_lock_file(name):
|
||||||
|
try:
|
||||||
|
os.unlink(os.path.join(name, DBLOCKFN))
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
|
||||||
|
def write_lock_file(name):
|
||||||
|
if not os.path.isdir(name):
|
||||||
|
os.mkdir(name)
|
||||||
|
with open(os.path.join(name, DBLOCKFN), "w", encoding='utf8') as f:
|
||||||
|
if win():
|
||||||
|
user = get_env_var('USERNAME')
|
||||||
|
host = get_env_var('USERDOMAIN')
|
||||||
|
if host is None:
|
||||||
|
host = ""
|
||||||
|
else:
|
||||||
|
host = os.uname()[1]
|
||||||
|
# An ugly workaround for os.getlogin() issue with Konsole
|
||||||
|
try:
|
||||||
|
user = os.getlogin()
|
||||||
|
except:
|
||||||
|
# not win, so don't need get_env_var.
|
||||||
|
# under cron getlogin() throws and there is no USER.
|
||||||
|
user = os.environ.get('USER', 'noUSER')
|
||||||
|
if host:
|
||||||
|
text = "%s@%s" % (user, host)
|
||||||
|
else:
|
||||||
|
text = user
|
||||||
|
# Save only the username and host, so the massage can be
|
||||||
|
# printed with correct locale in DbManager.py when a lock is found
|
||||||
|
f.write(text)
|
||||||
|
@ -72,11 +72,11 @@ from . import (DbBsddbRead, DbWriteBase, BSDDBTxn,
|
|||||||
|
|
||||||
from gramps.gen.db import exceptions
|
from gramps.gen.db import exceptions
|
||||||
from gramps.gen.db.dbconst import *
|
from gramps.gen.db.dbconst import *
|
||||||
|
from gramps.gen.db.utils import write_lock_file, clear_lock_file
|
||||||
from gramps.gen.utils.callback import Callback
|
from gramps.gen.utils.callback import Callback
|
||||||
from gramps.gen.utils.id import create_id
|
from gramps.gen.utils.id import create_id
|
||||||
from gramps.gen.updatecallback import UpdateCallback
|
from gramps.gen.updatecallback import UpdateCallback
|
||||||
from gramps.gen.errors import DbError, HandleError
|
from gramps.gen.errors import DbError, HandleError
|
||||||
from gramps.gen.constfunc import win, get_env_var
|
|
||||||
from gramps.gen.const import HOME_DIR, GRAMPS_LOCALE as glocale
|
from gramps.gen.const import HOME_DIR, GRAMPS_LOCALE as glocale
|
||||||
_ = glocale.translation.gettext
|
_ = glocale.translation.gettext
|
||||||
|
|
||||||
@ -2308,38 +2308,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
|||||||
def _mkname(path, name):
|
def _mkname(path, name):
|
||||||
return os.path.join(path, name + DBEXT)
|
return os.path.join(path, name + DBEXT)
|
||||||
|
|
||||||
def clear_lock_file(name):
|
|
||||||
try:
|
|
||||||
os.unlink(os.path.join(name, DBLOCKFN))
|
|
||||||
except OSError:
|
|
||||||
return
|
|
||||||
|
|
||||||
def write_lock_file(name):
|
|
||||||
if not os.path.isdir(name):
|
|
||||||
os.mkdir(name)
|
|
||||||
with open(os.path.join(name, DBLOCKFN), "w", encoding='utf8') as f:
|
|
||||||
if win():
|
|
||||||
user = get_env_var('USERNAME')
|
|
||||||
host = get_env_var('USERDOMAIN')
|
|
||||||
if host is None:
|
|
||||||
host = ""
|
|
||||||
else:
|
|
||||||
host = os.uname()[1]
|
|
||||||
# An ugly workaround for os.getlogin() issue with Konsole
|
|
||||||
try:
|
|
||||||
user = os.getlogin()
|
|
||||||
except:
|
|
||||||
# not win, so don't need get_env_var.
|
|
||||||
# under cron getlogin() throws and there is no USER.
|
|
||||||
user = os.environ.get('USER', 'noUSER')
|
|
||||||
if host:
|
|
||||||
text = "%s@%s" % (user, host)
|
|
||||||
else:
|
|
||||||
text = user
|
|
||||||
# Save only the username and host, so the massage can be
|
|
||||||
# printed with correct locale in DbManager.py when a lock is found
|
|
||||||
f.write(text)
|
|
||||||
|
|
||||||
def upgrade_researcher(owner_data):
|
def upgrade_researcher(owner_data):
|
||||||
"""
|
"""
|
||||||
Upgrade researcher data to include a locality field in the address.
|
Upgrade researcher data to include a locality field in the address.
|
||||||
|
Loading…
Reference in New Issue
Block a user