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)
openSUSE Build Service is sponsored by