NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

serviceProxy.py (6053B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\sys\serviceProxy.py
      2 import zlib
      3 import types
      4 import inspect
      5 import random
      6 import uthread
      7 from cluster import NODES, NODE_ALL, NODE_ANY, NODE_ALL_SERVER, NODE_ALL_PROXY, NODE_ANY_SERVER, NODE_ANY_PROXY
      8 from cluster import SERVICE_MODS, SERVICE_MOD_DEFAULT
      9 from eveprefs import prefs
     10 
     11 class ServiceProxy(object):
     12     __guid__ = 'service.ServiceProxy'
     13     _methods = {}
     14 
     15     def __init__(self, serviceName, session):
     16         self._serviceName = serviceName
     17         self._session = session
     18         if serviceName not in self._methods or prefs.clusterMode == 'LOCAL':
     19             self._methods[serviceName] = self._WrapService(serviceName)
     20         for methodName, method in self._methods[serviceName].iteritems():
     21             setattr(self, methodName, types.MethodType(method, self, self.__class__))
     22 
     23     def __repr__(self):
     24         return '<ServiceProxy service=%s session=%s>' % (str(self._serviceName), str(self._session))
     25 
     26     def _WrapService(self, serviceName):
     27         import svc
     28         serviceClass = getattr(svc, sm.GetServiceImplementation(serviceName))
     29         defaultResolve = getattr(serviceClass, '__serviceproxyresolve__', None)
     30         exportedCalls = getattr(serviceClass, '__exportedcalls__', {})
     31         exportedCalls = [ (k, v) for k, v in exportedCalls.iteritems() if isinstance(v, dict) ]
     32         wrappedMethods = {}
     33         for methodName, definition in exportedCalls:
     34             resolve = definition.get('resolve', defaultResolve)
     35             if resolve is not None:
     36                 wrappedMethods[methodName] = self._WrapServiceMethod(methodName, getattr(serviceClass, methodName), resolve)
     37 
     38         return wrappedMethods
     39 
     40     def _WrapServiceMethod(self, methodName, method, resolve):
     41         resolveConst, resolveArgument = resolve
     42         argspec = inspect.getargspec(method)
     43         if isinstance(resolveArgument, str):
     44             resolveArgumentIndex = argspec[0].index(resolveArgument) - 1
     45         elif isinstance(resolveArgument, int) and resolveArgument in NODES:
     46             resolveArgumentIndex = None
     47         else:
     48             raise RuntimeError("Resolve argument '%s' for ServiceProxy '%s' is invalid" % (str(resolveArgument), self))
     49 
     50         def wrapped(self, *args, **kwargs):
     51             try:
     52                 if resolveArgumentIndex is None:
     53                     resolveValue = resolveArgument
     54                 else:
     55                     resolveValue = kwargs.get(resolveArgument, args[resolveArgumentIndex])
     56                     if isinstance(resolveValue, basestring):
     57                         resolveValue = zlib.crc32(resolveValue)
     58                     elif resolveValue is None:
     59                         resolveValue = 0
     60             except ValueError:
     61                 raise RuntimeError("ServiceProxy could not find the resolve argument '%s' for the method '%s'" % (str(resolveArgument), methodName))
     62 
     63             if resolveArgument == NODE_ALL:
     64                 nodes = self._GetNodesFromServiceID(resolveConst, server=True, proxy=True)
     65             elif resolveArgument == NODE_ALL_SERVER:
     66                 nodes = self._GetNodesFromServiceID(resolveConst, server=True)
     67             elif resolveArgument == NODE_ALL_PROXY:
     68                 nodes = self._GetNodesFromServiceID(resolveConst, proxy=True)
     69             elif resolveArgument == NODE_ANY:
     70                 nodes = random.choice(self._GetNodesFromServiceID(resolveConst, server=True, proxy=True))
     71             elif resolveArgument == NODE_ANY_SERVER:
     72                 nodes = random.choice(self._GetNodesFromServiceID(resolveConst, server=True))
     73             elif resolveArgument == NODE_ANY_PROXY:
     74                 nodes = random.choice(self._GetNodesFromServiceID(resolveConst, proxy=True))
     75             else:
     76                 machoNet = sm.GetService('machoNet').session.ConnectToSolServerService('machoNet')
     77                 serviceMod = SERVICE_MODS.get(resolveConst, SERVICE_MOD_DEFAULT)
     78                 nodes = machoNet.GetNodeFromAddress(resolveConst, resolveValue % serviceMod)
     79             return ServiceProxyCall(self._session, self._serviceName, methodName, nodes)(*args, **kwargs)
     80 
     81         execdict = {'wrapped': wrapped}
     82         exec 'def %s%s: return wrapped(%s)' % (methodName, inspect.formatargspec(*argspec), ', '.join(argspec[0])) in execdict
     83         wrapped = execdict.get(methodName, wrapped)
     84         setattr(wrapped, '__doc__', method.__doc__)
     85         setattr(wrapped, '__name__', method.__name__)
     86         return wrapped
     87 
     88     def _GetNodesFromServiceID(self, serviceID, server = False, proxy = False):
     89         machoNet = sm.GetService('machoNet')
     90         serviceMask = 1 << serviceID - 1
     91         nodes = machoNet.ResolveServiceMaskToNodeIDs(serviceMask)
     92         if serviceMask & machoNet.serviceMask:
     93             nodes.add(machoNet.GetNodeID())
     94         if proxy == False:
     95             nodes = [ nodeID for nodeID in nodes if nodeID < const.maxNodeID ]
     96         if server == False:
     97             nodes = [ nodeID for nodeID in nodes if nodeID >= const.maxNodeID ]
     98         if not len(nodes):
     99             raise RuntimeError('ServiceProxy::GetNodesFromServiceID found no nodes for serviceID=%s (server=%s, proxy=%s)' % (serviceID, server, proxy))
    100         return list(nodes)
    101 
    102 
    103 class ServiceProxyCall(object):
    104     __guid__ = 'service.ServiceProxyCall'
    105 
    106     def __init__(self, session, serviceName, methodName, nodes):
    107         self._session = session
    108         self._serviceName = serviceName
    109         self._methodName = methodName
    110         self._nodes = nodes
    111 
    112     def __call__(self, *args, **kwargs):
    113         if not isinstance(self._nodes, (list, set, tuple)):
    114             return self._CallNode(self._nodes, *args, **kwargs)
    115         calls = [ (self._CallNode, [nodeID] + list(args), kwargs) for nodeID in self._nodes ]
    116         return uthread.parallel(calls)
    117 
    118     def _CallNode(self, nodeID, *args, **kwargs):
    119         service = self._session.ConnectToRemoteService(self._serviceName, nodeID=nodeID)
    120         return getattr(service, self._methodName)(*args, **kwargs)