Author: aconway
Date: Fri Oct 24 15:08:10 2014
New Revision: 1634072
URL: http://svn.apache.org/r1634072
Log:
DISPATCH-72: Fix c_entity locking to prevent add/remove entities during update.
Modified:
qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
qpid/dispatch/trunk/router/src/main.c
qpid/dispatch/trunk/src/c_entity.c
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/dispatch_c.py Fri Oct 24
15:08:10 2014
@@ -20,7 +20,6 @@
"""Access to functions in libqpid-dispatch.so"""
import ctypes
-from contextlib import contextmanager
from ctypes import c_char_p, c_long, py_object
from qpid_dispatch.site import QPID_DISPATCH_LIB
@@ -71,15 +70,8 @@ class QdDll(ctypes.PyDLL):
self._prototype(self.qd_connection_manager_start, None,
[self.qd_dispatch_p])
self._prototype(self.qd_waypoint_activate_all, None,
[self.qd_dispatch_p])
- self._prototype(self.qd_c_entity_flush, c_long, [py_object])
-
- @contextmanager
- def scoped_dispatch_router_lock(self, dispatch):
- self.qd_dispatch_router_lock(dispatch)
- try:
- yield
- finally:
- self.qd_dispatch_router_unlock(dispatch)
+ self._prototype(self.qd_c_entity_update_begin, c_long, [py_object])
+ self._prototype(self.qd_c_entity_update_end, None, [])
def _errcheck(self, result, func, args):
if self.qd_error_code():
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py
(original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/agent.py Fri
Oct 24 15:08:10 2014
@@ -309,8 +309,10 @@ class EntityCache(object):
except KeyError: pass
- with self.qd.scoped_dispatch_router_lock(self.agent.dispatch):
- self.qd.qd_c_entity_flush(events)
+ # FIXME aconway 2014-10-23: locking is ugly, push it down into C code.
+ self.qd.qd_dispatch_router_lock(self.agent.dispatch)
+ try:
+ self.qd.qd_c_entity_update_begin(events)
# Collapse sequences of add/remove into a single
remove/add/remove_add per pointer.
actions = {}
for action, type, pointer in events:
@@ -326,7 +328,9 @@ class EntityCache(object):
self.add(entity, pointer)
for e in self.entities: e._update()
-
+ finally:
+ self.qd.qd_c_entity_update_end()
+ self.qd.qd_dispatch_router_unlock(self.agent.dispatch)
class Agent(object):
"""AMQP managment agent"""
Modified: qpid/dispatch/trunk/router/src/main.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/main.c?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/main.c (original)
+++ qpid/dispatch/trunk/router/src/main.c Fri Oct 24 15:08:10 2014
@@ -113,7 +113,10 @@ static void main_process(const char *con
}
qd_server_run(dispatch);
- qd_dispatch_free(dispatch);
+
+ qd_dispatch_t *d = dispatch;
+ dispatch = NULL;
+ qd_dispatch_free(d);
if (exit_with_sigint) {
signal(SIGINT, SIG_DFL);
Modified: qpid/dispatch/trunk/src/c_entity.c
URL:
http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/c_entity.c?rev=1634072&r1=1634071&r2=1634072&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/c_entity.c (original)
+++ qpid/dispatch/trunk/src/c_entity.c Fri Oct 24 15:08:10 2014
@@ -70,8 +70,11 @@ void qd_c_entity_add(const char *type, v
void qd_c_entity_remove(const char *type, void *object) { push_event(REMOVE,
type, object); }
-// Flush events in the add/remove cache into a python list of (action, type,
pointer)
-qd_error_t qd_c_entity_flush(PyObject *list) {
+// Get events in the add/remove cache into a python list of (action, type,
pointer)
+// Locks the entity cache so entities can be updated safely (prevent entities
from being deleted.)
+// Do not processs any entities if return error code != 0
+// Must call qd_c_entity_update_end when done, regardless of error code.
+qd_error_t qd_c_entity_update_begin(PyObject *list) {
if (!event_lock) return QD_ERROR_NONE; /* Unit tests don't call
qd_c_entity_initialize */
qd_error_clear();
sys_mutex_lock(event_lock);
@@ -86,10 +89,13 @@ qd_error_t qd_c_entity_flush(PyObject *l
free(event);
event = DEQ_HEAD(event_list);
}
- sys_mutex_unlock(event_lock);
return qd_error_code();
}
+void qd_c_entity_update_end() {
+ sys_mutex_unlock(event_lock);
+}
+
const char *QD_ALLOCATOR_TYPE = "allocator";
const char *QD_CONNECTION_TYPE = "connection";
const char *QD_ROUTER_TYPE = "router";
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]