Do not query database for every metadata_get

This change stores the rsrc_metadata locally when the Resource object
is created so that the database is not queried every time
metadata_get is called. There are some instances where the metadata
must come from the database (eg, polling for waitcondition signal) so
an optional refresh arg is added to metadata_get to force a database
refresh of the stored rsrc_metadata.

This results in one less sql query for every time metadata_get is called,
which will help the optimising effort for
Related-Bug: #1306743

Change-Id: Iad2d810c299347ae3b6a4a8329bbd314ee4b5c16
This commit is contained in:
Steve Baker 2014-04-23 14:49:25 +12:00
parent 96791aaa10
commit 65c6c3bac8
4 changed files with 20 additions and 9 deletions

View File

@ -141,6 +141,7 @@ class Resource(object):
self._data = db_api.resource_data_get_all(self, resource.data)
except exception.NotFound:
self._data = {}
self._rsrc_metadata = resource.rsrc_metadata
self.created_time = resource.created_at
self.updated_time = resource.updated_at
else:
@ -154,6 +155,7 @@ class Resource(object):
self.status_reason = ''
self.id = None
self._data = {}
self._rsrc_metadata = None
self.created_time = None
self.updated_time = None
@ -181,11 +183,16 @@ class Resource(object):
return result
return not result
def metadata_get(self):
def metadata_get(self, refresh=False):
if refresh:
self._rsrc_metadata = None
if self.id is None:
return self.parsed_template('Metadata')
if self._rsrc_metadata is not None:
return self._rsrc_metadata
rs = db_api.resource_get(self.stack.context, self.id)
rs.refresh(attrs=['rsrc_metadata'])
self._rsrc_metadata = rs.rsrc_metadata
return rs.rsrc_metadata
def metadata_set(self, metadata):
@ -193,6 +200,7 @@ class Resource(object):
raise exception.ResourceNotAvailable(resource_name=self.name)
rs = db_api.resource_get(self.stack.context, self.id)
rs.update_and_save({'rsrc_metadata': metadata})
self._rsrc_metadata = metadata
def type(self):
return self.t['Type']
@ -444,7 +452,7 @@ class Resource(object):
'type': self.type(),
'action': self.action,
'status': self.status,
'metadata': self.metadata_get(),
'metadata': self.metadata_get(refresh=True),
'resource_data': self.data()
}
@ -736,6 +744,7 @@ class Resource(object):
new_rs = db_api.resource_create(self.context, rs)
self.id = new_rs.id
self.created_time = new_rs.created_at
self._rsrc_metadata = metadata
except Exception as ex:
logger.error(_('DB error %s') % ex)

View File

@ -427,11 +427,11 @@ class Server(stack_user.StackUser):
else:
self.data_set('password', password, True)
def metadata_get(self):
def metadata_get(self, refresh=False):
if self.user_data_software_config():
return self._build_deployments_metadata()
else:
return super(Server, self).metadata_get()
return super(Server, self).metadata_get(refresh)
def metadata_set(self, metadata):
if not self.user_data_software_config():

View File

@ -72,7 +72,7 @@ class WaitConditionHandle(signal_responder.SignalResponder):
return
if self._metadata_format_ok(new_metadata):
rsrc_metadata = self.metadata_get()
rsrc_metadata = self.metadata_get(refresh=True)
if new_metadata['UniqueId'] in rsrc_metadata:
logger.warning(_("Overwriting Metadata item for UniqueId %s!")
% new_metadata['UniqueId'])
@ -89,14 +89,14 @@ class WaitConditionHandle(signal_responder.SignalResponder):
'''
Return a list of the Status values for the handle signals
'''
return [v['Status'] for v in self.metadata_get().values()]
return [v['Status'] for v in self.metadata_get(refresh=True).values()]
def get_status_reason(self, status):
'''
Return a list of reasons associated with a particular status
'''
return [v['Reason']
for v in self.metadata_get().values()
for v in self.metadata_get(refresh=True).values()
if v['Status'] == status]
@ -274,7 +274,7 @@ class WaitCondition(resource.Resource):
handle_res_name = self._get_handle_resource_name()
handle = self.stack[handle_res_name]
if key == 'Data':
meta = handle.metadata_get()
meta = handle.metadata_get(refresh=True)
# Note, can't use a dict generator on python 2.6, hence:
res = dict([(k, meta[k]['Data']) for k in meta])
logger.debug(_('%(name)s.GetAtt(%(key)s) == %(res)s') %

View File

@ -290,7 +290,9 @@ class WaitCondMetadataUpdateTest(HeatTestCase):
update_metadata('456', 'blarg', 'wibble')
self.assertEqual('{"123": "foo", "456": "blarg"}',
watch.FnGetAtt('Data'))
self.assertEqual('{"123": "foo", "456": "blarg"}',
self.assertEqual('{"123": "foo"}',
inst.metadata_get()['test'])
self.assertEqual('{"123": "foo", "456": "blarg"}',
inst.metadata_get(refresh=True)['test'])
self.m.VerifyAll()