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 move_entries(self,
                  move_before=None,
                  delete_after_move=False,
                  query=None):
     move_before = move_before or rospy.Duration(self.interval)
     if query is None:
         query = {}
     query = StringPairList(pairs=[
         StringPair(first=MongoQueryMsgRequest.JSON_QUERY,
                    second=json_util.dumps(query))
     ])
     goal = MoveEntriesGoal(database=self.database,
                            collections=StringList(self.collections),
                            move_before=move_before,
                            delete_after_move=delete_after_move,
                            query=query)
     self.replicate_ac.send_goal(goal,
                                 done_cb=self.done_cb,
                                 active_cb=self.active_cb,
                                 feedback_cb=self.feedback_cb)
     while not self.replicate_ac.wait_for_result(
             timeout=rospy.Duration(5.0)):
         if rospy.is_shutdown():
             break
         elif self.monitor_network and not self.network_connected:
             rospy.loginfo(
                 "disconnected wired network connection. canceling replication..."
             )
             self.replicate_ac.cancel_all_goals()
Beispiel #4
0
	def query(self, type, message_query = {}, meta_query = {}, single = False, sort_query = []):
		"""
		Finds and returns message(s) matching the message and meta data queries.
		
		:Parameters:
		    | type (str): The ROS message type of the stored messsage to retrieve.
		    | message_query (dict): A query to match the actual ROS message
		    | meta_query (dict): A query to match against the meta data of the message
		    | sort_query (list of tuple): A query to request sorted list to mongodb module
		    | single (bool): Should only one message be returned?
		:Returns:
		    | [message, meta] where message is the queried message and meta a dictionary of
		      meta information. If single is false returns a list of these lists.
		"""
		# assume meta is a dict, convert k/v to tuple pairs for ROS msg type

		# serialise the json queries to strings using json_util.dumps
		message_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(message_query, default=json_util.default)),)
		meta_tuple = (StringPair(dc_srv.MongoQueryMsgRequest.JSON_QUERY, json.dumps(meta_query, default=json_util.default)),)
		if len(sort_query) > 0:
				sort_tuple = [StringPair(str(k), str(v)) for k, v in sort_query]
		else:
				sort_tuple = []

		# a tuple of SerialisedMessages
		response = self.query_id_srv(self.database, self.collection, type, single, StringPairList(message_tuple), StringPairList(meta_tuple), StringPairList(sort_tuple))

		# print response

		if response.messages is None:
			messages = []
			metas = []
		else:
			messages = map(dc_util.deserialise_message, response.messages) 
			metas = map(dc_util.string_pair_list_to_dictionary, response.metas)

		if single:
			if len(messages) > 0:
				return [messages[0], metas[0]]
			else:				
				return [None, None]
		else:
			return zip(messages,metas)
Beispiel #5
0
    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]
Beispiel #6
0
        quaternion = Quaternion(10, 11, 12, 13)
        # note that everything that is pass to the message_store must be a ros message type
        #therefore use std_msg types for standard data types like float, int, bool, string etc
        result = Bool(True)

        # we will store our results in a separate collection
        msg_store = MessageStoreProxy(collection='pose_results')
        # save the ids from each addition
        stored = []
        stored.append([pose._type, msg_store.insert(pose)])
        stored.append([point._type, msg_store.insert(point)])
        stored.append([quaternion._type, msg_store.insert(quaternion)])
        stored.append([result._type, msg_store.insert(result)])

        # now store ids togther in store, addition types for safety
        spl = StringPairList()
        for pair in stored:
            spl.pairs.append(StringPair(pair[0], pair[1]))

        # and add some meta information
        meta = {}
        meta['description'] = "this wasn't great"
        meta['result_time'] = datetime.utcfromtimestamp(
            rospy.get_rostime().to_sec())
        msg_store.insert(spl, meta=meta)

        # now let's get all our logged data back
        results = msg_store.query(StringPairList._type)
        for message, meta in results:
            if 'description' in meta:
                print 'description: %s' % meta['description']
Beispiel #7
0
        type=str,
        default='{}',
        help='Only entries that are matched by the query are moved.')
    return p.parse_args(args)


if __name__ == '__main__':
    rospy.init_node("mongodb_replicator_client")

    args = parse_args(rospy.myargv()[1:])

    # validate parameters
    try:
        data = json_util.loads(args.query)
        query = StringPairList(pairs=[
            StringPair(first=MongoQueryMsgRequest.JSON_QUERY,
                       second=json_util.dumps(data))
        ])
    except:
        raise ValueError('The query is invalid')
    if args.move_before < 0:
        raise ValueError('move_before time must be >= 0')
    move_before = rospy.Duration(args.move_before)
    goal = MoveEntriesGoal(database=args.database,
                           collections=StringList(args.collection),
                           move_before=move_before,
                           delete_after_move=args.delete_after_move,
                           query=query)

    rospy.loginfo('Moves entries from (db: %s, cols: %s)' %
                  (args.database, args.collection))
    rospy.loginfo('before time: %s' % (rospy.Time.now() - move_before))