Revision: 6913
http://playerstage.svn.sourceforge.net/playerstage/?rev=6913&view=rev
Author: thjc
Date: 2008-07-23 07:14:31 +0000 (Wed, 23 Jul 2008)
Log Message:
-----------
Merged 6886 and 6907 from 2-1
blackboard interface/driver and proxy fixes
Modified Paths:
--------------
code/player/trunk/client_libs/libplayerc/bindings/python/playerc.i
code/player/trunk/client_libs/libplayerc/dev_blackboard.c
code/player/trunk/client_libs/libplayerc/playerc.h
code/player/trunk/libplayercore/interfaces/064_blackboard.def
code/player/trunk/server/drivers/blackboard/localbb/localbb.cpp
Property Changed:
----------------
code/player/trunk/
Property changes on: code/player/trunk
___________________________________________________________________
Modified: svn:mergeinfo
- /code/player/branches/release-2-1-patches:6672-6673,6738,6834
+ /code/player/branches/release-2-1-patches:6672-6673,6738,6834,6886
Modified: code/player/trunk/client_libs/libplayerc/bindings/python/playerc.i
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/python/playerc.i
2008-07-23 06:40:18 UTC (rev 6912)
+++ code/player/trunk/client_libs/libplayerc/bindings/python/playerc.i
2008-07-23 07:14:31 UTC (rev 6913)
@@ -28,7 +28,7 @@
memset(buffer, 0, blength );
//result is of type playerc_rfidtag_t
- unsigned int j;
+ unsigned int j;
unsigned int guid_count=$1[i].guid_count;
//copy the bytes into the buffer
@@ -416,432 +416,672 @@
%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.
+// Returns a new reference to a 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;
+ int ok;
- group_dict = (PyObject*) PyDict_GetItemString(groups, entry.group);
- if (!group_dict)
- {
- return;
- }
+ entry_dict = PyDict_New(); // New reference
+ assert (entry_dict);
+
+ assert(entry);
+ assert(entry->key);
+ assert(entry->key_count > 0);
+ assert(entry->group);
+ assert(entry->group_count > 0);
+
+ ok = PyDict_SetItemString(entry_dict, "key",
PyString_FromString(entry->key)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'key'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
+
+ ok = PyDict_SetItemString(entry_dict, "group",
PyString_FromString(entry->group)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'group'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
- // find our key in the group, if it exists
- entry_dict = (PyObject*) PyDict_GetItemString(group_dict, entry.key);
- if (!entry_dict)
- {
- return;
- }
+ ok = PyDict_SetItemString(entry_dict, "type", PyLong_FromLong(entry->type));
// Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'type'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
- 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)
+ ok = PyDict_SetItemString(entry_dict, "subtype",
PyLong_FromLong(entry->subtype)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'subtype'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
+
+ ok = PyDict_SetItemString(entry_dict, "timestamp_sec",
PyLong_FromLong(entry->timestamp_sec)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'timestamp_sec'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
+
+ ok = PyDict_SetItemString(entry_dict, "timestamp_usec",
PyLong_FromLong(entry->timestamp_usec)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'timestamp_usec'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
+
+ switch(entry->subtype)
+ {
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_NONE:
+ data = Py_None;
+ Py_INCREF(data);
+ break;
+ case PLAYERC_BLACKBOARD_DATA_SUBTYPE_STRING:
+ assert(entry->type == PLAYERC_BLACKBOARD_DATA_TYPE_COMPLEX);
+ str = malloc(entry->data_count);
+ if (!str)
+ {
+ Py_XDECREF(entry_dict);
+ return PyErr_NoMemory();
+ }
+ 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;
+ Py_INCREF(data);
+ break;
+ }
+
+ ok = PyDict_SetItemString(entry_dict, "data", data); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Could not set dictionary value for
'data'");
+ Py_XDECREF(entry_dict);
+ return NULL;
+ }
+
+ return entry_dict;
+}
+
+// Helper function which sets a value in a nested dictionary. Equivalent of
dict['group']['key'] = value.
+// Steals the entry reference.
+PyObject *__set_nested_dictionary_entry__(PyObject *dict, const char* key,
const char* group, PyObject *entry)
+{
+ PyObject *group_dict;
+ int ok;
+ 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); // Borrowed
reference
+ if (!group_dict)
+ {
+ create_dict = 1;
+ group_dict = PyDict_New(); // New reference
+ }
+
+ ok = PyDict_SetItemString(group_dict, key, entry); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set dictionary entry");
+ if (create_dict)
{
- 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;
+ Py_XDECREF(group_dict);
}
+ return NULL;
+ }
- 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));
- }
+ // If we created the dictionary, we need to put it in the parent dictionary.
+ if (create_dict == 1)
+ {
+ ok = PyDict_SetItemString(dict, group, group_dict); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set dictionary entry");
+ Py_XDECREF(group_dict);
+ return NULL;
+ }
+ }
+
+ Py_RETURN_NONE;
}
-// Will always return a list object. Returns a list of dictionary objects
containing the event data.
-PyObject *get_events()
+// 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 *list, *copy;
- int i, j;
+ PyObject *group_dict, *entry;
+ int old_value, new_value;
+
+ // Get the dictionary for the entry's group. If it doesn't exist.
+ group_dict = (PyObject*)PyDict_GetItemString(dict, group); // Borrowed
reference
+ if (!group_dict)
+ {
+ playerc_blackboard___set_nested_dictionary_entry__(self, dict, key, group,
(PyObject*)PyInt_FromLong(inc)); // Steals reference to entry
+ return inc;
+ }
+
+ entry = PyDict_GetItemString(group_dict, key); // Borrowed reference
+ if (entry)
+ {
+ old_value = PyLong_AsLong(entry);
+ }
+ else
+ {
+ old_value = 0;
+ }
+
+ 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)); // Steals reference to entry
+
+ 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); // Borrowed reference
+ assert(groups_dict);
+
+ // Get a dictionary of the entry
+ entry_dict = playerc_blackboard___convert_blackboard_entry__(device,
&entry); // New reference
+ assert(entry_dict);
+
+ // If we are queueing events, add them to the list
+ queue_events = PyTuple_GetItem(device->py_private, BOOL_QUEUE_EVENTS_INDEX);
// Borrowed reference
+ assert(queue_events);
+ if (PyLong_AsLong(queue_events) != 0)
+ {
+ list = (PyObject*)PyTuple_GetItem(device->py_private, LIST_EVENTS_INDEX);
// Borrowed reference
+ assert(list);
+ PyList_Append(list, entry_dict); // Increments refcount for us
+ }
+
+ // Set the entry in the groups dictionary
+ playerc_blackboard___set_nested_dictionary_entry__(device, groups_dict,
entry.key, entry.group, entry_dict); // Steals reference to 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, *item;
+ int i, j, ok;
+
assert(self->py_private);
+ list = (PyObject*)PyTuple_GetItem(self->py_private, LIST_EVENTS_INDEX); //
Borrowed reference
+ assert(list);
- list = (PyObject*)PyTuple_GetItem(self->py_private,1);
- copy = PyList_New(0);
j = PyList_Size(list);
+ copy = PyList_New(j); // New reference
+
for (i = 0; i < j; i++)
{
- PyList_Append(copy, PyList_GetItem(list, 0));
+ item = PyList_GetItem(list, 0); // Borrowed reference
+ Py_INCREF(item);
+ assert(item);
+ ok = PyList_SetItem(copy, i, item); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set list entry");
+ Py_XDECREF(copy);
+ Py_XDECREF(item);
+ return NULL;
+ }
PySequence_DelItem(list,0);
}
+
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;
+
+ assert(self->py_private);
+ dict = (PyObject*)PyTuple_GetItem(self->py_private, DICT_GROUPS_INDEX); //
Borrowed reference
+ assert(dict);
+
+ copy = PyDict_Copy(dict); // New reference
+ return copy;
+}
+
+// Set whether events should be put into the list, to be retrieved by
get_events_list().
+PyObject *SetQueueEvents(PyObject *boolean)
+{
+ int ok;
+
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));
+ ok = PyTuple_SetItem((PyObject*)self->py_private, BOOL_QUEUE_EVENTS_INDEX,
PyLong_FromLong(0)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set tuple entry");
+ return NULL;
+ }
}
else
{
- PyTuple_SetItem(self->py_private,2,PyLong_FromLong(1));
+ ok = PyTuple_SetItem((PyObject*)self->py_private, BOOL_QUEUE_EVENTS_INDEX,
PyLong_FromLong(1)); // Steals reference
+ if (ok != 0)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Failed to set tuple entry");
+ return NULL;
+ }
}
+
+ 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((PyObject*)self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX); // Borrowed reference
+ assert(subscription_data);
+ ref_count = playerc_blackboard___increment_reference_count__(self,
subscription_data, key, group, -1);
+ if (ref_count <= 0)
+ {
+ groups_dict = PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+ group_dict = PyDict_GetItemString(groups_dict, group); // Borrowed
reference
+ 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);
// New reference
+ assert(entry_dict);
+ groups_dict = (PyObject*)PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+
+ Py_INCREF(entry_dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict, key,
group, entry_dict); // Steals reference to entry_dict
+
+ subscription_data = PyTuple_GetItem((PyObject*)self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX); // Borrowed reference
+ 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, *item;
+ const char* key;
+ int result;
+
+ result = playerc_blackboard_unsubscribe_from_group(self, group);
+
+ assert(self->py_private);
+ groups_dict = PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+
+ group_dict = PyDict_GetItemString(groups_dict, group); // Borrowed reference
+ if (group_dict)
+ {
+ list = PyList_New(0); // New reference
+ subscription_data = PyTuple_GetItem((PyObject*)self->py_private,
DICT_SUBSCRIPTION_DATA_INDEX); // Borrowed reference
+ 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); // Borrowed reference
+ assert(tuple);
+ item = PyTuple_GetItem(tuple, 0); // Borrowed reference
+ assert(item);
+ key = PyString_AsString(item);
+ ref_count = playerc_blackboard___increment_reference_count__(self,
subscription_data, key, group, 0);
+ if (ref_count <= 0)
+ {
+ PyList_Append(list, item); // Increments refcount for us
+ }
+ }
+ j = PyList_Size(list);
+ for (i =0; i < j; i++)
+ {
+ item = PyList_GetItem(list, i); // Borrowed reference
+ assert(item);
+ PyDict_DelItem(group_dict, item);
}
- 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;
+
+ Py_DECREF(list);
}
-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);
// New reference
+
+ groups_dict = PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+ assert(entry_dict);
+ Py_INCREF(entry_dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict, key,
group, entry_dict); // Steals reference to 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);
// New reference
+ assert(entry_dict);
+ groups_dict = PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict,
entry->key, entry->group, entry_dict); // Steals reference to 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)
- {
- 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;
+ player_blackboard_entry_t entry;
+ memset(&entry, 0, sizeof(entry));
- if (!PyDict_Check(dict))
- {
- PyErr_SetString(PyExc_RuntimeError, "Expected a dictionary
object.");
- return PyLong_FromLong(-1);
- }
+ key = PyDict_GetItem(dict, PyString_FromString("key")); // Borrowed reference
+ group = PyDict_GetItem(dict, PyString_FromString("group")); // Borrowed
reference
+ type = PyDict_GetItem(dict, PyString_FromString("type")); // Borrowed
reference
+ subtype = PyDict_GetItem(dict, PyString_FromString("subtype")); // Borrowed
reference
+ timestamp_sec = PyDict_GetItem(dict, PyString_FromString("timestamp_sec"));
// Borrowed reference
+ timestamp_usec = PyDict_GetItem(dict,
PyString_FromString("timestamp_usec")); // Borrowed reference
+ data = PyDict_GetItem(dict, PyString_FromString("data")); // Borrowed
reference
- player_blackboard_entry_t entry;
- memset(&entry, 0, sizeof(entry));
+ 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. One
or more of the following keys were not found: 'key', 'group', 'type',
'subtype', 'timestamp_sec', 'timestamp_usec', 'data'.");
+ return NULL;
+ }
- 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 (!PyString_Check(key))
+ {
+ PyErr_SetString(PyExc_TypeError, "'key' should be a 'string' type.");
+ return NULL;
+ }
- 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(group))
+ {
+ PyErr_SetString(PyExc_TypeError, "'group' should be a 'string' type.");
+ return NULL;
+ }
- if (!PyString_Check(key))
- {
- PyErr_SetString(PyExc_RuntimeError, "key should be a string
type.");
- return PyLong_FromLong(-1);
- }
+ if (!PyLong_Check(type))
+ {
+ PyErr_SetString(PyExc_TypeError, "'type' should be a 'long' type.");
+ return NULL;
+ }
- if (!PyString_Check(group))
- {
- PyErr_SetString(PyExc_RuntimeError, "group should be a string
type.");
- return PyLong_FromLong(-1);
- }
+ if (!PyLong_Check(subtype))
+ {
+ PyErr_SetString(PyExc_TypeError, "'subtype' should be a 'long' 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(timestamp_sec))
+ {
+ PyErr_SetString(PyExc_TypeError, "'timestamp_sec' should be a 'long'
type.");
+ return NULL;
+ }
- if (!PyLong_Check(subtype))
- {
- PyErr_SetString(PyExc_RuntimeError, "subtype should be a long
type.");
- return PyLong_FromLong(-1);
- }
+ if (!PyLong_Check(timestamp_usec))
+ {
+ PyErr_SetString(PyExc_TypeError, "'timestamp_usec' should be a 'long'
type");
+ return NULL;
+ }
- if (!PyLong_Check(timestamp_sec))
- {
- PyErr_SetString(PyExc_RuntimeError, "timestamp_sec 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);
- if (!PyLong_Check(timestamp_usec))
- {
- PyErr_SetString(PyExc_RuntimeError, "timestamp_usec should be a
long type");
- return PyLong_FromLong(-1);
- }
+ 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;
+ }
- 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);
+ result = playerc_blackboard_set_entry(self, &entry);
+ groups_dict = PyTuple_GetItem((PyObject*)self->py_private,
DICT_GROUPS_INDEX); // Borrowed reference
+ assert(groups_dict);
+ Py_INCREF(dict);
+ playerc_blackboard___set_nested_dictionary_entry__(self, groups_dict,
entry.key, entry.group, dict); // Steals reference to entry
+ free(entry.data);
- 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 PyInt_FromLong(result);
+}
- return PyLong_FromLong(0);
- }
}
%{
// 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.
+// It performs the same functionality, but points the callback function to the
new python one.
playerc_blackboard_t *python_playerc_blackboard_create(playerc_client_t
*client, int index)
{
playerc_blackboard_t *device= playerc_blackboard_create(client, index);
@@ -850,10 +1090,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 = (void*)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;
}
@@ -866,7 +1110,7 @@
playerc_device_term(&device->info);
if (device->py_private != NULL)
{
- Py_DECREF((PyObject*)device->py_private);
+ Py_XDECREF((PyObject*)device->py_private);
}
free(device);
}
Modified: code/player/trunk/client_libs/libplayerc/dev_blackboard.c
===================================================================
--- code/player/trunk/client_libs/libplayerc/dev_blackboard.c 2008-07-23
06:40:18 UTC (rev 6912)
+++ code/player/trunk/client_libs/libplayerc/dev_blackboard.c 2008-07-23
07:14:31 UTC (rev 6913)
@@ -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/trunk/client_libs/libplayerc/playerc.h
===================================================================
--- code/player/trunk/client_libs/libplayerc/playerc.h 2008-07-23 06:40:18 UTC
(rev 6912)
+++ code/player/trunk/client_libs/libplayerc/playerc.h 2008-07-23 07:14:31 UTC
(rev 6913)
@@ -1174,6 +1174,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/trunk/libplayercore/interfaces/064_blackboard.def
===================================================================
--- code/player/trunk/libplayercore/interfaces/064_blackboard.def
2008-07-23 06:40:18 UTC (rev 6912)
+++ code/player/trunk/libplayercore/interfaces/064_blackboard.def
2008-07-23 07:14:31 UTC (rev 6913)
@@ -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/trunk/server/drivers/blackboard/localbb/localbb.cpp
===================================================================
--- code/player/trunk/server/drivers/blackboard/localbb/localbb.cpp
2008-07-23 06:40:18 UTC (rev 6912)
+++ code/player/trunk/server/drivers/blackboard/localbb/localbb.cpp
2008-07-23 07:14:31 UTC (rev 6913)
@@ -69,12 +69,14 @@
#include <stdlib.h>
#include <libplayercore/playercore.h>
#include <libplayercore/error.h>
-// #include <libplayerc++/playererror.h>
#include <vector>
#include <map>
#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 +182,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 +207,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 +258,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 +271,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
@@ -267,8 +280,8 @@
void UnsubscribeGroup(const string &group, const QueuePointer
&qp);
/** @brief Set the entry in the entries hashmap. *
- * @param entry BlackBoardEntry that must be put in the hashmap.
- */
+ * @param entry BlackBoardEntry that must be put in the hashmap.
+ */
void SetEntry(const BlackBoardEntry &entry);
// Helper functions
@@ -281,17 +294,80 @@
/** 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> > >
*/
map<string, map<string, vector<QueuePointer> > > listeners;
+
/** Map of groups to queues subscribed to groups.
* 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)
@@ -364,6 +440,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;
}
@@ -377,7 +457,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);
@@ -408,7 +488,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)
@@ -438,14 +558,13 @@
int LocalBB::ProcessSubscribeGroupMessage(QueuePointer &resp_queue,
player_msghdr * hdr, void * data)
{
if (!CheckHeader(hdr))
- return -1;
+ return -1;
// 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);
@@ -503,7 +622,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);
@@ -566,9 +685,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 == "")
{
@@ -596,17 +716,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;
+ //map<group, map<key, entry> >
+ map<string, BlackBoardEntry> &entry_map = entries[group];
- // Add all entries for a group to the group_entries vector
- //map<group, map<key, entry> >
- 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;
}
@@ -645,3 +775,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