summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Laszlo <tim.laszlo@gmail.com>2012-10-26 15:23:48 -0500
committerTim Laszlo <tim.laszlo@gmail.com>2012-10-26 15:36:22 -0500
commitc722716736c94261de77b337f1bffe924b8724e3 (patch)
tree4b2ae82c55502292e0b243f0e36caf4753b425a7
parentc2e16384931a6789cb6ce49acb11ab47e34d5fa9 (diff)
downloadbcfg2-c722716736c94261de77b337f1bffe924b8724e3.tar.gz
bcfg2-c722716736c94261de77b337f1bffe924b8724e3.tar.bz2
bcfg2-c722716736c94261de77b337f1bffe924b8724e3.zip
Probes/DatabaseBackend: add a thread lock for databases that cannot handle multiple writes
-rw-r--r--src/lib/Bcfg2/Server/Core.py3
-rw-r--r--src/lib/Bcfg2/Server/Plugin/helpers.py29
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Probes.py1
3 files changed, 33 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index 66a1a23a7..dca169b54 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -170,6 +170,9 @@ class BaseCore(object):
#: :attr:`fam_thread`) to shutdown
self.terminate = threading.Event()
+ #: RLock to be held on writes to the backend db
+ self.db_write_lock = threading.RLock()
+
# generate Django ORM settings. this must be done _before_ we
# load plugins
Bcfg2.settings.read_config(repo=self.datastore)
diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py
index bbceb1989..c7798b705 100644
--- a/src/lib/Bcfg2/Server/Plugin/helpers.py
+++ b/src/lib/Bcfg2/Server/Plugin/helpers.py
@@ -118,6 +118,7 @@ class DatabaseBacked(Plugin):
database.
.. private-include: _use_db
+ .. private-include: _must_lock
"""
#: The option to look up in :attr:`section` to determine whether or
@@ -148,6 +149,34 @@ class DatabaseBacked(Plugin):
self.logger.error("%s is true but django not found" % self.option)
return False
+ @property
+ def _must_lock(self):
+ """ Whether or not the backend database allows multiple
+ threads to write. """
+ engine = self.core.setup.cfp.get(Bcfg2.Options.DB_ENGINE.cf[0],
+ Bcfg2.Options.DB_ENGINE.cf[1],
+ default=Bcfg2.Options.DB_ENGINE.default)
+ if engine == 'sqlite3':
+ return True
+ else:
+ return False
+
+ @staticmethod
+ def _db_writer(fn):
+ """ Decorator to be used when a call will update the data
+ threads to write. """
+ def _acquire_and_run(self, *args, **kwargs):
+ if self._must_lock:
+ try:
+ self.core.db_write_lock.acquire()
+ rv = fn(self, *args, **kwargs)
+ finally:
+ self.core.db_write_lock.release()
+ else:
+ rv = fn(self, *args, **kwargs)
+ return rv
+ return _acquire_and_run
+
class PluginDatabaseModel(object):
""" A database model mixin that all database models used by
diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py
index bb1cbf81c..78dd2af85 100644
--- a/src/lib/Bcfg2/Server/Plugins/Probes.py
+++ b/src/lib/Bcfg2/Server/Plugins/Probes.py
@@ -218,6 +218,7 @@ class Probes(Bcfg2.Server.Plugin.Probing,
err = sys.exc_info()[1]
self.logger.error("Failed to write probed.xml: %s" % err)
+ @Bcfg2.Server.Plugin.DatabaseBacked._db_writer
def _write_data_db(self, client):
""" Write received probe data to the database """
for probe, data in self.probedata[client.hostname].items():