File 0002-Fix-clear-expirer-metering-data.patch of Package openstack-ceilometer
From 23684784d81165494c525f2f0403728af7dc5c93 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@gmail.com>
Date: Fri, 10 Apr 2015 09:51:11 +0200
Subject: [PATCH] Fix `clear_expirer_metering_data`
Backport and adapt `clear_expirer_metering_data` from Juno to
Icehouse to avoid memory problems when deleting metering data.
Fix bsc#926274
---
ceilometer/storage/impl_sqlalchemy.py | 38 ++++++++++++++++++++-------------
ceilometer/storage/sqlalchemy/models.py | 17 +++++++++++++++
2 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py
index 87d2a44..72bb5a5 100644
--- a/ceilometer/storage/impl_sqlalchemy.py
+++ b/ceilometer/storage/impl_sqlalchemy.py
@@ -372,10 +372,27 @@ def clear_expired_metering_data(self, ttl):
session = self._get_db_session()
with session.begin():
end = timeutils.utcnow() - datetime.timedelta(seconds=ttl)
- sample_query = session.query(models.Sample)\
- .filter(models.Sample.timestamp < end)
- for sample_obj in sample_query.all():
- session.delete(sample_obj)
+ sample_q = session.query(models.Sample)\
+ .filter(models.Sample.timestamp < end)
+
+ sample_subq = sample_q.subquery()
+ for table in [models.MetaText, models.MetaBigInt,
+ models.MetaFloat, models.MetaBool]:
+ session.query(table)\
+ .join(sample_subq, sample_subq.c.id == table.id)\
+ .delete()
+
+ session.query(models.Sourceassoc)\
+ .join(sample_subq, sample_subq.c.id == models.Sourceassoc.sample_id)\
+ .delete()
+
+ sample_q.delete()
+
+ query = session.query(models.Resource)\
+ .filter(~models.Resource.id.in_(
+ session.query(models.Sample.resource_id).group_by(
+ models.Sample.resource_id)))
+ query.delete(synchronize_session='fetch')
query = session.query(models.User).filter(
~models.User.id.in_(session.query(models.Sample.user_id)
@@ -383,8 +400,7 @@ def clear_expired_metering_data(self, ttl):
~models.User.id.in_(session.query(models.AlarmChange.user_id)
.group_by(models.AlarmChange.user_id))
)
- for user_obj in query.all():
- session.delete(user_obj)
+ query.delete(synchronize_session='fetch')
query = session.query(models.Project)\
.filter(~models.Project.id.in_(
@@ -397,15 +413,7 @@ def clear_expired_metering_data(self, ttl):
session.query(models.AlarmChange.on_behalf_of)
.group_by(models.AlarmChange.on_behalf_of))
)
- for project_obj in query.all():
- session.delete(project_obj)
-
- query = session.query(models.Resource)\
- .filter(~models.Resource.id.in_(
- session.query(models.Sample.resource_id).group_by(
- models.Sample.resource_id)))
- for res_obj in query.all():
- session.delete(res_obj)
+ query.delete(synchronize_session='fetch')
def get_users(self, source=None):
"""Return an iterable of user id strings.
diff --git a/ceilometer/storage/sqlalchemy/models.py b/ceilometer/storage/sqlalchemy/models.py
index b79507f..7e3a733 100644
--- a/ceilometer/storage/sqlalchemy/models.py
+++ b/ceilometer/storage/sqlalchemy/models.py
@@ -137,6 +137,23 @@ def update(self, values):
name='uniq_sourceassoc0sample_id0user_id')
+# Classic SQLAlchemy mapping
+from sqlalchemy.orm import mapper
+
+class Sourceassoc(object):
+ def __init__(self, sample_id, project_id, user_id, source_id):
+ self.sample_id = sample_id
+ self.project_id = project_id
+ self.user_id = user_id
+ self.source_id = source_id
+
+mapper(Sourceassoc, sourceassoc, primary_key=[sourceassoc.c.sample_id,
+ sourceassoc.c.project_id,
+ sourceassoc.c.resource_id,
+ sourceassoc.c.user_id,
+ sourceassoc.c.source_id])
+
+
class Source(Base):
__tablename__ = 'source'
id = Column(String(255), primary_key=True)