예제 #1
0
    async def call_node(self, path: str, data):
        self.log.info("Got request for path %s", path)
        if path == "search":
            if isinstance(data, query_pb2.Query):
                query = data
            else:
                query = query_pb2.Query()
                query.ParseFromString(data)
            if not self._am_i_closer_and_update_query(query):
                return []
            data = query.SerializeToString()
        elif path == "update":
            self.error("GOT update", data)
            if isinstance(data, update_pb2.Update):
                data = data.SerializeToString()

        result = await self.callMe(path, data)
        if path == "update":
            self.notify_update()
        elif path == "search":
            #TODO(AB): HACK. do this in a nice way
            core_id = self._id.replace("-search", "-core").encode("UTF-8")
            res = response_pb2.SearchResponse()
            res.ParseFromString(result)
            for r in res.result:
                if r.key == core_id:
                    r.distance = self.location.distance(
                        query.directed_search.target.geo)
            result = res.SerializeToString()
        return result
예제 #2
0
 async def async_search(self, query):
     self.log.info("Got search query with TTL %d", query.ttl)
     my_location = self.search_com.call("get", "location")
     my_distance = my_location.distance(query.directed_search.target.geo)
     query.source_key = self._bin_id
     query.directed_search.distance.geo = my_distance + 1.
     result = await self.search_com.call_node("search", query)
     res = response_pb2.SearchResponse()
     res.ParseFromString(result)
     for r in res.result:
         if r.key == self._bin_id:
             res.result.remove(r)
     return res
예제 #3
0
 def merge_response(self, resps: List[DataWrapper[response_pb2.SearchResponse]]) -> \
         DataWrapper[response_pb2.SearchResponse]:
     resp = response_pb2.SearchResponse()
     error_code = 1000
     narrative = []
     keys = []
     success = False
     for r in resps:
         result = []
         success |= r.success
         error_code = min(error_code, r.error_code)
         narrative.extend(r.narrative)
         for rr in r.data.result:
             if rr.key in keys:
                 continue
             keys.append(rr.key)
             result.append(rr)
         resp.result.extend(result)
     return DataWrapper(success, "search", resp, error_code, "", narrative)
예제 #4
0
 async def handle_message(
         self,
         msg: query_pb2.Query) -> DataWrapper[response_pb2.SearchResponse]:
     global _count_request, _count_success, _count_exception, _count_ignored, _count_empty
     resp = response_pb2.SearchResponse()
     distance = None
     _count_request.inc()
     try:
         location = self._dap_manager.getPlaneInformation(
             "location")["values"]
         if len(location) > 1:
             self.warning(
                 "Got more then 1 location from dapManager (I'm using first, ignoring the rest now): ",
                 location)
         #TODO: multiple core
         location = location[0].value.l
         prev_distance = msg.directed_search.distance.geo
         target = msg.directed_search.target.geo
         distance = geo_distance(location, target)
         if prev_distance > 0 and distance > prev_distance:
             #ignore query
             _count_ignored.inc()
             self.warning(
                 "Ignoring query with TTL %d, because source (%s) distance (%.3f) was smaller then "
                 "my distance (%.3f)", msg.ttl,
                 msg.source_key.decode("UTF-8"), prev_distance, distance)
             return DataWrapper(False, "search", resp, 601,
                                "Ignoring query because distance!")
         else:
             self.info(
                 "Handling query with TTL %d, because source (%s) distance (%.3f) was greater then"
                 " my distance (%.3f)", msg.ttl,
                 msg.source_key.decode("UTF-8"), prev_distance, distance)
     except Exception as e:
         #TODO: what?
         self.info("Exception during location check: ", str(e))
         #return DataWrapper(False, "search", resp, 600, "Ignoring query, location check error!")
         _count_exception.inc()
     try:
         query = self._proto_wrapper.get_instance(msg)
         result = self._dap_manager.execute(query.toDapQuery())
         items = {}
         for element in result.identifiers:
             core, agent_id = element.core, element.agent
             if core not in items:
                 item = response_pb2.SearchResponse.Item()
                 address = element.uri.split(":")
                 if len(address) == 2:
                     item.ip = address[0]
                     item.port = int(address[1])
                 elif len(address) == 3:
                     item.ip = address[1]
                     item.port = int(address[2])
                 else:
                     self.warning("No valid address for core: ", core,
                                  "! address=", address)
                     continue
                 item.key = core
                 items[core] = item
                 if distance:
                     #TODO multiple core
                     item.distance = distance
             agent = items[core].agents.add()
             agent.key = agent_id
             agent.score = element.score
         resp.result.extend(items.values())
         self.info("SEARCH RESULT: ", resp)
         if len(items) == 0:
             _count_empty.inc()
     except Exception as e:
         self.exception("Exception while processing query: ", str(e))
         _count_exception.inc()
         return DataWrapper(False, "search", resp, 500, str(e))
     _count_success.inc()
     return DataWrapper(True, "search", resp)
예제 #5
0
 def get_response_type(self):
     return response_pb2.SearchResponse().__class__