blob: 531170967740dc2c3d88e60c924badbf6b116eb4 [file] [log] [blame]
Brad Bishopa34c0302019-09-23 22:34:48 -04001# Copyright (C) 2019 Garmin Ltd.
2#
3# SPDX-License-Identifier: GPL-2.0-only
4#
5
Andrew Geissler6ce62a22020-11-30 19:58:47 -06006import asyncio
Brad Bishopa34c0302019-09-23 22:34:48 -04007import json
8import logging
9import socket
Brad Bishop00e122a2019-10-05 11:10:57 -040010import os
Andrew Geisslerc926e172021-05-07 16:11:35 -050011import bb.asyncrpc
12from . import create_async_client
Brad Bishopa34c0302019-09-23 22:34:48 -040013
14
Andrew Geissler6ce62a22020-11-30 19:58:47 -060015logger = logging.getLogger("hashserv.client")
Brad Bishopa34c0302019-09-23 22:34:48 -040016
17
Andrew Geisslerc926e172021-05-07 16:11:35 -050018class AsyncClient(bb.asyncrpc.AsyncClient):
Brad Bishopa34c0302019-09-23 22:34:48 -040019 MODE_NORMAL = 0
20 MODE_GET_STREAM = 1
21
22 def __init__(self):
Andrew Geisslerc926e172021-05-07 16:11:35 -050023 super().__init__('OEHASHEQUIV', '1.1', logger)
Brad Bishopa34c0302019-09-23 22:34:48 -040024 self.mode = self.MODE_NORMAL
25
Andrew Geisslerc926e172021-05-07 16:11:35 -050026 async def setup_connection(self):
27 await super().setup_connection()
28 cur_mode = self.mode
29 self.mode = self.MODE_NORMAL
30 await self._set_mode(cur_mode)
Brad Bishopa34c0302019-09-23 22:34:48 -040031
Andrew Geissler6ce62a22020-11-30 19:58:47 -060032 async def send_stream(self, msg):
33 async def proc():
34 self.writer.write(("%s\n" % msg).encode("utf-8"))
35 await self.writer.drain()
36 l = await self.reader.readline()
Brad Bishopa34c0302019-09-23 22:34:48 -040037 if not l:
Andrew Geisslerc926e172021-05-07 16:11:35 -050038 raise ConnectionError("Connection closed")
Andrew Geissler6ce62a22020-11-30 19:58:47 -060039 return l.decode("utf-8").rstrip()
Brad Bishopa34c0302019-09-23 22:34:48 -040040
Andrew Geissler6ce62a22020-11-30 19:58:47 -060041 return await self._send_wrapper(proc)
Brad Bishopa34c0302019-09-23 22:34:48 -040042
Andrew Geissler6ce62a22020-11-30 19:58:47 -060043 async def _set_mode(self, new_mode):
Brad Bishopa34c0302019-09-23 22:34:48 -040044 if new_mode == self.MODE_NORMAL and self.mode == self.MODE_GET_STREAM:
Andrew Geissler6ce62a22020-11-30 19:58:47 -060045 r = await self.send_stream("END")
46 if r != "ok":
Andrew Geisslerc926e172021-05-07 16:11:35 -050047 raise ConnectionError("Bad response from server %r" % r)
Brad Bishopa34c0302019-09-23 22:34:48 -040048 elif new_mode == self.MODE_GET_STREAM and self.mode == self.MODE_NORMAL:
Andrew Geissler6ce62a22020-11-30 19:58:47 -060049 r = await self.send_message({"get-stream": None})
50 if r != "ok":
Andrew Geisslerc926e172021-05-07 16:11:35 -050051 raise ConnectionError("Bad response from server %r" % r)
Brad Bishopa34c0302019-09-23 22:34:48 -040052 elif new_mode != self.mode:
Andrew Geissler6ce62a22020-11-30 19:58:47 -060053 raise Exception(
54 "Undefined mode transition %r -> %r" % (self.mode, new_mode)
55 )
Brad Bishopa34c0302019-09-23 22:34:48 -040056
57 self.mode = new_mode
58
Andrew Geissler6ce62a22020-11-30 19:58:47 -060059 async def get_unihash(self, method, taskhash):
60 await self._set_mode(self.MODE_GET_STREAM)
61 r = await self.send_stream("%s %s" % (method, taskhash))
Brad Bishopa34c0302019-09-23 22:34:48 -040062 if not r:
63 return None
64 return r
65
Andrew Geissler6ce62a22020-11-30 19:58:47 -060066 async def report_unihash(self, taskhash, method, outhash, unihash, extra={}):
67 await self._set_mode(self.MODE_NORMAL)
Brad Bishopa34c0302019-09-23 22:34:48 -040068 m = extra.copy()
Andrew Geissler6ce62a22020-11-30 19:58:47 -060069 m["taskhash"] = taskhash
70 m["method"] = method
71 m["outhash"] = outhash
72 m["unihash"] = unihash
73 return await self.send_message({"report": m})
Brad Bishopa34c0302019-09-23 22:34:48 -040074
Andrew Geissler6ce62a22020-11-30 19:58:47 -060075 async def report_unihash_equiv(self, taskhash, method, unihash, extra={}):
76 await self._set_mode(self.MODE_NORMAL)
Andrew Geissler82c905d2020-04-13 13:39:40 -050077 m = extra.copy()
Andrew Geissler6ce62a22020-11-30 19:58:47 -060078 m["taskhash"] = taskhash
79 m["method"] = method
80 m["unihash"] = unihash
81 return await self.send_message({"report-equiv": m})
Andrew Geissler82c905d2020-04-13 13:39:40 -050082
Andrew Geissler6ce62a22020-11-30 19:58:47 -060083 async def get_taskhash(self, method, taskhash, all_properties=False):
84 await self._set_mode(self.MODE_NORMAL)
85 return await self.send_message(
86 {"get": {"taskhash": taskhash, "method": method, "all": all_properties}}
87 )
Andrew Geissler475cb722020-07-10 16:00:51 -050088
Andrew Geisslerd1e89492021-02-12 15:35:20 -060089 async def get_outhash(self, method, outhash, taskhash):
90 await self._set_mode(self.MODE_NORMAL)
91 return await self.send_message(
92 {"get-outhash": {"outhash": outhash, "taskhash": taskhash, "method": method}}
93 )
94
Andrew Geissler6ce62a22020-11-30 19:58:47 -060095 async def get_stats(self):
96 await self._set_mode(self.MODE_NORMAL)
97 return await self.send_message({"get-stats": None})
Brad Bishopa34c0302019-09-23 22:34:48 -040098
Andrew Geissler6ce62a22020-11-30 19:58:47 -060099 async def reset_stats(self):
100 await self._set_mode(self.MODE_NORMAL)
101 return await self.send_message({"reset-stats": None})
102
103 async def backfill_wait(self):
104 await self._set_mode(self.MODE_NORMAL)
105 return (await self.send_message({"backfill-wait": None}))["tasks"]
106
107
Andrew Geisslerc926e172021-05-07 16:11:35 -0500108class Client(bb.asyncrpc.Client):
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600109 def __init__(self):
Andrew Geisslerc926e172021-05-07 16:11:35 -0500110 super().__init__()
111 self._add_methods(
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600112 "connect_tcp",
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600113 "close",
114 "get_unihash",
115 "report_unihash",
116 "report_unihash_equiv",
117 "get_taskhash",
118 "get_stats",
119 "reset_stats",
120 "backfill_wait",
Andrew Geisslerc926e172021-05-07 16:11:35 -0500121 )
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600122
Andrew Geisslerc926e172021-05-07 16:11:35 -0500123 def _get_async_client(self):
124 return AsyncClient()