[REF] osv: moved (and adapted) vacuum code to osv_memory.

bzr revid: vmt@openerp.com-20110812113355-lylavdsc3mqjovrj
This commit is contained in:
Vo Minh Thu 2011-08-12 13:33:55 +02:00
parent 44d41334d7
commit 2f5e8d48b3
5 changed files with 71 additions and 41 deletions

View File

@ -42,5 +42,8 @@ import tools
import wizard
import workflow
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER = 1
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -19,18 +19,16 @@
#
##############################################################################
from osv import osv
from osv.orm import orm_memory
import openerp
class osv_memory_autovacuum(osv.osv_memory):
class osv_memory_autovacuum(openerp.osv.osv.osv_memory):
""" Expose the osv_memory.vacuum() method to the cron jobs mechanism. """
_name = 'osv_memory.autovacuum'
def power_on(self, cr, uid, context=None):
for model in self.pool.obj_list():
obj = self.pool.get(model)
if isinstance(obj, orm_memory):
obj.vaccum(cr, uid)
if obj._transient:
obj.vacuum(cr, uid)
return True
osv_memory_autovacuum()

View File

@ -284,6 +284,8 @@ def init_module_models(cr, module_name, obj_list):
cr.commit()
for obj in obj_list:
obj._auto_end(cr, {'module': module_name})
if obj._transient:
obj.vacuum(cr, openerp.SUPERUSER)
cr.commit()
todo.sort()
for t in todo:

View File

@ -2250,8 +2250,6 @@ class orm_memory(orm_template):
_protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count', 'exists']
_inherit_fields = {}
_max_count = None
_max_hours = None
_check_time = 20
@classmethod
@ -2262,43 +2260,12 @@ class orm_memory(orm_template):
super(orm_memory, self).__init__(pool, cr)
self.datas = {}
self.next_id = 0
self.check_id = 0
self._max_count = config.get('osv_memory_count_limit')
self._max_hours = config.get('osv_memory_age_limit')
cr.execute('delete from wkf_instance where res_type=%s', (self._name,))
def _check_access(self, uid, object_id, mode):
if uid != 1 and self.datas[object_id]['internal.create_uid'] != uid:
raise except_orm(_('AccessError'), '%s access is only allowed on your own records for osv_memory objects except for the super-user' % mode.capitalize())
def vaccum(self, cr, uid, force=False):
"""Run the vaccuum cleaning system, expiring and removing old records from the
virtual osv_memory tables if the "max count" or "max age" conditions are enabled
and have been reached. This method can be called very often (e.g. everytime a record
is created), but will only actually trigger the cleanup process once out of
"_check_time" times (by default once out of 20 calls)."""
self.check_id += 1
if (not force) and (self.check_id % self._check_time):
return True
tounlink = []
# Age-based expiration
if self._max_hours:
max = time.time() - self._max_hours * 60 * 60
for k,v in self.datas.iteritems():
if v['internal.date_access'] < max:
tounlink.append(k)
self.unlink(cr, ROOT_USER_ID, tounlink)
# Count-based expiration
if self._max_count and len(self.datas) > self._max_count:
# sort by access time to remove only the first/oldest ones in LRU fashion
records = self.datas.items()
records.sort(key=lambda x:x[1]['internal.date_access'])
self.unlink(cr, ROOT_USER_ID, [x[0] for x in records[:len(self.datas)-self._max_count]])
return True
def read(self, cr, user, ids, fields_to_read=None, context=None, load='_classic_read'):
if not context:
context = {}
@ -2352,7 +2319,7 @@ class orm_memory(orm_template):
return object_id
def create(self, cr, user, vals, context=None):
self.vaccum(cr, user)
self.vacuum(cr, user)
self.next_id += 1
id_new = self.next_id

View File

@ -22,11 +22,13 @@
#.apidoc title: Objects Services (OSV)
import orm
import openerp
import openerp.netsvc as netsvc
import openerp.pooler as pooler
import openerp.sql_db as sql_db
import logging
from psycopg2 import IntegrityError, errorcodes
from openerp.tools.config import config
from openerp.tools.func import wraps
from openerp.tools.translate import translate
from openerp.osv.orm import MetaModel
@ -203,12 +205,70 @@ class osv_memory(orm.orm):
""" Deprecated class. """
__metaclass__ = MetaModel
_register = False # Set to false if the model shouldn't be automatically discovered.
_transient = True
_max_count = None
_max_hours = None
_check_time = 20
def __init__(self, pool, cr):
super(osv_memory, self).__init__(pool, cr)
self.check_id = 0
self._max_count = config.get('osv_memory_count_limit')
self._max_hours = config.get('osv_memory_age_limit')
def _clean_transient_rows_older_than(self, cr, seconds):
if not self._log_access:
self.logger = logging.getLogger('orm').warning(
"Transient model without write_date: %s" % (self._name,))
return
cr.execute("SELECT id FROM " + self._table + " WHERE "
"COALESCE(write_date, create_date, now())::timestamp < "
"(now() - interval %s)", ("%s seconds" % seconds,))
ids = [x[0] for x in cr.fetchall()]
self.unlink(cr, openerp.SUPERUSER, ids)
def _clean_old_transient_rows(self, cr, count):
if not self._log_access:
self.logger = logging.getLogger('orm').warning(
"Transient model without write_date: %s" % (self._name,))
return
cr.execute(
"SELECT id, COALESCE(write_date, create_date, now())::timestamp"
" AS t FROM " + self._table +
" ORDER BY t LIMIT %s", (count,))
ids = [x[0] for x in cr.fetchall()]
self.unlink(cr, openerp.SUPERUSER, ids)
def vacuum(self, cr, uid, force=False):
""" Run the vacuum cleaner, i.e. unlink old records from the
virtual osv_memory tables if the "max count" or "max age" conditions are enabled
and have been reached. This method can be called very often (e.g. everytime a record
is created), but will only actually trigger the cleanup process once out of
"_check_time" times (by default once out of 20 calls)."""
self.check_id += 1
if (not force) and (self.check_id % self._check_time):
self.check_id = 0
return True
tounlink = []
# Age-based expiration
if self._max_hours:
self._clean_transient_rows_older_than(cr, self._max_hours * 60 * 60)
# Count-based expiration
if self._max_count:
self._clean_old_transient_rows(cr, self._max_count)
return True
class osv(orm.orm):
""" Deprecated class. """
__metaclass__ = MetaModel
_register = False # Set to false if the model shouldn't be automatically discovered.
_transient = False
def start_object_proxy():