class RequestPacket(util.struct): mapcls_context = util.mapclass(util.string, util.string) mapcls_status = util.mapclass(util.string, util.string) def __init__(self): self.iVersion = 0 self.cPacketType = 0 self.iMessageType = 0 self.iRequestId = 0 self.sServantName = '' self.sFuncName = '' self.sBuffer = bytes() self.iTimeout = 0 self.context = RequestPacket.mapcls_context() self.status = RequestPacket.mapcls_status() @staticmethod def writeTo(oos, value): oos.write(util.int16, 1, value.iVersion) oos.write(util.int8, 2, value.cPacketType) oos.write(util.int32, 3, value.iMessageType) oos.write(util.int32, 4, value.iRequestId) oos.write(util.string, 5, value.sServantName) oos.write(util.string, 6, value.sFuncName) oos.write(util.bytes, 7, value.sBuffer) oos.write(util.int32, 8, value.iTimeout) oos.write(RequestPacket.mapcls_context, 9, value.context) oos.write(RequestPacket.mapcls_status, 10, value.status) @staticmethod def readFrom(ios): value = RequestPacket() value.iVersion = ios.read(util.int16, 1, True, 0) print("iVersion = %d" % value.iVersion) value.cPacketType = ios.read(util.int8, 2, True, 0) print("cPackerType = %d" % value.cPacketType) value.iMessageType = ios.read(util.int32, 3, True, 0) print("iMessageType = %d" % value.iMessageType) value.iRequestId = ios.read(util.int32, 4, True, 0) print("iRequestId = %d" % value.iRequestId) value.sServantName = ios.read(util.string, 5, True, '22222222') value.sFuncName = ios.read(util.string, 6, True, '') value.sBuffer = ios.read(util.bytes, 7, True, value.sBuffer) value.iTimeout = ios.read(util.int32, 8, True, 0) value.context = ios.read(RequestPacket.mapcls_context, 9, True, value.context) value.status = ios.read(RequestPacket.mapcls_status, 10, True, value.status) return value
class ResponsePacket(util.struct): __tars_class__ = "tars.RpcMessage.ResponsePacket" mapcls_status = util.mapclass(util.string, util.string) def __init__(self): self.iVersion = 0 self.cPacketType = 0 self.iRequestId = 0 self.iMessageType = 0 self.iRet = 0 self.sBuffer = bytes() self.status = RequestPacket.mapcls_status() @staticmethod def writeTo(oos, value): oos.write(util.int16, 1, value.iVersion) oos.write(util.int8, 2, value.cPacketType) oos.write(util.int32, 3, value.iRequestId) oos.write(util.int32, 4, value.iMessageType) oos.write(util.int32, 5, value.iRet) oos.write(util.bytes, 6, value.sBuffer) oos.write(value.mapcls_status, 7, value.status) @staticmethod def readFrom(ios): value = ResponsePacket() value.iVersion = ios.read(util.int16, 1, True) value.cPacketType = ios.read(util.int8, 2, True) value.iRequestId = ios.read(util.int32, 3, True) value.iMessageType = ios.read(util.int32, 4, True) value.iRet = ios.read(util.int32, 5, True) value.sBuffer = ios.read(util.bytes, 6, True) value.status = ios.read(value.mapcls_status, 7, True) return value
class ServantProxy(object): ''' @brief: 1、远程对象的本地代理 2、同名servant在一个通信器中最多只有一个实例 3、防止和用户在Tars中定义的函数名冲突,接口以tars_开头 ''' # 服务器响应的错误码 TARSSERVERSUCCESS = 0 # 服务器端处理成功 TARSSERVERDECODEERR = -1 # 服务器端解码异常 TARSSERVERENCODEERR = -2 # 服务器端编码异常 TARSSERVERNOFUNCERR = -3 # 服务器端没有该函数 TARSSERVERNOSERVANTERR = -4 # 服务器端五该Servant对象 TARSSERVERRESETGRID = -5 # 服务器端灰度状态不一致 TARSSERVERQUEUETIMEOUT = -6 # 服务器队列超过限制 TARSASYNCCALLTIMEOUT = -7 # 异步调用超时 TARSPROXYCONNECTERR = -8 # proxy链接异常 TARSSERVERUNKNOWNERR = -99 # 服务器端未知异常 TARSVERSION = 1 TUPVERSION = 2 TUPVERSION2 = 3 TARSNORMAL = 0 TARSONEWAY = 1 TARSMESSAGETYPENULL = 0 TARSMESSAGETYPEHASH = 1 TARSMESSAGETYPEGRID = 2 TARSMESSAGETYPEDYED = 4 TARSMESSAGETYPESAMPLE = 8 TARSMESSAGETYPEASYNC = 16 mapcls_context = util.mapclass(util.string, util.string) def __init__(self): tarsLogger.debug('ServantProxy:__init__') self.__reactor = None self.__object = None self.__initialize = False def __del__(self): tarsLogger.debug('ServantProxy:__del__') def _initialize(self, reactor, obj): ''' @brief: 初始化函数,需要调用才能使用ServantProxy @param reactor: 网络管理的reactor实例 @type reactor: FDReactor @return: None @rtype: None ''' tarsLogger.debug('ServantProxy:_initialize') assert (reactor and obj) if self.__initialize: return self.__reactor = reactor self.__object = obj self.__initialize = True def _terminate(self): ''' @brief: 不再使用ServantProxy时调用,会释放相应资源 @return: None @rtype: None ''' tarsLogger.debug('ServantProxy:_terminate') self.__object = None self.__reactor = None self.__initialize = False def tars_name(self): ''' @brief: 获取ServantProxy的名字 @return: ServantProxy的名字 @rtype: str ''' return self.__object.name() def tars_timeout(self): ''' @brief: 获取超时时间,单位是ms @return: 超时时间 @rtype: int ''' # 默认的为3S = ObjectProxy.DEFAULT_TIMEOUT return int(self.__timeout() * 1000) def tars_ping(self): pass # def tars_initialize(self): # pass # def tars_terminate(self): # pass def tars_invoke(self, cPacketType, sFuncName, sBuffer, context, status): ''' @brief: TARS协议同步方法调用 @param cPacketType: 请求包类型 @type cPacketType: int @param sFuncName: 调用函数名 @type sFuncName: str @param sBuffer: 序列化后的发送参数 @type sBuffer: str @param context: 上下文件信息 @type context: ServantProxy.mapcls_context @param status: 状态信息 @type status: @return: 响应报文 @rtype: ResponsePacket ''' tarsLogger.debug('ServantProxy:tars_invoke, func: %s', sFuncName) req = RequestPacket() req.iVersion = ServantProxy.TARSVERSION req.cPacketType = cPacketType req.iMessageType = ServantProxy.TARSMESSAGETYPENULL req.iRequestId = 0 req.sServantName = self.tars_name() req.sFuncName = sFuncName req.sBuffer = sBuffer req.iTimeout = self.tars_timeout() reqmsg = ReqMessage() reqmsg.type = ReqMessage.SYNC_CALL reqmsg.servant = self reqmsg.lock = threading.Condition() reqmsg.request = req reqmsg.begtime = time.time() # # test reqmsg.isHash = True reqmsg.isConHash = True reqmsg.hashCode = 123456 rsp = None try: rsp = self.__invoke(reqmsg) except exception.TarsSyncCallTimeoutException: if reqmsg.adapter: reqmsg.adapter.finishInvoke(True) raise except TarsException: raise except: raise TarsException('ServantProxy::tars_invoke excpetion') if reqmsg.adapter: reqmsg.adapter.finishInvoke(False) return rsp def tars_invoke_async(self, cPacketType, sFuncName, sBuffer, context, status, callback): ''' @brief: TARS协议同步方法调用 @param cPacketType: 请求包类型 @type cPacketType: int @param sFuncName: 调用函数名 @type sFuncName: str @param sBuffer: 序列化后的发送参数 @type sBuffer: str @param context: 上下文件信息 @type context: ServantProxy.mapcls_context @param status: 状态信息 @type status: @param callback: 异步调用回调对象 @type callback: ServantProxyCallback的子类 @return: 响应报文 @rtype: ResponsePacket ''' tarsLogger.debug('ServantProxy:tars_invoke') req = RequestPacket() req.iVersion = ServantProxy.TARSVERSION req.cPacketType = cPacketType if callback else ServantProxy.TARSONEWAY req.iMessageType = ServantProxy.TARSMESSAGETYPENULL req.iRequestId = 0 req.sServantName = self.tars_name() req.sFuncName = sFuncName req.sBuffer = sBuffer req.iTimeout = self.tars_timeout() reqmsg = ReqMessage() reqmsg.type = ReqMessage.ASYNC_CALL if callback else ReqMessage.ONE_WAY reqmsg.callback = callback reqmsg.servant = self reqmsg.request = req reqmsg.begtime = time.time() rsp = None try: rsp = self.__invoke(reqmsg) except TarsException: raise except Exception: raise TarsException('ServantProxy::tars_invoke excpetion') if reqmsg.adapter: reqmsg.adapter.finishInvoke(False) return rsp def __timeout(self): ''' @brief: 获取超时时间,单位是s @return: 超时时间 @rtype: float ''' return self.__object.timeout() def __invoke(self, reqmsg): ''' @brief: 远程过程调用 @param reqmsg: 请求数据 @type reqmsg: ReqMessage @return: 调用成功或失败 @rtype: bool ''' tarsLogger.debug('ServantProxy:invoke, func: %s', reqmsg.request.sFuncName) ret = self.__object.invoke(reqmsg) if ret == -2: errmsg = ('ServantProxy::invoke fail, no valid servant,' + ' servant name : %s, function name : %s' % (reqmsg.request.sServantName, reqmsg.request.sFuncName)) raise TarsException(errmsg) if ret == -1: errmsg = ('ServantProxy::invoke connect fail,' + ' servant name : %s, function name : %s, adapter : %s' % (reqmsg.request.sServantName, reqmsg.request.sFuncName, reqmsg.adapter.getEndPointInfo())) raise TarsException(errmsg) elif ret != 0: errmsg = ('ServantProxy::invoke unknown fail, ' + 'Servant name : %s, function name : %s' % (reqmsg.request.sServantName, reqmsg.request.sFuncName)) raise TarsException(errmsg) if reqmsg.type == ReqMessage.SYNC_CALL: reqmsg.lock.acquire() reqmsg.lock.wait(self.__timeout()) reqmsg.lock.release() if not reqmsg.response: errmsg = ('ServantProxy::invoke timeout: %d, servant name' ': %s, adapter: %s, request id: %d' % (self.tars_timeout(), self.tars_name(), reqmsg.adapter.trans().getEndPointInfo(), reqmsg.request.iRequestId)) raise exception.TarsSyncCallTimeoutException(errmsg) elif reqmsg.response.iRet == ServantProxy.TARSSERVERSUCCESS: return reqmsg.response else: errmsg = 'servant name: %s, function name: %s' % ( self.tars_name(), reqmsg.request.sFuncName) self.tarsRaiseException(reqmsg.response.iRet, errmsg) def _finished(self, reqmsg): ''' @brief: 通知远程过程调用线程响应报文到了 @param reqmsg: 请求响应报文 @type reqmsg: ReqMessage @return: 函数执行成功或失败 @rtype: bool ''' tarsLogger.debug('ServantProxy:finished') if not reqmsg.lock: return False reqmsg.lock.acquire() reqmsg.lock.notifyAll() reqmsg.lock.release() return True def tarsRaiseException(self, errno, desc): ''' @brief: 服务器调用失败,根据服务端给的错误码抛出异常 @param errno: 错误码 @type errno: int @param desc: 错误描述 @type desc: str @return: 没有返回值,函数会抛出异常 @rtype: ''' if errno == ServantProxy.TARSSERVERSUCCESS: return elif errno == ServantProxy.TARSSERVERDECODEERR: raise exception.TarsServerDecodeException( "server decode exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSSERVERENCODEERR: raise exception.TarsServerEncodeException( "server encode exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSSERVERNOFUNCERR: raise exception.TarsServerNoFuncException( "server function mismatch exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSSERVERNOSERVANTERR: raise exception.TarsServerNoServantException( "server servant mismatch exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSSERVERRESETGRID: raise exception.TarsServerResetGridException( "server reset grid exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSSERVERQUEUETIMEOUT: raise exception.TarsServerQueueTimeoutException( "server queue timeout exception: errno: %d, msg: %s" % (errno, desc)) elif errno == ServantProxy.TARSPROXYCONNECTERR: raise exception.TarsServerQueueTimeoutException( "server connection lost: errno: %d, msg: %s" % (errno, desc)) else: raise exception.TarsServerUnknownException( "server unknown exception: errno: %d, msg: %s" % (errno, desc))
class ServantProxy(object): ''' @brief: 1、远程对象的本地代理 2、同名servant在一个通信器中最多只有一个实例 3、防止和用户在Tars中定义的函数名冲突,接口以tars_开头 ''' # 服务器响应的错误码 TARSSERVERSUCCESS = 0 #服务器端处理成功 TARSSERVERDECODEERR = -1 #服务器端解码异常 TARSSERVERENCODEERR = -2 #服务器端编码异常 TARSSERVERNOFUNCERR = -3 #服务器端没有该函数 TARSSERVERNOSERVANTERR = -4 #服务器端五该Servant对象 TARSSERVERRESETGRID = -5 #服务器端灰度状态不一致 TARSSERVERQUEUETIMEOUT = -6 #服务器队列超过限制 TARSASYNCCALLTIMEOUT = -7 #异步调用超时 TARSPROXYCONNECTERR = -8 #proxy链接异常 TARSSERVERUNKNOWNERR = -99 #服务器端未知异常 TARSVERSION = 1 TUPVERSION = 2 TUPVERSION2 = 3 TARSNORMAL = 0 TARSONEWAY = 1 TARSMESSAGETYPENULL = 0 TARSMESSAGETYPEHASH = 1 TARSMESSAGETYPEGRID = 2 TARSMESSAGETYPEDYED = 4 TARSMESSAGETYPESAMPLE = 8 TARSMESSAGETYPEASYNC = 16 mapcls_context = util.mapclass(util.string, util.string) def __init__(self): tarsLogger.debug('ServantProxy:__init__') self.__reactor = None self.__object = None self.__initialize = False def __del__(self): tarsLogger.debug('ServantProxy:__del__') def _initialize(self, reactor, obj): ''' @brief: 初始化函数,需要调用才能使用ServantProxy @param reactor: 网络管理的reactor实例 @type reactor: FDReactor @return: None @rtype: None ''' tarsLogger.debug('ServantProxy:_initialize') assert (reactor and obj) if self.__initialize: return self.__reactor = reactor self.__object = obj self.__initialize = True def _terminate(self): ''' @brief: 不再使用ServantProxy时调用,会释放相应资源 @return: None @rtype: None ''' tarsLogger.debug('ServantProxy:_terminate') self.__object = None self.__reactor = None self.__initialize = False def tars_name(self): ''' @brief: 获取ServantProxy的名字 @return: ServantProxy的名字 @rtype: str ''' return self.__object.name() def tars_timeout(self): ''' @brief: 获取超时时间,单位是ms @return: 超时时间 @rtype: int ''' return int(self.__timeout() * 1000) def tars_ping(self): pass #def tars_initialize(self): #pass #def tars_terminate(self): #pass def tars_invoke(self, cPacketType, sFuncName, sBuffer, context, status): ''' @brief: TARS协议同步方法调用 @param cPacketType: 请求包类型 @type cPacketType: int @param sFuncName: 调用函数名 @type sFuncName: str @param sBuffer: 序列化后的发送参数 @type sBuffer: str @param context: 上下文件信息 @type context: ServantProxy.mapcls_context @param status: 状态信息 @type status: @return: 响应报文 @rtype: ResponsePacket ''' tarsLogger.debug('ServantProxy:tars_invoke, func: %s', sFuncName) req = RequestPacket() req.iVersion = ServantProxy.TARSVERSION req.cPacketType = cPacketType req.iMessageType = ServantProxy.TARSMESSAGETYPENULL req.iRequestId = 0 req.sServantName = self.tars_name() req.sFuncName = sFuncName req.sBuffer = sBuffer req.iTimeout = self.tars_timeout() reqmsg = ReqMessage() reqmsg.type = ReqMessage.SYNC_CALL reqmsg.servant = self reqmsg.lock = threading.Condition() reqmsg.request = req reqmsg.begtime = time.time() rsp = None try: rsp = self.__invoke(reqmsg) except TarsSyncCallTimeoutException, msg: if reqmsg.adapter: reqmsg.adapter.finishInvoke(True) raise except TarsException: raise
def mapclass(ktype, vtype): return util.mapclass(ktype, vtype)
def __init__(self): self.__mapa = util.mapclass(util.string, util.bytes) self.__mapv = util.mapclass(util.string, self.__mapa) self.__buffer = self.__mapv() self.__code = RequestPacket()
def mapclass(ktype, vtype): return util.mapclass(ktype, vtype); @staticmethod
def __init__(self): self.__mapa = util.mapclass(util.string, util.bytes); self.__mapv = util.mapclass(util.string, self.__mapa); self.__buffer = self.__mapv(); self.__code = RequestPacket();
class ServantProxy(object): JCEVERSION = 1 JCENORMAL = 0x0 JCEMESSAGETYPENULL = 0x0 JCESERVERSUCCESS = 0 mapcls_context = util.mapclass(util.string, util.string) def __init__(self): self.ip = '' self.port = 0 self.sServantName = '' self.iTimeout = 3000 def locator(self, connInfo): self.sServantName, argvs = connInfo.split('@') args = argvs.lower().split() if len(args) == 0: raise Exception('string parsing error around "@"') if args[0] != 'tcp': raise Exception('unsupport transmission protocal : %s' % args[0]) i = 1 while i < len(args): if args[i] == '-h': i += 1 self.ip = args[i] elif args[i] == '-p': i += 1 self.port = int(args[i]) else: raise Exception('unkown parameter : %s' % args[i]) i += 1 if self.ip == '' or self.port == 0: raise Exception('can not find ip or port info') def taf_invoke(self, cPacketType, sFuncName, sBuffer, context, status): req = RequestPacket() req.iVersion = ServantProxy.JCEVERSION req.cPacketType = cPacketType req.iMessageType = ServantProxy.JCEMESSAGETYPENULL req.iRequestId = 0 req.sServantName = self.sServantName req.sFuncName = sFuncName req.sBuffer = sBuffer req.iTimeout = self.iTimeout oos = JceOutputStream() RequestPacket.writeTo(oos, req) reqpkt = oos.getBuffer() plen = len(reqpkt) + 4 reqpkt = struct.pack('!i', plen) + reqpkt ret = self.__trans(reqpkt, plen) if len(ret) == 0: raise Exception('server do not response') ios = JceInputStream(ret) rsp = ResponsePacket.readFrom(ios) if rsp.iRet != 0: raise Exception("Taf Error:%d" % rsp.iRet) return rsp # send def __trans(self, buf, blen): try: s = socket.socket() s.connect((self.ip, self.port)) s.send(buf) ret = s.recv(4) blen, = struct.unpack_from('!i', ret) blen -= 4 # ret = s.recv(blen) # Modified by jasonling bufSize = 1024 total = 0 ret = '' while total < blen: tmpStr = s.recv(bufSize) total += len(tmpStr) # print total ret += tmpStr # print str(len(ret)) + '_' + str(blen) if len(ret) != blen: raise Exception('receive response packet error') s.close() except socket.error, e: raise Exception(e) return ret