def SinglecastByServiceMask(self, serviceMask, method, *args, **kwargs): with bluepy.Timer('machoNet::SinglecastByServiceMask'): callTimer = base.CallTimer('SinglecastByServiceMask:: %s (Broadcast\\Client)' % method) try: self.SinglecastByServiceMaskWithoutTheStars(serviceMask, method, args, kwargs) finally: callTimer.Done()
def SinglecastByClientID(self, clientid, method, *args): with bluepy.Timer('machoNet::SinglecastByClientID'): callTimer = base.CallTimer('SinglecastByClientID::%s (Broadcast\\Client)' % method) try: self.NarrowcastByClientIDsWithoutTheStars([clientid], method, args) finally: callTimer.Done()
def NarrowcastByNodeIDs(self, nodeids, method, *args, **kwargs): with bluepy.Timer('machoNet::NarrowcastByNodeIDs'): callTimer = base.CallTimer('NarrowcastByClientIDs::%s (Broadcast\\Client)' % method) try: self.NarrowcastByNodeIDsWithoutTheStars(nodeids, method, args, kwargs) finally: callTimer.Done()
def Objectcast(self, object, method, *args): with bluepy.Timer('machoNet::Objectcast'): callTimer = base.CallTimer('Objectcast::%s (Broadcast\\Client)' % method) try: self.ObjectcastWithoutTheStars(object, method, args) finally: callTimer.Done()
def SinglecastByWorldSpaceID(self, instanceid, method, *args): with bluepy.Timer('machoNet::SinglecastByWorldSpaceID'): callTimer = base.CallTimer('SinglecastByWorldSpaceID::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='worldspaceid', narrowcast=[instanceid]), payload=(1, args))) finally: callTimer.Done()
def Scattercast(self, idtype, ids, method, *args): with bluepy.Timer('machoNet::Scattercast'): callTimer = base.CallTimer('Scattercast::%s::%s (Broadcast\\Client)' % (method, idtype)) try: return self.ScattercastWithoutTheStars(idtype, ids, method, args) finally: callTimer.Done()
def NotifyUp(self, packet): if packet.payload[0]: if getattr(packet.destination, 'service', None) is not None: if session.contextOnly and packet.command != const.cluster.MACHONETMSG_TYPE_SESSIONCHANGENOTIFICATION and packet.command != const.cluster.MACHONETMSG_TYPE_SESSIONINITIALSTATENOTIFICATION: packet.srcTransport.InstallSessionIfRequired( packet.destination.service, packet.payload[1]) packet.srcTransport = None method = getattr(packet.service, packet.payload[1]) callTimer = base.CallTimer( '%s::%s (ServiceNotify\\Server)' % (packet.destination.service, packet.payload[1])) try: if len(packet.payload) == 3: ClockThisWithoutTheStars( 'Remote Service Notify::%s::%s' % (packet.destination.service, packet.payload[1]), method, packet.payload[2]) else: ClockThisWithoutTheStars( 'Remote Service Notify::%s::%s' % (packet.destination.service, packet.payload[1]), method, packet.payload[2], packet.payload[3]) finally: callTimer.Done() return else: packet.payload = packet.payload[1] return self.ForwardNotifyUp(packet)
def ReliableSinglecastByCharID(self, charid, method, *args): with bluepy.Timer('machoNet::ReliableSinglecastByCharID'): callTimer = base.CallTimer( 'ReliableSinglecastByCharID::%s (Broadcast\\Client)' % method) try: clientIDs = sm.GetService('sessionMgr').GetClientIDsFromID( 'charid', charid, refresh=1) self.NarrowcastByClientIDsWithoutTheStars( clientIDs, method, args) except UnMachoDestination as e: self.machoNet.LogInfo( 'Character ', charid, " was not reachable, so he didn't get this singlecast. Should be fine and dandy. reason=", e.payload) sys.exc_clear() except UserError as e: if e.msg != 'UnMachoDestination': raise self.machoNet.LogInfo( 'Character ', charid, " was not reachable, so he didn't get this singlecast. Should be fine and dandy. reason=", e.msg) sys.exc_clear() finally: callTimer.Done()
def NarrowcastByClientIDs(self, clientids, method, *args): with bluepy.Timer('machoNet::NarrowcastByClientIDs'): callTimer = base.CallTimer('NarrowcastByClientIDs::%s (Broadcast\\Client)' % method) try: return self.NarrowcastByClientIDsWithoutTheStars(clientids, method, args) finally: callTimer.Done()
def ClientBroadcast(self, method, *args): with bluepy.Timer('machoNet::ClientBroadcast'): callTimer = base.CallTimer('ClientBroadcast::%s (Broadcast\\Client)' % method) try: packet = macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='clientID'), payload=(1, args)) self.ForwardNotifyDown(packet) finally: callTimer.Done()
def NarrowcastByShipIDs(self, shipids, method, *args): if not shipids: return callTimer = base.CallTimer('NarrowcastByShipIDs::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='shipid', narrowcast=shipids), payload=(1, args))) finally: callTimer.Done()
def NarrowcastBySolarSystemID2s(self, solarsystemid2s, method, *args): if not solarsystemid2s: return callTimer = base.CallTimer('NarrowcastBySolarSystemID2s::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='solarsystemid2', narrowcast=solarsystemid2s), payload=(1, args))) finally: callTimer.Done()
def NotifyUp(self, packet): if packet.payload[0] == 1: tup = self.FromPickle(packet.payload[1], packet.source) objectID, method, args = tup[0], tup[1], tup[2] if method == 'ClientHasReleasedTheseObjects': oidsandrefs = objectID for each in oidsandrefs: objectID, refID = each if objectID in session.machoObjectsByID: object = session.machoObjectsByID[objectID][1] objectType, guts = self.__GetObjectTypeAndGuts(object) session.UnregisterMachoObject(objectID, refID) return else: if objectID[0] == 'C' and macho.mode == 'client': cid, oid = objectID.split(':') objectID = '%s:%s' % (self.identifier, oid) if objectID not in session.machoObjectsByID: raise UnMachoDestination( 'The specified object (%s) is not a member of this session' % objectID) object = session.machoObjectsByID[objectID][1] if isinstance(object, base.ObjectConnection): objclass = object.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) callTimer = base.CallTimer('%s::%s (ObjectNotify\\Server)' % (objclass, method)) try: func = getattr(object, method) if method in object.__dict__.get( '__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError( 'This call can only be the result of a hack attack', method) if not isinstance(object, base.ObjectConnection) and len( tup) == 4 and 'machoVersion' in tup[3]: if len(tup[3]) == 1: tup = (tup[0], tup[1], tup[2]) else: del tup[3]['machoVersion'] if len(tup) == 3: ClockThisWithoutTheStars( 'Remote Object Notify::%s::%s' % (objclass, method), func, args) else: ClockThisWithoutTheStars( 'Remote Object Notify::%s::%s' % (objclass, method), func, args, tup[3]) finally: callTimer.Done() return else: packet.payload = self.FromPickle(packet.payload[1], packet.source) self.ForwardNotifyUp(packet)
def NarrowcastByCharIDs(self, charids, method, *args): if not charids: return with bluepy.Timer('machoNet::NarrowcastByCharIDs'): callTimer = base.CallTimer('NarrowcastByCharIDs::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='charid', narrowcast=charids), payload=(1, args))) finally: callTimer.Done()
def SinglecastByCorporationID(self, corpid, method, *args): callTimer = base.CallTimer( 'SinglecastByCorporationID::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown( macho.Notification(destination=macho.MachoAddress( broadcastID=method, idtype='corpid', narrowcast=[corpid]), payload=(1, args))) finally: callTimer.Done()
def NarrowcastToObservers(self, sourceEntityID, method, *args): with bluepy.Timer('machoNet::NarrowcastToObservers'): callTimer = base.CallTimer('NarrowcastToObservers::%s (Broadcast\\Client)' % method) try: if not self.apertureService: self.apertureService = sm.GetService('apertureServer') charids = self.apertureService.GetSubjectObservers(sourceEntityID) if charids: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='charid', narrowcast=charids), payload=(1, args))) finally: callTimer.Done()
def doCall(): method = attribute mask = self.session.Masquerade() try: callTimer = base.CallTimer('%s::%s (RemoteServiceCall)' % (self.service, method)) try: return call(self.session, self.nodeID, self.servicename, method, args, kwargs) finally: callTimer.Done() finally: mask.UnMask()
def __call__(self, *args, **keywords): mask = self.session.Masquerade() try: callTimer = base.CallTimer('%s::%s (UberMachoRemoteServiceCall)' % (self.service, self.method)) try: return self.gpcs.UberMachoRemoteServiceCall(self.nodeGroup, self.batchInterval, self.session, self.service, self.method, *args, **keywords) finally: callTimer.Done() finally: mask.UnMask() self.__dict__.clear()
def SinglecastBySolarSystemID2(self, solarsystemid2, method, *args): callTimer = base.CallTimer( 'SinglecastBySolarSystemID2::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown( macho.Notification(destination=macho.MachoAddress( broadcastID=method, idtype='solarsystemid2', narrowcast=[solarsystemid2]), payload=(1, args))) finally: callTimer.Done()
def ServerBroadcast(self, method, *args): with bluepy.Timer('machoNet::ServerBroadcast'): callTimer = base.CallTimer('ServerBroadcast::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='nodeID'), payload=(1, args))) if macho.mode == 'server': if method.startswith('Process'): sm.ChainEventWithoutTheStars(method, args) elif method.startswith('Do'): sm.SendEventWithoutTheStars(method, args) else: sm.ScatterEventWithoutTheStars(method, args) finally: callTimer.Done()
def ProxyBroadcast(self, method, *args): with bluepy.Timer('machoNet::ProxyBroadcast'): callTimer = base.CallTimer('ProxyBroadcast::%s (Broadcast\\Client)' % method) try: self.ForwardNotifyDown(macho.Notification(destination=macho.MachoAddress(broadcastID=method, idtype='+nodeID', narrowcast=self.machoNet.GetConnectedProxyNodes()), payload=(1, args))) if macho.mode == 'proxy': if method.startswith('Process'): sm.ChainEventWithoutTheStars(method, args) elif method.startswith('Do'): sm.SendEventWithoutTheStars(method, args) else: sm.ScatterEventWithoutTheStars(method, args) finally: callTimer.Done()
def CallUp(self, packet): if packet.payload[0]: if getattr(packet.destination, 'service', None) is not None: if packet.payload[1] in packet.service.__dict__.get('__restrictedcalls__', {}) or packet.payload[1].startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', packet.payload[1]) if packet.payload[1] == 'MachoBindObject': args = packet.payload[2][:-1] nodeID = packet.service.MachoResolveObject(args[0], 0) if nodeID and nodeID != self.machoNet.GetNodeID(): self.machoNet.LogError('MachoBindObject received on wrong node. Should have gone to ', nodeID, ', bindParams=', args[0], ', packet=', packet) raise WrongMachoNode(nodeID) call = packet.payload[2][-1] boundObject = packet.service.MachoGetObjectBoundToSession(packet.payload[2][0], session) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT: kwargs = packet.payload[3] if len(packet.payload) >= 4 else None self.machoNet.LogClientCall(session, packet.destination.service, packet.payload[1], packet.payload[2], kwargs) if call is not None: if isinstance(boundObject, base.ObjectConnection): objclass = boundObject.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) method, args, keywords = call if method in boundObject.__dict__.get('__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', method) callTimer = base.CallTimer('%s::%s (UnBoundObjectCall\\Server)' % (objclass, method)) try: func = getattr(boundObject, method) self.UpdateRecvServiceCallStats(objclass, method, packet.source) if not keywords: retval = ClockThisWithoutTheStars('Remote Unbound Object Call::%s::%s' % (objclass, method), func, args) else: retval = ClockThisWithoutTheStars('Remote Unbound Object Call::%s::%s' % (objclass, method), func, args, keywords) payload = (boundObject, retval) finally: callTimer.Done() else: payload = (boundObject, None) else: args = packet.payload[2] method = getattr(packet.service, packet.payload[1]) callTimer = base.CallTimer('%s::%s (ServiceCall\\Server)' % (packet.destination.service, packet.payload[1])) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT and packet.payload[1] != 'MachoBindObject': kwargs = packet.payload[3] if len(packet.payload) >= 4 else None self.machoNet.LogClientCall(session, packet.destination.service, packet.payload[1], args, kwargs) try: self.UpdateRecvServiceCallStats(packet.destination.service, method.__method__, packet.source) if len(packet.payload) == 3: payload = ClockThisWithoutTheStars('Remote Service Call::%s::%s' % (packet.destination.service, packet.payload[1]), method, args) else: payload = ClockThisWithoutTheStars('Remote Service Call::%s::%s' % (packet.destination.service, packet.payload[1]), method, args, packet.payload[3]) finally: callTimer.Done() if session.contextOnly: packet.srcTransport.InstallSessionIfRequired(packet.destination.service, packet.payload[1]) packet.srcTransport = None return packet.Response(payload=payload) else: packet.payload = packet.payload[1] return self.ForwardCallUp(packet)
def RemoteServiceNotifyWithoutTheStars(self, sess, nodeID, service, method, args, keywords): while 1: try: if sess is None: self.machoNet.LogError('Session is None during RemoteServiceNotify') log.LogTraceback() if nodeID is None and macho.mode == 'client': nodeID = self.services.get(service, None) if nodeID is None and service in self.machoNet.serviceInfo: where = self.machoNet.serviceInfo[service] for k, v in self.machoNet.serviceInfo.iteritems(): if k != service and v == where: nodeID = self.services.get(k, None) break if nodeID is None and self.machoNet.serviceInfo.get(service, None) is not None: self.machoNet.LogInfo("I haven't got a clue where ", service, ' should run, although I could guess any of these: ', str(self.services.keys())) if nodeID is None: if macho.mode == 'server': proxies = self.machoNet.GetConnectedProxyNodes() if not proxies: raise UnMachoDestination('No proxy available') destination = macho.MachoAddress(nodeID=random.choice(proxies), service=service) else: destination = macho.MachoAddress(service=service) elif isinstance(nodeID, macho.MachoAddress): destination = nodeID else: destination = macho.MachoAddress(nodeID=nodeID, service=service) if keywords: kw2 = copy.copy(keywords) else: kw2 = {} if currentcall: machoTimeout = kw2.get('machoTimeout', currentcall.packet.oob.get('machoTimeout', None)) else: machoTimeout = kw2.get('machoTimeout', None) if 'machoTimeout' in kw2: del kw2['machoTimeout'] if kw2: payload = (1, method, args, kw2) else: payload = (1, method, args) packet = macho.Notification(destination=destination, payload=payload) if machoTimeout is not None: packet.oob['machoTimeout'] = machoTimeout mask = sess.Masquerade() try: callTimer = base.CallTimer('%s::%s (ServiceNotify\\Client)' % (service, method)) try: self.ForwardNotifyDown(packet) finally: callTimer.Done() finally: mask.UnMask() except WrongMachoNode as e: sys.exc_clear() self.services[service] = e.payload if nodeID == e.payload: self.machoNet.LogError('Redirected to same node', nodeID) raise UnMachoDestination('Failed to redirect call, because we were being redirected to the same place we were trying to call in the first place (%s)' % nodeID) else: self.machoNet.LogInfo('Redirecting call to node ', e.payload, ' that was originally intended for node ', nodeID) nodeID = e.payload continue except UserError as e: if e.msg in ('UnMachoDestination', 'GPSTransportClosed'): self.services.clear() raise except StandardError: self.services.clear() raise return
def RemoteServiceCallWithoutTheStars(self, sess, nodeID, service, method, args, keywords): while 1: try: if sess is None: self.machoNet.LogError('Session is None during RemoteServiceCall') log.LogTraceback() sessionVars1 = self._GetRemoteServiceCallVariables(sess) mask = sess.Masquerade() try: cachable, versionCheck, throwOK, cachedResultRecord, cacheKey, cacheDetails = sm.GetService('objectCaching').PerformCachedMethodCall(None, service, method, args) if cachable: if not versionCheck: if throwOK: self.LogMethodCall(objectCaching.CacheOK(), service, method + '[Cached]', args, keywords) raise objectCaching.CacheOK() elif cachedResultRecord: self.LogMethodCall(cachedResultRecord['lret'], service, method + '[Cached]', args, keywords) return cachedResultRecord['lret'] if nodeID is None and macho.mode == 'client': nodeID = self.services.get(service, None) if nodeID is None and service in self.machoNet.serviceInfo: where = self.machoNet.serviceInfo[service] if where: for k, v in self.machoNet.serviceInfo.iteritems(): if k != service and v and (v.startswith(where) or where.startswith(v)): nodeID = self.services.get(k, None) break if nodeID is None and self.services and service not in ('DB2',): self.machoNet.LogInfo("I haven't got a clue where ", service, ' should run, although I could guess any of these: ', str(self.services.keys())) if nodeID is None: if macho.mode == 'server': proxies = self.machoNet.GetConnectedProxyNodes() if not proxies: raise UnMachoDestination('No proxy available') destination = macho.MachoAddress(nodeID=random.choice(proxies), service=service) else: destination = macho.MachoAddress(service=service) elif isinstance(nodeID, macho.MachoAddress): destination = nodeID else: destination = macho.MachoAddress(nodeID=nodeID, service=service) if keywords: kw2 = copy.copy(keywords) else: kw2 = {} if kw2.get('machoVersion', None) is None: if cachedResultRecord is not None and cachedResultRecord['version'] is not None: kw2['machoVersion'] = cachedResultRecord['version'] else: kw2['machoVersion'] = 1 if currentcall: machoTimeout = kw2.get('machoTimeout', currentcall.packet.oob.get('machoTimeout', None)) else: machoTimeout = kw2.get('machoTimeout', None) if 'machoTimeout' in kw2: del kw2['machoTimeout'] payload = (1, method, args, kw2) packet = macho.CallReq(destination=destination, payload=payload) if machoTimeout is not None: packet.oob['machoTimeout'] = machoTimeout callTimer = base.CallTimer('%s::%s (ServiceCall\\Client)' % (service, method)) try: ret = self.ForwardCallDown(packet).payload self.UpdateSendServiceCallStats(service, method) self.LogMethodCall(ret, service, method, args, keywords) except util.UpdateMoniker as e: raise except RuntimeError: raise except UserError: raise except ProxyRedirect: raise except WrongMachoNode: raise except objectCaching.CacheOK: if cachedResultRecord is None: raise sys.exc_clear() self.LogMethodCall(cachedResultRecord['lret'], service, method, args, keywords) sm.GetService('objectCaching').UpdateVersionCheckPeriod(cacheKey) return cachedResultRecord['lret'] finally: callTimer.Done() if isinstance(ret, objectCaching.CachedMethodCallResult): sm.GetService('objectCaching').CacheMethodCall(service, method, args, ret) ret = ret.GetResult() return ret finally: mask.UnMask() sessionVars2 = self._GetRemoteServiceCallVariables(sess) except WrongMachoNode as e: sys.exc_clear() self._HandleServiceCallWrongNode(e, service, sessionVars1, sessionVars2) self.services[service] = e.payload if nodeID == e.payload: self.machoNet.LogError('Redirected to same node', nodeID) raise UnMachoDestination('Failed to redirect call, because we were being redirected to the same place we were trying to call in the first place (%s)' % nodeID) else: self.machoNet.LogInfo('Redirecting call to node ', e.payload, ' that was originally intended for node ', nodeID) nodeID = e.payload except UserError as e: if e.msg in ('UnMachoDestination', 'GPSTransportClosed'): self.services.clear() raise except StandardError: if service in self.services: otherNodeID = self.services[service] for s, n in self.services.items()[:]: if n and n in (otherNodeID, nodeID): del self.services[s] raise
def CallUp(self, packet): if packet.command == const.cluster.MACHONETMSG_TYPE_AUTHENTICATION_REQ: retval = self.ForwardCallUp(packet) self.__StringifyPayloadForLogging(retval, retval.payload) retval.payload = self.ToPickle(retval.payload) if self.added_objects: retval.oob['OID+'] = self.added_objects retval.compressedPart = self.compressedPart return retval elif packet.payload[0]: tup = self.FromPickle(packet.payload[1], packet.source) objectID, method, args = tup[0], tup[1], tup[2] if objectID[0] == 'C' and macho.mode == 'client': cid, oid = objectID.split(':') objectID = '%s:%s' % (self.identifier, oid) if objectID not in session.machoObjectsByID: session.DumpSession('OBJECTNOTMEMBER', 'The specified object (%s) is not a member of this session' % objectID) raise UnMachoDestination('The specified object (%s) is not a member of this session' % objectID) object = session.machoObjectsByID[objectID][1] if isinstance(object, base.ObjectConnection): objclass = object.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) callTimer = base.CallTimer('%s::%s (ObjectCall\\Server)' % (objclass, method)) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT: kwargs = tup[3] if len(tup) >= 4 else None self.machoNet.LogClientCall(session, objclass, method, args, kwargs) try: func = getattr(object, method) if method in object.__dict__.get('__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', method) if not isinstance(object, base.ObjectConnection): if 0 == session.role & service.ROLE_SERVICE and hasattr(object, '__exportedcalls__') and method not in object.__exportedcalls__: raise RuntimeError('%s call is not exported from this pass-by-reference object.' % method) if not session.role & service.ROLE_SERVICE: paramList = object.__exportedcalls__.get(method, None) paramDict = None if paramList is not None: if type(paramList) is list: if len(paramList): tmp = {} tmp['role'] = paramList[0] tmp['preargs'] = paramList[1:] paramDict = tmp elif type(paramList) is dict: paramDict = paramList if paramDict is not None: role = paramDict.get('role', service.ROLE_SERVICE) if not role & session.role: session.LogSessionError("Called %s::%s, which requires role 0x%x, which the user doesn't have. User has role 0x%x" % (object.__class__.__name__, method, role, session.role)) raise RuntimeError('RoleNotAssigned', "%s::%s requires role 0x%x, which the user doesn't have. User has role 0x%x. Calling session: %s" % (object.__class__.__name__, method, role, session.role, str(session))) preargs = paramDict.get('preargs', []) args2 = len(preargs) * [None] + list(args) for i in range(len(preargs)): args2[i] = getattr(session, preargs[i]) args = tuple(args2) if len(tup) == 4 and 'machoVersion' in tup[3]: if len(tup[3]) == 1: tup = (tup[0], tup[1], tup[2]) else: del tup[3]['machoVersion'] if len(tup) == 3: retval = ClockThisWithoutTheStars('Remote Object Call::%s::%s' % (objclass, method), func, args) else: retval = ClockThisWithoutTheStars('Remote Object Call::%s::%s' % (objclass, method), func, args, tup[3]) retpickle = self.ToPickle(retval) retval = packet.Response(payload=retpickle) if self.added_objects: retval.oob['OID+'] = self.added_objects self.__StringifyPayloadForLogging(retval, retpickle) retval.compressedPart = self.compressedPart finally: callTimer.Done() return retval else: packet.payload = self.FromPickle(packet.payload[1], packet.source) retval = self.ForwardCallUp(packet) self.__StringifyPayloadForLogging(retval, retval.payload) retval.payload = self.ToPickle(retval.payload) if self.added_objects: retval.oob['OID+'] = self.added_objects retval.compressedPart = self.compressedPart return retval
def ObjectCallWithoutTheStars(self, oob, persistantObjectID, blocking, sess, destination, objectID, method, args, keywords): cachable, versionCheck, throwOK, cachedResultRecord, cacheKey, cacheDetails = sm.GetService('objectCaching').PerformCachedMethodCall(None, persistantObjectID, method, args) if cachable: if not versionCheck: if throwOK: sm.GetService('objectCaching').LogInfo('Local cache hit with throw for remote object ', persistantObjectID, '::', method, '(', args, ')') raise objectCaching.CacheOK() elif cachedResultRecord: sm.GetService('objectCaching').LogInfo('Local cache hit for remote object ', persistantObjectID, '::', method, '(', args, ')') return cachedResultRecord['lret'] if keywords: kw2 = copy.copy(keywords) else: kw2 = {} if kw2.get('machoVersion', None) is None: if cachedResultRecord is not None and cachedResultRecord['version'] is not None: kw2['machoVersion'] = cachedResultRecord['version'] else: kw2['machoVersion'] = 1 if currentcall: machoTimeout = kw2.get('machoTimeout', currentcall.packet.oob.get('machoTimeout', None)) else: machoTimeout = kw2.get('machoTimeout', None) if 'machoTimeout' in kw2: del kw2['machoTimeout'] payload = (1, self.ToPickle((objectID, method, args, kw2))) if blocking == 1: packet = macho.CallReq(destination=destination, payload=payload) if oob: packet.oob = oob if machoTimeout is not None: packet.oob['machoTimeout'] = machoTimeout if self.added_objects: if 'OID+' in packet.oob: packet.oob['OID+'].update(self.added_objects) else: packet.oob['OID+'] = self.added_objects try: callTimer = base.CallTimer('Remote Object Call::%s (ObjectCall\\Client)' % (method,)) try: retval = self.ForwardCallDown(packet) finally: callTimer.Done() retval = self.FromPickle(retval.payload, packet.destination) except objectCaching.CacheOK: if cachedResultRecord is None: raise sys.exc_clear() sm.GetService('objectCaching').LogInfo('Version matches for remote object ', persistantObjectID, '::', method, '(', args, ')') sm.GetService('objectCaching').UpdateVersionCheckPeriod(cacheKey) return cachedResultRecord['lret'] if isinstance(retval, objectCaching.CachedMethodCallResult): sm.GetService('objectCaching').CacheMethodCall(persistantObjectID, method, args, retval) retval = retval.GetResult() return retval else: packet = macho.Notification(destination=destination, payload=payload) if oob: packet.oob = oob if machoTimeout is not None: packet.oob['machoTimeout'] = machoTimeout if self.added_objects: if 'OID+' in packet.oob: packet.oob['OID+'].update(self.added_objects) else: packet.oob['OID+'] = self.added_objects self.ForwardNotifyDown(packet) return MachoBoobyTrap()
def GetCachableObject(self, shared, objectID, objectVersion, nodeID): """ Returns a cached copy of object 'objectID' or returns None if 'objectID' is not found in cache. If the cached version is older than 'objectVersion': acquire it from node nodeID (through our proxy, of course, if we're a client). 'shared' is true iff object has been cached in "shared" mode (meaning: a copy is cached on servers and proxies). Returns a utilCachedObject or objectCaching.CachedObject. """ callTimer = base.CallTimer('objectCaching::GetCachableObject') try: if macho.mode == 'client': gpcs = sm.services['machoNet'] else: gpcs = sm.services['machoNet'] gpcs.GetGPCS() if objectID in self.cachedObjects and isinstance( self.cachedObjects[objectID], utilCachedObject) and macho.mode == 'proxy': if sm.services['machoNet'].GetTransportOfNode( self.cachedObjects[objectID].__nodeID__) is None: del self.cachedObjects[objectID] if objectID in self.cachedObjects and isinstance( self.cachedObjects[objectID], uthread.Semaphore ) or objectID not in self.cachedObjects or not isinstance( self.cachedObjects[objectID], uthread.Semaphore) and self.__OlderVersion( self.cachedObjects[objectID].version, objectVersion): if objectID not in self.cachedObjects or not isinstance( self.cachedObjects[objectID], uthread.Semaphore) and self.__OlderVersion( self.cachedObjects[objectID].version, objectVersion): self.cachedObjects[objectID] = uthread.Semaphore( ('objectCaching', objectID)) while 1: semaphore = self.cachedObjects[objectID] semaphore.acquire() try: if not isinstance(self.cachedObjects[objectID], uthread.Semaphore): self.__UpdateStatisticsGetCachableObject( objectID, objectVersion, self.cachedObjects[objectID]) return self.cachedObjects[objectID] if macho.mode == 'client': if shared: if not sm.services['machoNet'].myProxyNodeID: proxyNodeID = nodeID else: proxyNodeID = sm.services[ 'machoNet'].myProxyNodeID remoteObject = gpcs.RemoteServiceCall( session, proxyNodeID, 'objectCaching', 'GetCachableObject', shared, objectID, objectVersion, nodeID) else: remoteObject = gpcs.RemoteServiceCall( session, nodeID, 'objectCaching', 'GetCachableObject', shared, objectID, objectVersion, nodeID) self.cachedObjects[objectID] = remoteObject self.__CacheIsDirty('cachedObjects', objectID) elif macho.mode == 'proxy': remoteObject = gpcs.RemoteServiceCall( self.session, nodeID, 'objectCaching', 'GetCachableObject', shared, objectID, objectVersion, nodeID) if not remoteObject.compressed and len( remoteObject.pickle) > 200: try: t = ClockThis('objectCaching::compress', zlib.compress, remoteObject.pickle, 1) except zlib.error as e: raise RuntimeError( 'Compression Failure: ' + strx(e)) if len(t) < len(remoteObject.pickle): remoteObject.compressed = 1 remoteObject.pickle = t if remoteObject.shared: self.cachedObjects[objectID] = remoteObject self.__CacheIsDirty('cachedObjects', objectID) else: del self.cachedObjects[objectID] return remoteObject elif macho.mode == 'server': self.LogError( "Some dude asked me for a cached object I just don't have, objectID=", objectID, ', objectVersion=', objectVersion, ', nodeID=', nodeID) del self.cachedObjects[objectID] raise RuntimeError( "I don't have %s, which just don't make sense...." % repr(objectID)) finally: semaphore.release() if not isinstance(self.cachedObjects[objectID], uthread.Semaphore): self.__UpdateStatisticsGetCachableObject( objectID, objectVersion, self.cachedObjects[objectID]) return self.cachedObjects[objectID] else: if macho.mode == 'server' and not self.cachedObjects[ objectID].shared: tmp = self.cachedObjects[objectID] self.__UpdateStatisticsGetCachableObject( objectID, objectVersion, self.cachedObjects[objectID]) del self.cachedObjects[objectID] return tmp self.__UpdateStatisticsGetCachableObject( objectID, objectVersion, self.cachedObjects[objectID]) return self.cachedObjects[objectID] finally: callTimer.Done()