diff options
author | Tim Laszlo <tim.laszlo@gmail.com> | 2012-10-26 15:23:48 -0500 |
---|---|---|
committer | Tim Laszlo <tim.laszlo@gmail.com> | 2012-10-26 15:36:22 -0500 |
commit | c722716736c94261de77b337f1bffe924b8724e3 (patch) | |
tree | 4b2ae82c55502292e0b243f0e36caf4753b425a7 | |
parent | c2e16384931a6789cb6ce49acb11ab47e34d5fa9 (diff) | |
download | bcfg2-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.py | 3 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugin/helpers.py | 29 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Probes.py | 1 |
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(): |