From 0d7e708d7a75d0aaa9e2ff56ee6445a07998f6fe Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 29 Oct 2012 08:50:50 -0400 Subject: added database locking to Metadata --- src/lib/Bcfg2/Server/Plugin/helpers.py | 20 +++++++++++--------- src/lib/Bcfg2/Server/Plugins/Metadata.py | 16 +++++++++++----- src/lib/Bcfg2/Server/Plugins/Probes.py | 4 ++-- 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/lib/Bcfg2') diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py index c7798b705..a9e7b6067 100644 --- a/src/lib/Bcfg2/Server/Plugin/helpers.py +++ b/src/lib/Bcfg2/Server/Plugin/helpers.py @@ -151,22 +151,24 @@ class DatabaseBacked(Plugin): @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) + """ Whether or not the backend database must acquire a thread + lock before writing, because it does not allow 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 get_db_lock(fn): + """ Decorator to be used by a method of a + :class:`DatabaseBacked` plugin that will update database data. """ def _acquire_and_run(self, *args, **kwargs): - if self._must_lock: + if self._must_lock: # pylint: disable=W0212 try: self.core.db_write_lock.acquire() rv = fn(self, *args, **kwargs) diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index 6daf23476..4929cb52d 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -43,7 +43,8 @@ if HAS_DJANGO: hostname = models.CharField(max_length=255, primary_key=True) version = models.CharField(max_length=31, null=True) - class ClientVersions(MutableMapping, object): + class ClientVersions(MutableMapping, + Bcfg2.Server.Plugin.DatabaseBacked): """ dict-like object to make it easier to access client bcfg2 versions from the database """ @@ -53,12 +54,15 @@ if HAS_DJANGO: except MetadataClientModel.DoesNotExist: raise KeyError(key) + @Bcfg2.Server.Plugin.DatabaseBacked.get_db_lock def __setitem__(self, key, value): - client, created = MetadataClientModel.objects.get_or_create(hostname=key) + client, created = \ + MetadataClientModel.objects.get_or_create(hostname=key) if created or client.version != value: client.version = value client.save() + @Bcfg2.Server.Plugin.DatabaseBacked.get_db_lock def __delitem__(self, key): # UserDict didn't require __delitem__, but MutableMapping # does. we don't want deleting a client version record to @@ -435,7 +439,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, self.negated_groups = dict() # mapping of hostname -> version string if self._use_db: - self.versions = ClientVersions() + self.versions = ClientVersions(core, datastore) else: self.versions = dict() self.uuid = {} @@ -540,6 +544,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, else: return self._add_xdata(self.groups_xml, "Bundle", bundle_name) + @Bcfg2.Server.Plugin.DatabaseBacked.get_db_lock def add_client(self, client_name, attribs=None): """Add client to clients.xml.""" if attribs is None: @@ -914,9 +919,10 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, if client not in self.versions or version != self.versions[client]: self.logger.info("Setting client %s version to %s" % (client, version)) - self.update_client(client, dict(version=version)) + if not self._use_db: + self.update_client(client, dict(version=version)) + self.clients_xml.write() self.versions[client] = version - self.clients_xml.write() else: msg = "Cannot set version on non-existent client %s" % client self.logger.error(msg) diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py index 78dd2af85..941bc4fd8 100644 --- a/src/lib/Bcfg2/Server/Plugins/Probes.py +++ b/src/lib/Bcfg2/Server/Plugins/Probes.py @@ -218,7 +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 + @Bcfg2.Server.Plugin.DatabaseBacked.get_db_lock def _write_data_db(self, client): """ Write received probe data to the database """ for probe, data in self.probedata[client.hostname].items(): @@ -320,7 +320,7 @@ class Probes(Bcfg2.Server.Plugin.Probing, cprobedata[data.get('name')] = ProbeData('') return dlines = data.text.split('\n') - self.logger.debug("%s:probe:%s:%s" % + self.logger.debug("Processing probe from %s: %s:%s" % (client.hostname, data.get('name'), [line.strip() for line in dlines])) for line in dlines[:]: -- cgit v1.2.3-1-g7c22