def insert(self, message, meta={}, wait=True): """ Inserts a ROS message into the message storage. :Args: | message (ROS Message): An instance of a ROS message type to store | meta (dict): A dictionary of additional meta data to store in association with thie message. | wait (bool): If true, waits until database returns object id after insert :Returns: | (str) the ObjectId of the MongoDB document containing the stored message. """ # assume meta is a dict, convert k/v to tuple pairs meta_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta, default=json_util.default)), ) serialised_msg = dc_util.serialise_message(message) if wait: return self.insert_srv(self.database, self.collection, serialised_msg, StringPairList(meta_tuple)).id else: msg = Insert(self.database, self.collection, serialised_msg, StringPairList(meta_tuple)) self.pub_insert.publish(msg) return True
def update(self, message, meta={}, message_query={}, meta_query={}, upsert=False): """ Updates a message. :Args: | message (ROS Message): The updated ROS message | meta (dict): Updated meta data to store with the message. | message_query (dict): A query to match the ROS message that is to be updated. | meta_query (dict): A query to match against the meta data of the message to be updated | upsert (bool): If True, insert the named message if it doesnt exist. :Return: | str, bool: The MongoDB ObjectID of the document, and whether it was altered by the update. """ # serialise the json queries to strings using json_util.dumps message_query_tuple = (StringPair( dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(message_query, default=json_util.default)), ) meta_query_tuple = (StringPair( dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta_query, default=json_util.default)), ) meta_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta, default=json_util.default)), ) return self.update_srv(self.database, self.collection, upsert, StringPairList(message_query_tuple), StringPairList(meta_query_tuple), dc_util.serialise_message(message), StringPairList(meta_tuple))
def query_messages_ros_srv(self, req): """ Returns t """ collection = self._mongo_client[req.database][req.collection] # build the query doc obj_query = self.to_query_dict(req.message_query, req.meta_query) # restrict results to have the type asked for obj_query["_meta.stored_type"] = req.type # TODO start using some string constants! rospy.logdebug("query document: %s", obj_query) # this is a list of entries in dict format including meta sort_query_dict = dc_util.string_pair_list_to_dictionary(req.sort_query) sort_query_tuples = [] for k,v in sort_query_dict.iteritems(): try: sort_query_tuples.append((k, int(v))) except ValueError: sort_query_tuples.append((k,v)) entries = dc_util.query_message(collection, obj_query, sort_query_tuples, req.single, req.limit) # keep trying clients until we find an answer for extra_client in self.extra_clients: if len(entries) == 0: extra_collection = extra_client[req.database][req.collection] entries = dc_util.query_message(extra_collection, obj_query, sort_query_tuples, req.single, req.limit) if len(entries) > 0: rospy.loginfo("found result in extra datacentre") else: break # rospy.logdebug("entries: %s", entries) serialised_messages = () metas = () for entry in entries: # load the class object for this type # TODO this should be the same for every item in the list, so could reuse cls = dc_util.load_class(entry["_meta"]["stored_class"]) # instantiate the ROS message object from the dictionary retrieved from the db message = dc_util.dictionary_to_message(entry, cls) # the serialise this object in order to be sent in a generic form serialised_messages = serialised_messages + (dc_util.serialise_message(message), ) # add ObjectID into meta as it might be useful later entry["_meta"]["_id"] = entry["_id"] # serialise meta metas = metas + (StringPairList([StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(entry["_meta"], default=json_util.default))]), ) return [serialised_messages, metas]
def insert_msg(message, database='message_store', collection='message_store'): sp = (StringPair(MongoQueryMsgRequest.JSON_QUERY, json.dumps({}, default=json_util.default)),) # deserialize data into object obj = dc_util.deserialise_message(dc_util.serialise_message(message)) # obj = to_msg(message) # convert input tuple to dict meta = dc_util.string_pair_list_to_dictionary(StringPairList(sp)) # get requested collection from the db, creating if necessary collection = _mongo_client[database][collection] meta['inserted_at'] = datetime.utcfromtimestamp(rospy.get_rostime().to_sec()) meta['inserted_by'] = 'asdf' obj_id = dc_util.store_message(collection, obj, meta) return str(obj_id)
def insert(self, message, meta = {}): """ Inserts a ROS message into the message storage. :Args: | message (ROS Message): An instance of a ROS message type to store | meta (dict): A dictionary of additional meta data to store in association with thie message. :Returns: | (str) the ObjectId of the MongoDB document containing the stored message. """ # assume meta is a dict, convert k/v to tuple pairs meta_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta, default=json_util.default)),) serialised_msg = dc_util.serialise_message(message) return self.insert_srv(self.database, self.collection, serialised_msg, StringPairList(meta_tuple)).id
def query_messages_ros_srv(self, req): """ Returns t """ collection = self._mongo_client[req.database][req.collection] # build the query doc obj_query = self.to_query_dict(req.message_query, req.meta_query) # restrict results to have the type asked for obj_query["_meta.stored_type"] = req.type # TODO start using some string constants! rospy.logdebug("query document: %s", obj_query) # this is a list of entries in dict format including meta sort_query_dict = dc_util.string_pair_list_to_dictionary( req.sort_query) sort_query_tuples = [] for k, v in iteritems(sort_query_dict): try: sort_query_tuples.append((k, int(v))) except ValueError: sort_query_tuples.append((k, v)) # this is a list of entries in dict format including meta projection_query_dict = dc_util.string_pair_list_to_dictionary( req.projection_query) projection_meta_dict = dict() projection_meta_dict["_meta"] = 1 entries = dc_util.query_message(collection, obj_query, sort_query_tuples, projection_query_dict, req.single, req.limit) if projection_query_dict: meta_entries = dc_util.query_message(collection, obj_query, sort_query_tuples, projection_meta_dict, req.single, req.limit) # keep trying clients until we find an answer if self.replicate_on_write: for extra_client in self.extra_clients: if len(entries) == 0: extra_collection = extra_client[req.database][ req.collection] entries = dc_util.query_message(extra_collection, obj_query, sort_query_tuples, projection_query_dict, req.single, req.limit) if projection_query_dict: meta_entries = dc_util.query_message( extra_collection, obj_query, sort_query_tuples, projection_meta_dict, req.single, req.limit) if len(entries) > 0: rospy.loginfo("found result in extra datacentre") else: break serialised_messages = () metas = () for idx, entry in enumerate(entries): # load the class object for this type # TODO this should be the same for every item in the list, so could reuse cls = dc_util.load_class(entry["_meta"]["stored_class"]) # instantiate the ROS message object from the dictionary retrieved from the db message = dc_util.dictionary_to_message(entry, cls) # the serialise this object in order to be sent in a generic form serialised_messages = serialised_messages + ( dc_util.serialise_message(message), ) # add ObjectID into meta as it might be useful later if projection_query_dict: entry["_meta"]["_id"] = meta_entries[idx]["_id"] else: entry["_meta"]["_id"] = entry["_id"] # serialise meta metas = metas + (StringPairList([ StringPair( dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(entry["_meta"], default=json_util.default)) ]), ) return [serialised_messages, metas]
def update(self, message, meta = {}, message_query = {}, meta_query = {}, upsert = False): """ Updates a message. :Args: | message (ROS Message): The updated ROS message | meta (dict): Updated meta data to store with the message. | message_query (dict): A query to match the ROS message that is to be updated. | meta_query (dict): A query to match against the meta data of the message to be updated | upsert (bool): If True, insert the named message if it doesnt exist. :Return: | str, bool: The MongoDB ObjectID of the document, and whether it was altered by the update. """ # serialise the json queries to strings using json_util.dumps message_query_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(message_query, default=json_util.default)),) meta_query_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta_query, default=json_util.default)),) meta_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta, default=json_util.default)),) return self.update_srv(self.database, self.collection, upsert, StringPairList(message_query_tuple), StringPairList(meta_query_tuple), dc_util.serialise_message(message), StringPairList(meta_tuple))