Commit 797a8c29 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Support grouping active objects.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3790 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent d72a36fb
This diff is collapsed.
...@@ -42,6 +42,7 @@ from AccessControl.SecurityManagement import newSecurityManager ...@@ -42,6 +42,7 @@ from AccessControl.SecurityManagement import newSecurityManager
import threading import threading
import sys import sys
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
from OFS.Traversable import NotFound
from zLOG import LOG from zLOG import LOG
...@@ -86,34 +87,57 @@ class Message: ...@@ -86,34 +87,57 @@ class Message:
self.user_name = str(_getAuthenticatedUser(self)) self.user_name = str(_getAuthenticatedUser(self))
# Store REQUEST Info ? # Store REQUEST Info ?
def __call__(self, activity_tool): def getObject(self, activity_tool):
return activity_tool.unrestrictedTraverse(self.object_path)
def getObjectList(self, activity_tool):
try: try:
# LOG('WARNING ActivityTool', 0, expand_method_id = self.activity_kw['expand_method_id']
# 'Trying to call method %s on object %s' % (self.method_id, self.object_path)) except KeyError:
object = activity_tool.unrestrictedTraverse(self.object_path) return [self.getObject()]
# Change user if required (TO BE DONE)
activity_tool._v_active_process = self.active_process # Store the active_process as volatile thread variable obj = self.getObject(activity_tool)
# We will change the user only in order to execute this method # FIXME: how to pass parameters?
current_user = str(_getAuthenticatedUser(self)) return getattr(obj, expand_method_id)()
uf = object.getPortalObject().acl_users
user = uf.getUserById(self.user_name) def hasExpandMethod(self):
return self.activity_kw.has_key('expand_method_id')
def changeUser(self, user_name, activity_tool):
uf = activity_tool.getPortalObject().acl_users
user = uf.getUserById(user_name)
if user is not None: if user is not None:
user = user.__of__(uf) user = user.__of__(uf)
newSecurityManager(None, user) newSecurityManager(None, user)
result = getattr(object, self.method_id)(*self.args, **self.kw) return user
# Use again the previous user
if user is not None: def activateResult(self, activity_tool, result, object):
user = uf.getUserById(current_user).__of__(uf) if self.active_process is not None:
newSecurityManager(None, user) active_process = activity_tool.unrestrictedTraverse(self.active_process)
if activity_tool._v_active_process is not None:
active_process = activity_tool.getActiveProcess()
if isinstance(result,Error): if isinstance(result,Error):
result.edit(object_path=object) result.edit(object_path=object)
result.edit(method_id=self.method_id) result.edit(method_id=self.method_id)
active_process.activateResult(result) # XXX Allow other method_id in future active_process.activateResult(result) # XXX Allow other method_id in future
else: else:
active_process.activateResult(Error(object_path=object,method_id=self.method_id,result=result)) # XXX Allow other method_id in future active_process.activateResult(Error(object_path=object,method_id=self.method_id,result=result)) # XXX Allow other method_id in future
def __call__(self, activity_tool):
try:
# LOG('WARNING ActivityTool', 0,
# 'Trying to call method %s on object %s' % (self.method_id, self.object_path))
object = self.getObject(activity_tool)
# Change user if required (TO BE DONE)
# We will change the user only in order to execute this method
current_user = str(_getAuthenticatedUser(self))
user = self.changeUser(self.user_name, activity_tool)
result = getattr(object, self.method_id)(*self.args, **self.kw)
# Use again the previous user
if user is not None:
self.changeUser(current_user, activity_tool)
self.activateResult(activity_tool, result, object)
self.is_executed = 1 self.is_executed = 1
except ConflictError:
raise
except: except:
self.is_executed = 0 self.is_executed = 0
LOG('WARNING ActivityTool', 0, LOG('WARNING ActivityTool', 0,
...@@ -236,6 +260,8 @@ class ActivityTool (Folder, UniqueObject): ...@@ -236,6 +260,8 @@ class ActivityTool (Folder, UniqueObject):
for activity in activity_list: for activity in activity_list:
try: try:
activity.distribute(self, node_count) activity.distribute(self, node_count)
except ConflictError:
raise
except: except:
LOG('CMFActivity:', 100, 'Core call to distribute failed for activity %s' % activity, error=sys.exc_info()) LOG('CMFActivity:', 100, 'Core call to distribute failed for activity %s' % activity, error=sys.exc_info())
...@@ -280,6 +306,7 @@ class ActivityTool (Folder, UniqueObject): ...@@ -280,6 +306,7 @@ class ActivityTool (Folder, UniqueObject):
try: try:
activity.tic(self, processing_node) # Transaction processing is the responsability of the activity activity.tic(self, processing_node) # Transaction processing is the responsability of the activity
has_awake_activity = has_awake_activity or activity.isAwake(self, processing_node) has_awake_activity = has_awake_activity or activity.isAwake(self, processing_node)
#LOG('ActivityTool tic', 0, 'has_awake_activity = %r, activity = %r, activity.isAwake(self, processing_node) = %r' % (has_awake_activity, activity, activity.isAwake(self, processing_node)))
except ConflictError: except ConflictError:
raise raise
except: except:
...@@ -357,6 +384,64 @@ class ActivityTool (Folder, UniqueObject): ...@@ -357,6 +384,64 @@ class ActivityTool (Folder, UniqueObject):
def invoke(self, message): def invoke(self, message):
message(self) message(self)
def invokeGroup(self, method_id, message_list):
# Invoke a group method.
object_list = []
expanded_object_list = []
new_message_list = []
path_dict = {}
# Filter the list of messages. If an object is not available, ignore such a message.
# In addition, expand an object if necessary, and make sure that no duplication happens.
for m in message_list:
try:
obj = m.getObject(self)
object_list.append(obj)
if m.hasExpandMethod():
for obj in m.getObjectList(self):
path = obj.getPath()
if path not in path_dict:
path_dict[path] = None
expanded_object_list.append(obj)
else:
path = obj.getPath()
if path not in path_dict:
path_dict[path] = None
expanded_object_list.append(obj)
new_message_list.append(m)
except ConflictError:
raise
except:
m.is_executed = 0
LOG('WARNING ActivityTool', 0,
'Could not call method %s on object %s' % (m.method_id, m.object_path), error=sys.exc_info())
if len(expanded_object_list) > 0:
try:
method = self.unrestrictedTraverse(method_id)
# FIXME: how to pass parameters?
# FIXME: how to apply security here?
result = method(expanded_object_list)
except ConflictError:
raise
except:
for m in new_message_list:
m.is_executed = 0
LOG('WARNING ActivityTool', 0,
'Could not call method %s on objects %s' % (method_id, expanded_object_list), error=sys.exc_info())
else:
for i in xrange(len(object_list)):
object = object_list[i]
m = new_message_list[i]
try:
m.activateResult(self, result, object)
m.is_executed = 1
except ConflictError:
raise
except:
m.is_executed = 0
LOG('WARNING ActivityTool', 0,
'Could not call method %s on object %s' % (m.method_id, m.object_path), error=sys.exc_info())
def newMessage(self, activity, path, active_process, activity_kw, method_id, *args, **kw): def newMessage(self, activity, path, active_process, activity_kw, method_id, *args, **kw):
# Some Security Cheking should be made here XXX # Some Security Cheking should be made here XXX
global is_initialized global is_initialized
...@@ -412,12 +497,6 @@ class ActivityTool (Folder, UniqueObject): ...@@ -412,12 +497,6 @@ class ActivityTool (Folder, UniqueObject):
def reindexObject(self): def reindexObject(self):
self.immediateReindexObject() self.immediateReindexObject()
def getActiveProcess(self):
active_process = getattr(self, '_v_active_process')
if active_process:
return self.unrestrictedTraverse(active_process)
return None
# Active synchronisation methods # Active synchronisation methods
def validateOrder(self, message, validator_id, validation_value): def validateOrder(self, message, validator_id, validation_value):
global is_initialized global is_initialized
......
...@@ -9,15 +9,16 @@ class_file: ...@@ -9,15 +9,16 @@ class_file:
</dtml-comment> </dtml-comment>
<params></params> <params></params>
CREATE TABLE `message` ( CREATE TABLE `message` (
`uid` int(11) NOT NULL auto_increment, `uid` INT UNSIGNED NOT NULL auto_increment,
`date` datetime, `date` datetime,
`path` VARCHAR(255), `path` VARCHAR(255),
`method_id` VARCHAR(40), `method_id` VARCHAR(255),
`processing_node` INT DEFAULT -1, `processing_node` INT DEFAULT -1,
`processing` INT DEFAULT 0, `processing` TINYINT DEFAULT 0,
`processing_date` datetime, `processing_date` datetime,
`priority` INT DEFAULT 0, `priority` TINYINT DEFAULT 0,
`broadcast` INT DEFAULT 0, `broadcast` TINYINT DEFAULT 0,
`group_method_id` VARCHAR(255) DEFAULT '',
`message` BLOB, `message` BLOB,
PRIMARY KEY (`uid`), PRIMARY KEY (`uid`),
KEY `date` (`date`), KEY `date` (`date`),
......
<dtml-comment> <dtml-comment>
title: title:
connection_id:cmf_activity_sql_connection connection_id:cmf_activity_sql_connection
max_rows:1 max_rows:0
max_cache:0 max_cache:0
cache_time:0 cache_time:0
class_name: class_name:
...@@ -10,14 +10,23 @@ class_file: ...@@ -10,14 +10,23 @@ class_file:
<params>processing_node <params>processing_node
priority priority
to_date to_date
to_processing_date</params> to_processing_date
SELECT * FROM group_method_id</params>
SELECT DISTINCT * FROM
message message
WHERE WHERE
processing <> 1 processing <> 1
<dtml-if processing_node> AND processing_node = <dtml-sqlvar processing_node type="int"> </dtml-if> <dtml-if processing_node> AND processing_node = <dtml-sqlvar processing_node type="int"> </dtml-if>
<dtml-if priority> AND priority = <dtml-sqlvar priority type="int"> </dtml-if> <dtml-if priority> AND priority = <dtml-sqlvar priority type="int"> </dtml-if>
<dtml-if to_date>AND date <= <dtml-sqlvar to_date type="datetime"> </dtml-if> <dtml-if to_date>AND date <= <dtml-sqlvar to_date type="datetime"> </dtml-if>
<dtml-if group_method_id>AND group_method_id = <dtml-sqlvar group_method_id type="string"> </dtml-if>
GROUP BY
path, method_id
ORDER BY ORDER BY
priority, date priority, date
<dtml-if group_method_id>
LIMIT 100
<dtml-else>
LIMIT 1
</dtml-if>
...@@ -13,7 +13,8 @@ message ...@@ -13,7 +13,8 @@ message
priority priority
broadcast broadcast
date date
processing_node=-1</params> processing_node=-1
group_method_id</params>
INSERT INTO message INSERT INTO message
SET SET
path = <dtml-sqlvar path type="string">, path = <dtml-sqlvar path type="string">,
...@@ -23,4 +24,5 @@ SET ...@@ -23,4 +24,5 @@ SET
processing = -1, processing = -1,
priority = <dtml-sqlvar priority type="int">, priority = <dtml-sqlvar priority type="int">,
broadcast = <dtml-sqlvar broadcast type="int">, broadcast = <dtml-sqlvar broadcast type="int">,
group_method_id = <dtml-sqlvar group_method_id type="string">,
message = <dtml-sqlvar message type="string"> message = <dtml-sqlvar message type="string">
...@@ -13,20 +13,22 @@ message_list ...@@ -13,20 +13,22 @@ message_list
priority_list priority_list
broadcast_list broadcast_list
date_list date_list
processing_node_list</params> processing_node_list
group_method_id_list</params>
INSERT INTO message INSERT INTO message
(path, date, method_id, processing_node, processing, priority, broadcast, message) (path, date, method_id, processing_node, processing, priority, broadcast, group_method_id, message)
VALUES VALUES
<dtml-in prefix="loop" expr="_.range(_.len(path_list))"> <dtml-in prefix="loop" expr="_.range(_.len(path_list))">
<dtml-if sequence-start><dtml-else>,</dtml-if> <dtml-if sequence-start><dtml-else>,</dtml-if>
( (
<dtml-sqlvar expr="path_list[loop_item]" type="string">, <dtml-sqlvar expr="path_list[loop_item]" type="string">,
<dtml-if date_list><dtml-sqlvar expr="date_list[loop_item]" type="string"><dtml-else><dtml-sqlvar "_.DateTime()" type="datetime"></dtml-if>, <dtml-if date_list><dtml-sqlvar expr="date_list[loop_item]" type="datetime"><dtml-else><dtml-sqlvar "_.DateTime()" type="datetime"></dtml-if>,
<dtml-sqlvar expr="method_id_list[loop_item]" type="string">, <dtml-sqlvar expr="method_id_list[loop_item]" type="string">,
<dtml-if processing_node_list><dtml-sqlvar expr="processing_node_list[loop_item]" type="int"><dtml-else>-1</dtml-if>, <dtml-if processing_node_list><dtml-sqlvar expr="processing_node_list[loop_item]" type="int"><dtml-else>-1</dtml-if>,
-1, -1,
<dtml-sqlvar expr="priority_list[loop_item]" type="int">, <dtml-sqlvar expr="priority_list[loop_item]" type="int">,
<dtml-sqlvar expr="broadcast_list[loop_item]" type="int">, <dtml-sqlvar expr="broadcast_list[loop_item]" type="int">,
<dtml-sqlvar expr="group_method_id_list[loop_item]" type="string">,
<dtml-sqlvar expr="message_list[loop_item]" type="string"> <dtml-sqlvar expr="message_list[loop_item]" type="string">
) )
</dtml-in> </dtml-in>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment