6 changed files with 168 additions and 38 deletions
@ -1,50 +1,92 @@ |
|||||
import random |
import random |
||||
import gipc |
|
||||
import gevent |
import gevent |
||||
import string |
import string |
||||
import weakref |
import weakref |
||||
|
import marshal |
||||
|
import types |
||||
|
|
||||
|
from holster.enum import Enum |
||||
|
|
||||
|
from disco.util.logging import LoggingClass |
||||
|
|
||||
|
|
||||
def get_random_str(size): |
def get_random_str(size): |
||||
return ''.join([random.choice(string.ascii_printable) for _ in range(size)]) |
return ''.join([random.choice(string.printable) for _ in range(size)]) |
||||
|
|
||||
|
|
||||
|
IPCMessageType = Enum( |
||||
|
'CALL_FUNC', |
||||
|
'GET_ATTR', |
||||
|
'EXECUTE', |
||||
|
'RESPONSE', |
||||
|
) |
||||
|
|
||||
|
|
||||
class GIPCProxy(object): |
class GIPCProxy(LoggingClass): |
||||
def __init__(self, pipe): |
def __init__(self, obj, pipe): |
||||
|
super(GIPCProxy, self).__init__() |
||||
|
self.obj = obj |
||||
self.pipe = pipe |
self.pipe = pipe |
||||
self.results = weakref.WeakValueDictionary() |
self.results = weakref.WeakValueDictionary() |
||||
gevent.spawn(self.read_loop) |
gevent.spawn(self.read_loop) |
||||
|
|
||||
def read_loop(self): |
def resolve(self, parts): |
||||
while True: |
base = self.obj |
||||
nonce, data = self.pipe.get() |
for part in parts: |
||||
if nonce in self.results: |
base = getattr(base, part) |
||||
self.results[nonce].set(data) |
|
||||
|
|
||||
def __getattr__(self, name): |
return base |
||||
def wrapper(*args, **kwargs): |
|
||||
nonce = get_random_str() |
|
||||
self.results[nonce] = gevent.event.AsyncResult() |
|
||||
self.pipe.put(nonce, name, args, kwargs) |
|
||||
return self.results[nonce] |
|
||||
return wrapper |
|
||||
|
|
||||
|
def send(self, typ, data): |
||||
|
self.pipe.put((typ.value, data)) |
||||
|
|
||||
class GIPCObject(object): |
def handle(self, mtype, data): |
||||
def __init__(self, inst, pipe): |
if mtype == IPCMessageType.CALL_FUNC: |
||||
self.inst = inst |
nonce, func, args, kwargs = data |
||||
self.pipe = pipe |
res = self.resolve(func)(*args, **kwargs) |
||||
gevent.spawn(self.read_loop) |
self.send(IPCMessageType.RESPONSE, (nonce, res)) |
||||
|
elif mtype == IPCMessageType.GET_ATTR: |
||||
|
nonce, path = data |
||||
|
self.send(IPCMessageType.RESPONSE, (nonce, self.resolve(path))) |
||||
|
elif mtype == IPCMessageType.EXECUTE: |
||||
|
nonce, raw = data |
||||
|
func = types.FunctionType(marshal.loads(raw), globals(), nonce) |
||||
|
try: |
||||
|
result = func(self.obj) |
||||
|
except Exception as e: |
||||
|
self.log.exception('Failed to EXECUTE: ') |
||||
|
result = None |
||||
|
|
||||
|
self.send(IPCMessageType.RESPONSE, (nonce, result)) |
||||
|
elif mtype == IPCMessageType.RESPONSE: |
||||
|
nonce, res = data |
||||
|
if nonce in self.results: |
||||
|
self.results[nonce].set(res) |
||||
|
|
||||
def read_loop(self): |
def read_loop(self): |
||||
while True: |
while True: |
||||
nonce, func, args, kwargs = self.pipe.get() |
mtype, data = self.pipe.get() |
||||
func = getattr(self.inst, func) |
|
||||
self.pipe.put((nonce, func(*args, **kwargs))) |
try: |
||||
|
self.handle(mtype, data) |
||||
|
except: |
||||
|
self.log.exception('Error in GIPCProxy:') |
||||
|
|
||||
|
def execute(self, func): |
||||
|
nonce = get_random_str(32) |
||||
|
raw = marshal.dumps(func.func_code) |
||||
|
self.results[nonce] = result = gevent.event.AsyncResult() |
||||
|
self.pipe.put((IPCMessageType.EXECUTE.value, (nonce, raw))) |
||||
|
return result |
||||
|
|
||||
class IPC(object): |
def get(self, path): |
||||
def __init__(self, sharder): |
nonce = get_random_str(32) |
||||
self.sharder = sharder |
self.results[nonce] = result = gevent.event.AsyncResult() |
||||
|
self.pipe.put((IPCMessageType.GET_ATTR.value, (nonce, path))) |
||||
|
return result |
||||
|
|
||||
def get_shards(self): |
def call(self, path, *args, **kwargs): |
||||
return {} |
nonce = get_random_str(32) |
||||
|
self.results[nonce] = result = gevent.event.AsyncResult() |
||||
|
self.pipe.put((IPCMessageType.CALL_FUNC.value, (nonce, path, args, kwargs))) |
||||
|
return result |
||||
|
Loading…
Reference in new issue