Revision: 6886
http://playerstage.svn.sourceforge.net/playerstage/?rev=6886&view=rev
Author: thjc
Date: 2008-07-18 03:15:24 +0000 (Fri, 18 Jul 2008)
Log Message:
-----------
fixes to the group subscription etc for blackboard proxies.
Modified Paths:
--------------
code/player/branches/release-2-1-patches/client_libs/libplayerc/bindings/python/playerc.i
code/player/branches/release-2-1-patches/client_libs/libplayerc/dev_blackboard.c
code/player/branches/release-2-1-patches/client_libs/libplayerc/playerc.h
code/player/branches/release-2-1-patches/libplayercore/interfaces/064_blackboard.def
code/player/branches/release-2-1-patches/server/drivers/blackboard/localbb/localbb.cpp
Modified:
code/player/branches/release-2-1-patches/client_libs/libplayerc/bindings/python/playerc.i
===================================================================
---
code/player/branches/release-2-1-patches/client_libs/libplayerc/bindings/python/playerc.i
2008-07-17 21:30:23 UTC (rev 6885)
+++
code/player/branches/release-2-1-patches/client_libs/libplayerc/bindings/python/playerc.i
2008-07-18 03:15:24 UTC (rev 6886)
@@ -416,83 +416,185 @@
%extend playerc_blackboard
{
-static void python_on_blackboard_event(playerc_blackboard_t *device,
player_blackboard_entry_t entry)
+
+#define DICT_GROUPS_INDEX 0
+#define DICT_SUBSCRIPTION_DATA_INDEX 1
+#define LIST_EVENTS_INDEX 2
+#define BOOL_QUEUE_EVENTS_INDEX 3
+
+// Helper function to convert a c blackboard_entry_t into a python dictionary
object
+PyObject *__convert_blackboard_entry__(player_blackboard_entry_t *entry)
{
- char * str;
- int i;
- double d;
- PyObject *data, *entry_dict, *group_dict, *groups, *list;
- groups = (PyObject *)PyTuple_GetItem(device->py_private,0);
- assert(groups);
+ PyObject *entry_dict, *data;
+ char* str;
+ int i;
+ double d;
- group_dict = (PyObject*) PyDict_GetItemString(groups, entry.group);
- if (!group_dict)
- {
- return;
- }
-
- // find our key in the group, if it exists
- entry_dict = (PyObject*) PyDict_GetItemString(group_dict, entry.key);
- if (!entry_dict)
- {
- return;
- }
+ entry_dict = PyDict_New();
+ assert (entry_dict);
- PyDict_SetItemString(entry_dict, "type", PyLong_FromLong(entry.type));
- PyDict_SetItemString(entry_dict, "subtype",
PyLong_FromLong(entry.subtype));
- PyDict_SetItemString(entry_dict, "timestamp_sec",
PyLong_FromLong(entry.timestamp_sec));
- PyDict_SetItemString(entry_dict, "timestamp_usec",
PyLong_FromLong(entry.timestamp_usec));
- list = (PyObject*)PyTuple_GetItem(device->py_private,1);
- assert(list);
- data = NULL;
- switch(entry.subtype)
- {
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
- data = Py_None;
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
- assert(entry.type == PLAYERC_BLACKBOARD_DATA_TYPE_COMPLEX);
- str = malloc(entry.data_count);
- assert(str);
- memcpy(str, entry.data, entry.data_count);
- data = PyString_FromString(str);
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_INT:
- assert(entry.type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
- i = 0;
- memcpy(&i, entry.data, entry.data_count);
- data = PyLong_FromLong(i);
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_DOUBLE:
- assert(entry.type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
- d = 0.0;
- memcpy(&d, entry.data, entry.data_count);
- data = PyFloat_FromDouble(d);
- break;
- default:
- data = Py_None;
- break;
- }
+ assert(entry);
+ assert(entry->key);
+ assert(entry->key_count > 0);
+ assert(entry->group);
+ assert(entry->group_count > 0);
- assert(data != NULL);
- PyDict_SetItemString(entry_dict, "data", data);
-
- if (PyLong_AsLong(PyTuple_GetItem(device->py_private,2)) > 0)
- {
- list = (PyObject*)PyTuple_GetItem(device->py_private,1);
- assert(list);
- PyList_Append(list, PyDict_Copy(entry_dict));
- }
+ PyDict_SetItemString(entry_dict, "key", PyString_FromString(entry->key));
+ PyDict_SetItemString(entry_dict, "group",
PyString_FromString(entry->group));
+ PyDict_SetItemString(entry_dict, "type", PyLong_FromLong(entry->type));
+ PyDict_SetItemString(entry_dict, "subtype", PyLong_FromLong(entry->subtype));
+ PyDict_SetItemString(entry_dict, "timestamp_sec",
PyLong_FromLong(entry->timestamp_sec));
+ PyDict_SetItemString(entry_dict, "timestamp_usec",
PyLong_FromLong(entry->timestamp_usec));
+
+ switch(entry->subtype)
+ {
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
+ data = Py_None;
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
+ assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_COMPLEX);
+ str = malloc(entry->data_count);
+ assert(str);
+ memcpy(str, entry->data, entry->data_count);
+ data = PyString_FromString(str);
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_INT:
+ assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
+ i = 0;
+ memcpy(&i, entry->data, entry->data_count);
+ data = PyLong_FromLong(i);
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_DOUBLE:
+ assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
+ d = 0.0;
+ memcpy(&d, entry->data, entry->data_count);
+ data = PyFloat_FromDouble(d);
+ break;
+ default:
+ data = Py_None;
+ break;
+ }
+
+ PyDict_SetItemString(entry_dict, "data", data);
+ return entry_dict;
}
-// Will always return a list object. Returns a list of dictionary objects
containing the event data.
-PyObject *get_events()
+// Helper function which sets a value in a nested dictionary. Equivalent of
dict['group']['key'] = value.
+PyObject *__set_nested_dictionary_entry__(PyObject *dict, const char* key,
const char* group, PyObject *entry)
{
+ PyObject *group_dict;
+ int create_dict = 0;
+
+ // Check we got valid arguments.
+ if (!PyDict_Check(dict))
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected type 'dict' for first argument
(dict)");
+ return NULL;
+ }
+
+ if (!entry)
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected type non NULL for fourth
argument (entry)");
+ return NULL;
+ }
+
+ if (key == NULL || strlen(key) == 0)
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected type 'string' for second
argument (key)");
+ return NULL;
+ }
+
+ if (group == NULL || strlen(group) == 0)
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected type 'string' for second
argument (group)");
+ return NULL;
+ }
+
+ // Get the dictionary for the entry's group. If it doesn't exist, create it.
+ group_dict = (PyObject*)PyDict_GetItemString(dict, group);
+ if (!group_dict)
+ {
+ create_dict = 1;
+ group_dict = PyDict_New();
+ }
+
+ PyDict_SetItemString(group_dict, key, entry);
+
+ // If we created the dictionary, we need to put it in the parent dictionary.
+ if (create_dict == 1)
+ {
+ PyDict_SetItemString(dict, group, group_dict);
+ }
+
+ Py_RETURN_NONE;
+}
+
+// Helper function used to keep track to the number of subscriptions a
group/key combination has
+int __increment_reference_count__(PyObject *dict, const char* key, const char*
group, int inc)
+{
+ PyObject *group_dict, *entry;
+ int old_value, new_value;
+
+ // Get the dictionary for the entry's group. If it doesn't exist, create it
and increment it.
+ group_dict = (PyObject*)PyDict_GetItemString(dict, group);
+ if (!group_dict)
+ {
+ playerc_blackboard___set_nested_dictionary_entry__(self, dict, key, group,
(PyObject*)PyInt_FromLong(inc));
+ return inc;
+ }
+
+ entry = PyDict_GetItemString(group_dict, key);
+ old_value = PyLong_AsLong(entry);
+ new_value = old_value + inc;
+ if (new_value < 0)
+ new_value = 0;
+
+ playerc_blackboard___set_nested_dictionary_entry__(self, dict, key, group,
PyInt_FromLong(new_value));
+
+ return new_value;
+}
+
+// Replacement for the existing on_blackboard_event method. The python
implementation uses this instead.
+static void __python_on_blackboard_event__(playerc_blackboard_t *device,
player_blackboard_entry_t entry)
+{
+ PyObject *entry_dict, *groups_dict, *list, *queue_events;
+
+ // Get the main groups dictionary
+ assert(device->py_private);
+ groups_dict = (PyObject*)PyTuple_GetItem(device->py_private,
DICT_GROUPS_INDEX);
+ assert(groups_dict);
+
+ // Get a dictionary of the entry
+ entry_dict = playerc_blackboard___convert_blackboard_entry__(device, &entry);
+ assert(entry_dict);
+ // Set the entry in the groups dictionary
+ playerc_blackboard___set_nested_dictionary_entry__(device, groups_dict,
entry.key, entry.group, entry_dict);
+
+ // If we are queueing events, add them to the list
+ queue_events = PyTuple_GetItem(device->py_private, BOOL_QUEUE_EVENTS_INDEX);
+ assert(queue_events);
+ if (PyLong_AsLong(queue_events) != 0)
+ {
+ list = (PyObject*)PyTuple_GetItem(device->py_private, LIST_EVENTS_INDEX);
+ assert(list);
+ PyList_Append(list, PyDict_Copy(entry_dict));
+ }
+}
+
+// Returns a list of dictionary objects containing the entries.
+// Requires that set_queue_events is set to True for any events to be queued.
+// All events will be retrieved.
+// Will always return a list object.
+%feature("autodoc", "1");
+PyObject *GetEvents()
+{
PyObject *list, *copy;
int i, j;
+
assert(self->py_private);
+ list = (PyObject*)PyTuple_GetItem(self->py_private, LIST_EVENTS_INDEX);
+ assert(list);
- list = (PyObject*)PyTuple_GetItem(self->py_private,1);
copy = PyList_New(0);
j = PyList_Size(list);
for (i = 0; i < j; i++)
@@ -503,342 +605,370 @@
return copy;
}
-void set_queue_events(PyObject *boolean)
+// Returns a dictionary of the entry dictionary objects indexed by group.
+// Will only contain the latest values.
+// Will always return a dictionary object.
+PyObject *GetDict()
{
+ PyObject *dict, *copy, *list, *pair;
+ int i, j;
+
+ assert(self->py_private);
+ dict = (PyObject*)PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(dict);
+
+ copy = PyDict_New();
+ list = PyDict_Items(dict);
+ j = PyList_Size(list);
+ for (i = 0; i < j; i++)
+ {
+ pair = PyList_GetItem(list, i);
+ PyDict_SetItem(copy, PyTuple_GetItem(pair, 0), PyTuple_GetItem(pair, 1));
+ }
+
+ return copy;
+}
+
+// Set whether events should be put into the list, to be retrieved by
get_events_list().
+PyObject *SetQueueEvents(PyObject *boolean)
+{
if(!PyBool_Check(boolean))
{
- PyErr_SetString(PyExc_RuntimeError, "Expected a bool object.");
- return;
+ PyErr_SetString(PyExc_TypeError, "Expected type 'bool'");
+ return NULL;
}
- if (boolean==Py_False)
+ if (boolean == Py_False)
{
- PyTuple_SetItem(self->py_private,2,PyLong_FromLong(0));
+ PyTuple_SetItem(self->py_private, BOOL_QUEUE_EVENTS_INDEX,
PyLong_FromLong(0));
}
else
{
- PyTuple_SetItem(self->py_private,2,PyLong_FromLong(1));
+ PyTuple_SetItem(self->py_private, BOOL_QUEUE_EVENTS_INDEX,
PyLong_FromLong(1));
}
+
+ Py_RETURN_NONE;
}
-void unsubscribe_from_key_py(const char *key, const char *group)
+PyObject *Subscribe(int access)
{
- long refcount;
- PyObject *group_dict, *entry_dict, *groups;
+ int result;
+ result = playerc_blackboard_subscribe(self, access);
+ return PyInt_FromLong(result);
+}
- groups = (PyObject *)PyTuple_GetItem(self->py_private,0);
- assert(groups);
+PyObject *Unsubscribe()
+{
+ int result;
+ result = playerc_blackboard_unsubscribe(self);
+ return PyInt_FromLong(result);
+}
- group_dict = (PyObject*) PyDict_GetItemString(groups, group);
- if (!group_dict)
- {
- PyErr_SetString(PyExc_RuntimeError, "Group does not exist");
- return;
- }
-
- // find our key in the group, if it exists
- entry_dict = (PyObject*) PyDict_GetItemString(group_dict, key);
- if (!entry_dict)
- {
- PyErr_SetString(PyExc_RuntimeError, "Key does not exist");
- return;
- }
- refcount = PyLong_AsLong(PyDict_GetItemString(entry_dict,
"___refcount"));
- if(refcount==0)
- {
- PyErr_SetString(PyExc_RuntimeError, "No subscription to key to
unsubscribe from.");
- return;
- }
- if(refcount==1)
- {
- playerc_blackboard_unsubscribe_from_key(self, key, group);
- }
- PyDict_SetItemString(entry_dict, "___refcount",
PyLong_FromLong(refcount-1));
+PyObject *SetString(const char* key, const char* group, const char* value)
+{
+ int result;
+ result = playerc_blackboard_set_string(self, key, group, value);
+ return PyInt_FromLong(result);
}
-PyObject * subscribe_to_key_py(const char *key, const char *group)
+PyObject *SetInt(const char* key, const char* group, const int value)
{
- char *str;
- int i, result, refcount;
- double d;
- PyObject *data, *entry_dict, *group_dict, *groups;
- player_blackboard_entry_t *entry;
+ int result;
+ result = playerc_blackboard_set_int(self, key, group, value);
+ return PyInt_FromLong(result);
+}
- groups = (PyObject *)PyTuple_GetItem(self->py_private,0);
- assert(groups);
- // grab our group dict, if it doesnt exist create a new one
- group_dict = (PyObject*) PyDict_GetItemString(groups, group);
- if (!group_dict)
- {
- group_dict = PyDict_New();
- assert (group_dict);
- result = PyDict_SetItemString(groups,group,group_dict);
- if (result != 0)
- {
- PyErr_SetString(PyExc_RuntimeError, "Failed to set
group key");
- return Py_None;
- }
- }
- // find our key in the group, if it exists, create it if not
- entry_dict = (PyObject*) PyDict_GetItemString(group_dict, key);
- if (!entry_dict)
- {
- entry_dict = PyDict_New();
- assert (entry_dict);
- PyDict_SetItemString(entry_dict, "key",
PyString_FromString(key));
- PyDict_SetItemString(entry_dict, "group",
PyString_FromString(group));
- PyDict_SetItemString(entry_dict, "___refcount",
PyLong_FromLong(1));
- }
- else
- {
- // key already exists, so increment our ref count and return
current value
- refcount = PyLong_AsLong(PyDict_GetItemString(entry_dict,
"___refcount"));
- if(refcount>=1000)
- {
- PyErr_SetString(PyExc_RuntimeError, "Reached over 1000
subscriptions");
- }
- if(refcount!=0)
- {
- PyDict_SetItemString(entry_dict, "___refcount",
PyLong_FromLong(refcount+1));
- Py_INCREF(entry_dict);
- return entry_dict;
- }
- }
- assert(self);
- result = playerc_blackboard_subscribe_to_key(self, key, group, &entry);
- if (result != 0)
- {
- PyErr_SetString(PyExc_RuntimeError, "Failed to subscribe to
key");
- return Py_None;
- }
- assert(entry);
- assert(entry->key);
- assert(entry->key_count > 0);
- PyDict_SetItemString(entry_dict, "type", PyLong_FromLong(entry->type));
- PyDict_SetItemString(entry_dict, "subtype",
PyLong_FromLong(entry->subtype));
- PyDict_SetItemString(entry_dict, "timestamp_sec",
PyLong_FromLong(entry->timestamp_sec));
- PyDict_SetItemString(entry_dict, "timestamp_usec",
PyLong_FromLong(entry->timestamp_usec));
- switch(entry->subtype)
+PyObject *SetDouble(const char* key, const char* group, const double value)
+{
+ int result;
+ result = playerc_blackboard_set_double(self, key, group, value);
+ return PyInt_FromLong(result);
+}
+
+int UnsubscribeFromKey(const char *key, const char *group)
+{
+ PyObject *groups_dict, *group_dict, *subscription_data;
+ int result, ref_count;
+ subscription_data = PyTuple_GetItem(self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX);
+ assert(subscription_data);
+ ref_count = playerc_blackboard___increment_reference_count__(self,
subscription_data, key, group, -1);
+ if (ref_count <= 0)
+ {
+ groups_dict = PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(groups_dict);
+ group_dict = PyDict_GetItemString(groups_dict, group);
+ assert(group_dict);
+ PyDict_DelItemString(group_dict, key);
+ }
+
+ result = playerc_blackboard_unsubscribe_from_key(self, key, group);
+ return result;
+}
+
+PyObject *SubscribeToKey(const char *key, const char *group)
+{
+ int result;
+ PyObject *subscription_data, *groups_dict, *entry_dict;
+ player_blackboard_entry_t *entry;
+
+ result = playerc_blackboard_subscribe_to_key(self, key, group, &entry);
+ if (result != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to subscribe to key");
+ return NULL;
+ }
+
+ entry_dict = playerc_blackboard___convert_blackboard_entry__(self, entry);
+ groups_dict = (PyObject*)PyTuple_GetItem(self->py_private,
DICT_GROUPS_INDEX);
+ assert(groups_dict);
+
+ assert(entry_dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict, key,
group, entry_dict);
+
+ subscription_data = PyTuple_GetItem(self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX);
+ assert(subscription_data);
+
+ playerc_blackboard___increment_reference_count__(self, subscription_data,
key, group, 1);
+
+ free(entry->key);
+ free(entry->group);
+ free(entry->data);
+ free(entry);
+
+ return entry_dict;
+}
+
+int UnsubscribeFromGroup(const char *group)
+{
+ int i, j, ref_count;
+ PyObject *groups_dict, *group_dict, *list, *tuple, *subscription_data,
*items;
+ const char* key;
+ int result;
+ result = playerc_blackboard_unsubscribe_from_group(self, group);
+
+ assert(self->py_private);
+ groups_dict = PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(groups_dict);
+
+ group_dict = PyDict_GetItemString(groups_dict, group);
+ if (group_dict)
+ {
+ list = PyList_New(0);
+ subscription_data = PyTuple_GetItem(self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX);
+ assert(subscription_data);
+
+ items = PyDict_Items(group_dict);
+ j = PyList_Size(items);
+ for (i = 0; i < j; i++)
{
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
- data = Py_None;
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
- assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_COMPLEX);
- str = malloc(entry->data_count);
- assert(str);
- memcpy(str, entry->data, entry->data_count);
- data = PyString_FromString(str);
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_INT:
- assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
- i = 0;
- memcpy(&i, entry->data, entry->data_count);
- data = PyLong_FromLong(i);
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_DOUBLE:
- assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_SIMPLE);
- d = 0.0;
- memcpy(&d, entry->data, entry->data_count);
- data = PyFloat_FromDouble(d);
- break;
- default:
- data = Py_None;
- break;
-
+ tuple = PyList_GetItem(items, 0);
+ key = PyString_AsString(PyTuple_GetItem(tuple, 0));
+ ref_count = playerc_blackboard___increment_reference_count__(self,
subscription_data, key, group, 0);
+ if (ref_count <= 0)
+ {
+ PyList_Append(list, PyTuple_GetItem(tuple, 0));
+ }
}
- PyDict_SetItemString(entry_dict, "data", data);
- result = PyDict_SetItemString(group_dict,key,entry_dict);
- if (result != 0)
- {
- PyErr_SetString(PyExc_RuntimeError, "Failed to create key
dictionary entry");
- return Py_None;
- }
- free(entry->key);
- free(entry->group);
- free(entry->data);
- free(entry);
- Py_INCREF(entry_dict);
- return entry_dict;
+
+ j = PyList_Size(list);
+ for (i =0; i < j; i++)
+ {
+ PyDict_DelItem(group_dict, PyList_GetItem(list, i));
+ }
}
-PyObject * subscribe_to_key(const char *key, const char *group)
+ return result;
+}
+
+int SubscribeToGroup(const char *group)
{
- return playerc_blackboard_subscribe_to_key_py( self, key, group);
+ int result;
+ result = playerc_blackboard_subscribe_to_group(self, group);
+ return result;
}
-PyObject * get_value(const char *key, const char *group)
+PyObject *GetEntry(const char *key, const char *group)
{
- PyObject *group_dict, *entry_dict, *groups;
- int refcount;
-
- groups = (PyObject *)PyTuple_GetItem(self->py_private,0);
- assert(groups);
+ int result;
+ PyObject *entry_dict, *groups_dict;
+ player_blackboard_entry_t *entry;
+
+ result = playerc_blackboard_get_entry(self, key, group, &entry);
+ if (result != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to get entry");
+ return NULL;
+ }
+ entry_dict = playerc_blackboard___convert_blackboard_entry__(self, entry);
+
+ groups_dict = PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(groups_dict);
+ assert(entry_dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict, key,
group, entry_dict);
- group_dict = (PyObject*) PyDict_GetItemString(groups, group);
- if (!group_dict)
- return playerc_blackboard_subscribe_to_key_py( self, key,
group);
- // find our key in the group, if it exists
- entry_dict = (PyObject*) PyDict_GetItemString(group_dict, key);
- if (!entry_dict)
- return playerc_blackboard_subscribe_to_key_py( self, key,
group);
- refcount = PyLong_AsLong(PyDict_GetItemString(entry_dict,
"___refcount"));
- if(refcount==0)
- return playerc_blackboard_subscribe_to_key_py( self, key,
group);
- Py_INCREF(entry_dict);
- return entry_dict;
+ free(entry->key);
+ free(entry->group);
+ free(entry->data);
+ free(entry);
+
+ return entry_dict;
}
+
+PyObject *SetEntryRaw(player_blackboard_entry_t *entry)
+{
+ int result;
+ PyObject *entry_dict, *groups_dict;
- void set_entry_raw(player_blackboard_entry_t *entry)
+ entry_dict = playerc_blackboard___convert_blackboard_entry__(self, entry);
+ groups_dict = PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(groups_dict);
+ assert(entry_dict);
+
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict,
entry->key, entry->group, entry_dict);
+ result = playerc_blackboard_set_entry(self, entry);
+ return PyInt_FromLong(result);
+}
+
+PyObject *SetEntry(PyObject *dict)
+{
+ PyObject *key, *group, *type, *subtype, *timestamp_sec, *timestamp_usec,
*data, *groups_dict;
+ char *str;
+ int i, result, length;
+ double d;
+
+ if (!PyDict_Check(dict))
{
- playerc_blackboard_set_entry(self,entry);
+ PyErr_SetString(PyExc_RuntimeError, "Expected a dictionary object.");
+ return NULL;
}
-
- PyObject *set_entry(PyObject *dict)
+
+ player_blackboard_entry_t entry;
+ memset(&entry, 0, sizeof(entry));
+
+ key = PyDict_GetItem(dict, PyString_FromString("key"));
+ group = PyDict_GetItem(dict, PyString_FromString("group"));
+ type = PyDict_GetItem(dict, PyString_FromString("type"));
+ subtype = PyDict_GetItem(dict, PyString_FromString("subtype"));
+ timestamp_sec = PyDict_GetItem(dict, PyString_FromString("timestamp_sec"));
+ timestamp_usec = PyDict_GetItem(dict, PyString_FromString("timestamp_usec"));
+ data = PyDict_GetItem(dict, PyString_FromString("data"));
+
+ if (key == NULL || group == NULL || type == NULL || subtype == NULL ||
timestamp_sec == NULL || timestamp_usec == NULL || data == NULL)
{
- PyObject *key;
- PyObject *group;
- PyObject *type;
- PyObject *subtype;
- PyObject *timestamp_sec;
- PyObject *timestamp_usec;
- PyObject *data;
- char *str;
- int i, result;
- double d;
- int length;
-
- if (!PyDict_Check(dict))
- {
- PyErr_SetString(PyExc_RuntimeError, "Expected a dictionary
object.");
- return PyLong_FromLong(-1);
- }
+ PyErr_SetString(PyExc_RuntimeError, "Dictionary object missing keys. One
or more of the following keys were not found: 'key', 'group', 'type',
'subtype', 'timestamp_sec', 'timestamp_usec', 'data'.");
+ return NULL;
+ }
- player_blackboard_entry_t entry;
- memset(&entry, 0, sizeof(entry));
-
- key = PyDict_GetItem(dict, PyString_FromString("key"));
- group = PyDict_GetItem(dict, PyString_FromString("group"));
- type = PyDict_GetItem(dict, PyString_FromString("type"));
- subtype = PyDict_GetItem(dict, PyString_FromString("subtype"));
- timestamp_sec = PyDict_GetItem(dict,
PyString_FromString("timestamp_sec"));
- timestamp_usec = PyDict_GetItem(dict,
PyString_FromString("timestamp_usec"));
- data = PyDict_GetItem(dict, PyString_FromString("data"));
-
- if (key == NULL || group == NULL || type == NULL || subtype == NULL ||
timestamp_sec == NULL || timestamp_usec == NULL || data == NULL)
- {
- PyErr_SetString(PyExc_RuntimeError, "Dictionary object missing
keys.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyString_Check(key))
- {
- PyErr_SetString(PyExc_RuntimeError, "key should be a string
type.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyString_Check(group))
- {
- PyErr_SetString(PyExc_RuntimeError, "group should be a string
type.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyLong_Check(type))
- {
- PyErr_SetString(PyExc_RuntimeError, "type should be a long
type.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyLong_Check(subtype))
- {
- PyErr_SetString(PyExc_RuntimeError, "subtype should be a long
type.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyLong_Check(timestamp_sec))
- {
- PyErr_SetString(PyExc_RuntimeError, "timestamp_sec should be a
long type.");
- return PyLong_FromLong(-1);
- }
-
- if (!PyLong_Check(timestamp_usec))
- {
- PyErr_SetString(PyExc_RuntimeError, "timestamp_usec should be a
long type");
- return PyLong_FromLong(-1);
- }
-
- entry.key = PyString_AsString(key);
- entry.key_count = strlen(entry.key) + 1;
- entry.group = PyString_AsString(key);
- entry.group_count = strlen(entry.group) + 1;
- entry.type = PyInt_AsLong(type);
- entry.subtype = PyInt_AsLong(subtype);
- entry.timestamp_sec = PyInt_AsLong(timestamp_sec);
- entry.timestamp_usec = PyInt_AsLong(timestamp_usec);
-
- switch (entry.subtype)
- {
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
- entry.data = NULL;
- entry.data_count = 0;
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
- if (!PyString_Check(data))
- {
- PyErr_SetString(PyExc_RuntimeError, "data should be a
string type.");
- return PyLong_FromLong(-1);
- }
- str = NULL;
- str = PyString_AsString(data);
- length = strlen(str) + 1;
- entry.data = malloc(length);
- assert(entry.data);
- memcpy(entry.data, str, length);
- entry.data_count = length;
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_INT:
- if (!PyLong_Check(data))
- {
- PyErr_SetString(PyExc_RuntimeError, "data should be a
long type.");
- return PyLong_FromLong(-1);
- }
- i = 0;
- i = PyInt_AsLong(data);
- length = sizeof(i);
- entry.data = malloc(length);
- assert(entry.data);
- memcpy(&entry.data, &i, length);
- entry.data_count = length;
- break;
- case PLAYERC_BLACKBOARD_DATA_SUBTYPE_DOUBLE:
- if (!PyLong_Check(data))
- {
- PyErr_SetString(PyExc_RuntimeError, "data should be a
long type.");
- return PyLong_FromLong(-1);
- }
- d = 0.0;
- d = PyLong_AsDouble(data);
- length = sizeof(d);
- entry.data = malloc(length);
- assert(entry.data);
- memcpy(&entry.data, &d, length);
- entry.data_count = length;
- break;
- default:
- entry.data = NULL;
- entry.data_count = 0;
- break;
- }
- result = playerc_blackboard_set_entry(self, &entry);
- if (result != 0)
- {
- return PyLong_FromLong(-1);
- }
- free(entry.data);
-
- return PyLong_FromLong(0);
+ if (!PyString_Check(key))
+ {
+ PyErr_SetString(PyExc_TypeError, "'key' should be a 'string' type.");
+ return NULL;
}
+
+ if (!PyString_Check(group))
+ {
+ PyErr_SetString(PyExc_TypeError, "'group' should be a 'string' type.");
+ return NULL;
+ }
+
+ if (!PyLong_Check(type))
+ {
+ PyErr_SetString(PyExc_TypeError, "'type' should be a 'long' type.");
+ return NULL;
+ }
+
+ if (!PyLong_Check(subtype))
+ {
+ PyErr_SetString(PyExc_TypeError, "'subtype' should be a 'long' type.");
+ return PyLong_FromLong(-1);
+ }
+
+ if (!PyLong_Check(timestamp_sec))
+ {
+ PyErr_SetString(PyExc_TypeError, "'timestamp_sec' should be a 'long'
type.");
+ return NULL;
+ }
+
+ if (!PyLong_Check(timestamp_usec))
+ {
+ PyErr_SetString(PyExc_TypeError, "'timestamp_usec' should be a 'long'
type");
+ return NULL;
+ }
+
+ entry.key = PyString_AsString(key);
+ entry.key_count = strlen(entry.key) + 1;
+ entry.group = PyString_AsString(key);
+ entry.group_count = strlen(entry.group) + 1;
+ entry.type = PyInt_AsLong(type);
+ entry.subtype = PyInt_AsLong(subtype);
+ entry.timestamp_sec = PyInt_AsLong(timestamp_sec);
+ entry.timestamp_usec = PyInt_AsLong(timestamp_usec);
+
+ switch (entry.subtype)
+ {
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
+ entry.data = NULL;
+ entry.data_count = 0;
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
+ if (!PyString_Check(data))
+ {
+ PyErr_SetString(PyExc_TypeError, "'data' should be a 'string' type.");
+ return NULL;
+ }
+ str = NULL;
+ str = PyString_AsString(data);
+ length = strlen(str) + 1;
+ entry.data = malloc(length);
+ assert(entry.data);
+ memcpy(entry.data, str, length);
+ entry.data_count = length;
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_INT:
+ if (!PyLong_Check(data))
+ {
+ PyErr_SetString(PyExc_TypeError, "'data' should be a 'long' type.");
+ return NULL;
+ }
+ i = 0;
+ i = PyInt_AsLong(data);
+ length = sizeof(i);
+ entry.data = malloc(length);
+ assert(entry.data);
+ memcpy(&entry.data, &i, length);
+ entry.data_count = length;
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_DOUBLE:
+ if (!PyLong_Check(data))
+ {
+ PyErr_SetString(PyExc_TypeError, "'data' should be a 'long' type.");
+ return NULL;
+ }
+ d = 0.0;
+ d = PyLong_AsDouble(data);
+ length = sizeof(d);
+ entry.data = malloc(length);
+ assert(entry.data);
+ memcpy(&entry.data, &d, length);
+ entry.data_count = length;
+ break;
+ default:
+ entry.data = NULL;
+ entry.data_count = 0;
+ break;
+ }
+
+ result = playerc_blackboard_set_entry(self, &entry);
+ groups_dict = PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX);
+ assert(groups_dict);
+ assert(entry_dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict,
entry.key, entry.group, dict);
+ free(entry.data);
+
+ return PyInt_FromLong(result);
}
+}
+
%{
// This code overrides the default swig wrapper. We use a different callback
function for the python interface.
// It performs the same functionality, but points the callback function to the
new python one.
@@ -850,10 +980,14 @@
PyErr_SetString(PyExc_RuntimeError, "Failed to create blackboard");
return NULL;
}
+
+ // Tuple item 0: Dictionary of group/keys/values. As in
dict['group']['key']=value. Updated on client.read() callback.
+ // Tuple item 1: Dictionary of keys that have been subscribed to.
+ // Tuple item 2: List of all events that have occurred. Need to call
set_queue_events(True). Updated on client.read() callback.
+ // Tuple item 3: Whether to queue all events or not. Default not. (0 for
false, non-zero for true)
+ device->py_private = Py_BuildValue("({},{},[],i)",0); // tuple of a dict and
a list to store our keys and events in
- device->py_private = Py_BuildValue("({},[],i)",0); // tuple of a dict and a
list to store our keys and events in
-
- device->on_blackboard_event = playerc_blackboard_python_on_blackboard_event;
+ device->on_blackboard_event =
playerc_blackboard___python_on_blackboard_event__;
return device;
}
Modified:
code/player/branches/release-2-1-patches/client_libs/libplayerc/dev_blackboard.c
===================================================================
---
code/player/branches/release-2-1-patches/client_libs/libplayerc/dev_blackboard.c
2008-07-17 21:30:23 UTC (rev 6885)
+++
code/player/branches/release-2-1-patches/client_libs/libplayerc/dev_blackboard.c
2008-07-18 03:15:24 UTC (rev 6886)
@@ -295,6 +295,43 @@
return 0;
}
+// Get the value of a key
+int playerc_blackboard_get_entry(playerc_blackboard_t* device, const char*
key, const char* group, player_blackboard_entry_t** entry_out)
+{
+ player_blackboard_entry_t req;
+ memset(&req, 0, sizeof(req));
+ req.key = strdup(key);
+ req.key_count = strlen(key) + 1;
+
+ req.group = strdup(group);
+ req.group_count = strlen(group) + 1;
+
+ if (playerc_client_request(device->info.client, &device->info,
+ PLAYER_BLACKBOARD_REQ_GET_ENTRY, &req, (void**)entry_out) < 0)
+ {
+ if (req.key != NULL)
+ {
+ free(req.key);
+ }
+ if (req.group != NULL)
+ {
+ free(req.group);
+ }
+ PLAYERC_ERR("failed to get to blackboard entry");
+ return -1;
+ }
+
+ if (req.key != NULL)
+ {
+ free(req.key);
+ }
+ if (req.group != NULL)
+ {
+ free(req.group);
+ }
+ return 0;
+}
+
// Unsubscribe from a blackboard key
int playerc_blackboard_unsubscribe_from_key(playerc_blackboard_t* device,
const char* key, const char* group)
{
Modified:
code/player/branches/release-2-1-patches/client_libs/libplayerc/playerc.h
===================================================================
--- code/player/branches/release-2-1-patches/client_libs/libplayerc/playerc.h
2008-07-17 21:30:23 UTC (rev 6885)
+++ code/player/branches/release-2-1-patches/client_libs/libplayerc/playerc.h
2008-07-18 03:15:24 UTC (rev 6886)
@@ -1175,6 +1175,10 @@
* responsible for freeing it. */
int playerc_blackboard_subscribe_to_key(playerc_blackboard_t *device, const
char* key, const char* group, player_blackboard_entry_t** entry);
+/** @brief Get the current value of a key, without subscribing. If entry is
none null it will be filled in with the response. The caller is
+ * responsible for freeing it. */
+int playerc_blackboard_get_entry(playerc_blackboard_t *device, const char*
key, const char* group, player_blackboard_entry_t** entry);
+
/** @brief Unsubscribe from a key. */
int playerc_blackboard_unsubscribe_from_key(playerc_blackboard_t *device,
const char* key, const char* group);
Modified:
code/player/branches/release-2-1-patches/libplayercore/interfaces/064_blackboard.def
===================================================================
---
code/player/branches/release-2-1-patches/libplayercore/interfaces/064_blackboard.def
2008-07-17 21:30:23 UTC (rev 6885)
+++
code/player/branches/release-2-1-patches/libplayercore/interfaces/064_blackboard.def
2008-07-18 03:15:24 UTC (rev 6886)
@@ -13,6 +13,8 @@
message { REQ, SUBSCRIBE_TO_GROUP, 4, player_blackboard_entry_t };
/** Request/reply subtype: unsubscribe from group. */
message { REQ, UNSUBSCRIBE_FROM_GROUP, 5, player_blackboard_entry_t };
+/** Request/reply subtype: get a value. */
+message { REQ, GET_ENTRY, 6, player_blackboard_entry_t };
+
/** Data update reply */
message { DATA, UPDATE, 1, player_blackboard_entry_t };
-
Modified:
code/player/branches/release-2-1-patches/server/drivers/blackboard/localbb/localbb.cpp
===================================================================
---
code/player/branches/release-2-1-patches/server/drivers/blackboard/localbb/localbb.cpp
2008-07-17 21:30:23 UTC (rev 6885)
+++
code/player/branches/release-2-1-patches/server/drivers/blackboard/localbb/localbb.cpp
2008-07-18 03:15:24 UTC (rev 6886)
@@ -75,6 +75,9 @@
#include <strings.h>
#include <iostream>
+bool operator ==(const player_devaddr_t &a, const player_devaddr_t &b);
+bool operator <(const player_devaddr_t &a, const player_devaddr_t &b);
+
/[EMAIL PROTECTED] EntryData
* @brief Custom blackboard-entry data representation used internally by the
driver. */
typedef struct EntryData
@@ -180,6 +183,8 @@
int Setup();
/** @brief Driver de-initialisation. */
int Shutdown();
+ /** Override the unsubscribe to stop sending events to devices
which are no longer subscribed. */
+ int Unsubscribe(player_devaddr_t addr);
// MessageHandler
/** @brief Process incoming messages.
@@ -203,6 +208,15 @@
* @return 0 for success, -1 on error.
*/
int ProcessSubscribeKeyMessage(QueuePointer &resp_queue,
player_msghdr * hdr, void * data);
+ /** @brief Process a get entry message.
+ * Retrieves the entry for the given key, but does not
subscribe to the key.
+ * Publishes the entry.
+ * @param resp_queue Player response queue.
+ * @param hdr Message header.
+ * @param data Message data.
+ * @return 0 for success, -1 on error.
+ * */
+ int ProcessGetEntryMessage(QueuePointer &resp_queue,
player_msghdr * hdr, void * data);
/** @brief Process an unsubscribe from key message.
* Removes the response queue from the list of devices
listening to that key in the map.
* @param resp_queue Player response queue.
@@ -245,7 +259,7 @@
* @param group Second identifier.
* @param resp_queue Player response queue of the subscriber.
*/
- BlackBoardEntry SubscribeKey(const string &key, const string
&group, const QueuePointer &resp_queue);
+ BlackBoardEntry SubscribeKey(const string &key, const string
&group, const QueuePointer &resp_queue, const player_devaddr_t addr);
/** @brief Remove the key and queue combination from the
listeners hash-map.
* @param key Entry key.
* @param group Second identifier.
@@ -258,7 +272,7 @@
* @param qp resp_queue Player response queue of the subscriber
* @return Vector of blackboard entries of that group
*/
- vector<BlackBoardEntry> SubscribeGroup(const string &group,
const QueuePointer &qp);
+ vector<BlackBoardEntry> SubscribeGroup(const string &group,
const QueuePointer &qp, const player_devaddr_t addr);
/**
* @brief Remove the group from the group listeners hash-map.
* @param group Entry group
@@ -281,6 +295,7 @@
/** Map of labels to entry data.
* map<group, map<key, entry> >
*/
+
map<string, map<string, BlackBoardEntry> > entries;
/** Map of labels to listening queues.
* map<group, map<key, vector<device queue> > >
@@ -291,8 +306,69 @@
* map<group, vector<device queue> >
*/
map<string, vector<QueuePointer> > group_listeners;
+
+ /** Map of queues to devices. Used to remove unneeded queues
when a device is unsubscribed. */
+ map<player_devaddr_t, QueuePointer> subscribed_devices;
};
+////////////////////////////////////////////////////////////////////////////////
+// Override the unsubscribe. Stop sending out events to unsubscribed devices.
+int LocalBB::Unsubscribe(player_devaddr_t addr)
+{
+ QueuePointer &qp = subscribed_devices[addr];
+ for (map<string, map<string, vector<QueuePointer> > >::iterator itr =
listeners.begin(); itr != listeners.end(); itr++)
+ {
+ map<string, vector<QueuePointer> > &keys = (*itr).second;
+ for (map<string, vector<QueuePointer> >::iterator jtr =
keys.begin(); jtr != keys.end(); jtr++)
+ {
+ vector<QueuePointer> &qps = (*jtr).second;
+ vector<vector<QueuePointer>::iterator> remove_list;
+ for (vector<QueuePointer>::iterator ktr = qps.begin();
ktr != qps.end(); ktr++)
+ {
+ if ((*ktr) == qp)
+ {
+ remove_list.push_back(ktr);
+ }
+ }
+ for (vector<vector<QueuePointer>::iterator>::iterator
ltr = remove_list.begin(); ltr != remove_list.end(); ltr++)
+ {
+ qps.erase(*ltr);
+ }
+ }
+ }
+
+ for (map<string, vector<QueuePointer> >::iterator itr =
group_listeners.begin(); itr != group_listeners.end(); itr++)
+ {
+ vector<QueuePointer> &qps = (*itr).second;
+ vector<vector<QueuePointer>::iterator> remove_list;
+ for (vector<QueuePointer>::iterator jtr = qps.begin(); jtr !=
qps.end(); jtr++)
+ {
+ if ((*jtr) == qp)
+ {
+ remove_list.push_back(jtr);
+ }
+ }
+ for (vector<vector<QueuePointer>::iterator>::iterator ltr =
remove_list.begin(); ltr != remove_list.end(); ltr++)
+ {
+ qps.erase(*ltr);
+ }
+ }
+ int shutdownResult;
+ if(subscriptions == 0)
+ shutdownResult = -1;
+ else if ( subscriptions == 1)
+ {
+ shutdownResult = Shutdown();
+ subscriptions--;
+ }
+ else
+ {
+ subscriptions--;
+ shutdownResult = 0;
+ }
+
+ return shutdownResult;
+}
////////////////////////////////////////////////////////////////////////////////
// Factory method.
Driver* LocalBB_Init(ConfigFile* cf, int section)
@@ -365,6 +441,10 @@
{
return ProcessUnsubscribeGroupMessage(resp_queue, hdr, data);
}
+ else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
PLAYER_BLACKBOARD_REQ_GET_ENTRY, this->device_addr))
+ {
+ return ProcessGetEntryMessage(resp_queue, hdr, data);
+ }
// Don't know how to handle this message
return -1;
}
@@ -378,7 +458,7 @@
// Add the device to the listeners map
player_blackboard_entry_t *request =
reinterpret_cast<player_blackboard_entry_t*>(data);
- BlackBoardEntry current_value = SubscribeKey(request->key,
request->group, resp_queue);
+ BlackBoardEntry current_value = SubscribeKey(request->key,
request->group, resp_queue, hdr->addr);
// Get the entry for the given key
player_blackboard_entry_t response =
ToPlayerBlackBoardEntry(current_value);
@@ -409,7 +489,47 @@
return 0;
}
+////////////////////////////////////////////////////////////////////////////////
+// Retrieve an entry for a key.
+int LocalBB::ProcessGetEntryMessage(QueuePointer &resp_queue, player_msghdr *
hdr, void * data)
+{
+ if (!CheckHeader(hdr))
+ return -1;
+ // Retrieve the entry for the key
+ player_blackboard_entry_t *request =
reinterpret_cast<player_blackboard_entry_t*>(data);
+ BlackBoardEntry current_value =
entries[string(request->group)][string(request->key)];
+
+ // Convert the entry
+ player_blackboard_entry_t response =
ToPlayerBlackBoardEntry(current_value);
+ size_t response_size = sizeof(player_blackboard_entry_t) +
response.key_count + response.group_count + response.data_count;
+
+ // Publish the blackboard entry
+ this->Publish(
+ this->device_addr,
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK,
+ PLAYER_BLACKBOARD_REQ_GET_ENTRY,
+ &response,
+ response_size,
+ NULL);
+
+ if (response.key)
+ {
+ delete [] response.key;
+ }
+ if (response.group)
+ {
+ delete [] response.group;
+ }
+ if (response.data)
+ {
+ delete [] response.data;
+ }
+
+ return 0;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Unsubscribe a device from a key.
int LocalBB::ProcessUnsubscribeKeyMessage(QueuePointer &resp_queue,
player_msghdr * hdr, void * data)
@@ -443,10 +563,9 @@
// Add the device to the listeners map
player_blackboard_entry_t *request =
reinterpret_cast<player_blackboard_entry_t*>(data);
- vector<BlackBoardEntry> current_values = SubscribeGroup(request->group,
resp_queue);
+ vector<BlackBoardEntry> entries = SubscribeGroup(request->group,
resp_queue, hdr->addr);
- // Get the entries for the given key and send the data updates
- for (vector<BlackBoardEntry>::iterator itr=current_values.begin(); itr
!= current_values.end(); itr++)
+ for (vector<BlackBoardEntry>::iterator itr = entries.begin(); itr !=
entries.end(); itr++)
{
BlackBoardEntry current_value = *itr;
player_blackboard_entry_t response =
ToPlayerBlackBoardEntry(current_value);
@@ -504,7 +623,7 @@
this->device_addr,
resp_queue,
PLAYER_MSGTYPE_RESP_ACK,
- PLAYER_BLACKBOARD_REQ_UNSUBSCRIBE_FROM_KEY,
+ PLAYER_BLACKBOARD_REQ_UNSUBSCRIBE_FROM_GROUP,
NULL,
0,
NULL);
@@ -567,9 +686,10 @@
////////////////////////////////////////////////////////////////////////////////
// Add a device to the listener list for a key. Return the current value of
the entry.
-BlackBoardEntry LocalBB::SubscribeKey(const string &key, const string &group,
const QueuePointer &resp_queue)
+BlackBoardEntry LocalBB::SubscribeKey(const string &key, const string &group,
const QueuePointer &resp_queue, const player_devaddr_t addr)
{
listeners[group][key].push_back(resp_queue);
+ subscribed_devices[addr] = resp_queue;
BlackBoardEntry entry = entries[group][key];
if (entry.key == "")
{
@@ -597,17 +717,27 @@
////////////////////////////////////////////////////////////////////////////////
// Add a device to the group listener map. Return vector of entries for that
group.
-vector<BlackBoardEntry> LocalBB::SubscribeGroup(const string &group, const
QueuePointer &qp)
+vector<BlackBoardEntry> LocalBB::SubscribeGroup(const string &group, const
QueuePointer &qp, const player_devaddr_t addr)
{
group_listeners[group].push_back(qp);
+ subscribed_devices[addr] = qp;
+
vector<BlackBoardEntry> group_entries;
-
- // Add all entries for a group to the group_entries vector
//map<group, map<key, entry> >
- map<string, BlackBoardEntry> entry_map = entries[group];
+ map<string, BlackBoardEntry> &entry_map = entries[group];
+
for (map<string, BlackBoardEntry>::iterator itr = entry_map.begin();
itr != entry_map.end(); itr++)
{
- group_entries.push_back((*itr).second);
+ BlackBoardEntry current_value = (*itr).second;
+ if (current_value.key == "")
+ {
+ current_value.key = (*itr).first;
+ }
+ if (current_value.group == "")
+ {
+ current_value.group = group;
+ }
+ group_entries.push_back(current_value);
}
return group_entries;
}
@@ -646,3 +776,27 @@
}
return true;
}
+
+
+bool operator ==(const player_devaddr_t &a, const player_devaddr_t &b)
+{
+ return (a.host == b.host) && (a.robot == b.robot) && (a.interf ==
b.interf) && (a.index == b.index);
+}
+
+bool operator <(const player_devaddr_t &a, const player_devaddr_t &b)
+{
+ if (a.host != b.host)
+ {
+ return a.host < b.host;
+ }
+ else if (a.robot != b.robot)
+ {
+ return a.robot < b.robot;
+ }
+ else if (a.interf != b.interf)
+ {
+ return a.interf < b.interf;
+ }
+
+ return a.index < b.index;
+}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit