def testNonLocalAddressRevocationAssociation(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) lclAddr, mainAddr = self._makeLocalAndAssociated(myAddress, am) am.deadAddress(mainAddr) assert mainAddr == am.sendToAddress(lclAddr) assert mainAddr == am.sendToAddress(mainAddr) assert am.isDeadAddress(lclAddr) assert am.isDeadAddress(mainAddr) assert am.isDeadAddress(am.sendToAddress(mainAddr)) assert am.isDeadAddress(am.sendToAddress(lclAddr))
class TestLocalAddresses(unittest.TestCase): scope='unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def testGetValidLocalAddress(self): addr = ActorAddress(ActorLocalAddress(self.myAddress, 12, self.am)) self.assertIsInstance(addr.addressDetails, ActorLocalAddress) def testGetUniqueLocalAddresses(self): addr1 = self.am.createLocalAddress() addr2 = self.am.createLocalAddress() self.assertNotEqual(addr1, addr2) self.assertNotEqual(addr2, addr1) self.assertEqual(addr1, addr1) self.assertEqual(addr2, addr2) def testLocalAddressCannotBePickled(self): self.am = ActorAddressManager(None, 'me') addr = self.am.createLocalAddress() self.assertRaises(CannotPickleAddress, pickle.dumps, addr) def testLocalAddressCanBeReconstituted(self): addr = self.am.createLocalAddress() addr2 = self.am.getLocalAddress(addr.addressDetails.addressInstanceNum) self.assertEqual(addr, addr2) def testLocalAddressCannotBeUsedForSending(self): addr = self.am.createLocalAddress() self.assertIsNone(self.am.sendToAddress(addr))
def testMainAddressRevocation(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) addr = ActorAddress(id(self)) am.deadAddress(addr) assert addr == am.sendToAddress(addr) assert am.isDeadAddress(addr)
class TestLocalAddresses(unittest.TestCase): scope = 'unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def testGetValidLocalAddress(self): addr = ActorAddress(ActorLocalAddress(self.myAddress, 12, self.am)) self.assertIsInstance(addr.addressDetails, ActorLocalAddress) def testGetUniqueLocalAddresses(self): addr1 = self.am.createLocalAddress() addr2 = self.am.createLocalAddress() self.assertNotEqual(addr1, addr2) self.assertNotEqual(addr2, addr1) self.assertEqual(addr1, addr1) self.assertEqual(addr2, addr2) def testLocalAddressCannotBePickled(self): self.am = ActorAddressManager(None, 'me') addr = self.am.createLocalAddress() self.assertRaises(CannotPickleAddress, pickle.dumps, addr) def testLocalAddressCanBeReconstituted(self): addr = self.am.createLocalAddress() addr2 = self.am.getLocalAddress(addr.addressDetails.addressInstanceNum) self.assertEqual(addr, addr2) def testLocalAddressCannotBeUsedForSending(self): addr = self.am.createLocalAddress() self.assertIsNone(self.am.sendToAddress(addr))
def testLocalAddressRevocation(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) lcladdr = am.createLocalAddress() am.deadAddress(lcladdr) assert am.sendToAddress(lcladdr) is None assert am.isDeadAddress(lcladdr) assert lcladdr == am.getLocalAddress( lcladdr.addressDetails.addressInstanceNum)
def testAssociationRemembered(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) lclAddr, mainAddr = self._makeLocalAndAssociated(myAddress, am) assert mainAddr == am.sendToAddress(lclAddr) assert mainAddr == am.sendToAddress(mainAddr)
def testLocalAddressCannotBeUsedForSending(self): am = ActorAddressManager(None, "here") addr = am.createLocalAddress() assert am.sendToAddress(addr) is None
class systemCommonBase(object): def __init__(self, adminAddr, transport): self._adminAddr = adminAddr self.transport = transport self._addrManager = ActorAddressManager(adminAddr, self.transport.myAddress) self.transport.setAddressManager(self._addrManager) self._finalTransmitPending = { } # key = target ActorAddress, value=None or the last pending Intent self._awaitingAddressUpdate = { } # key = actorAddress waited on (usually local), value=array of transmit Intents self._receiveQueue = [] # array of ReceiveMessage to be processed self._children = [ ] # array of Addresses of children of this Actor/Admin self._governer = RateThrottle(RATE_THROTTLE) self._sCBStats = StatsManager() @property def address(self): return self.transport.myAddress @property def myAddress(self): return self.transport.myAddress @property def childAddresses(self): return self._children def _registerChild(self, childAddress): self._children.append(childAddress) def _handleChildExited(self, childAddress): self._sCBStats.inc('Common.Message Received.Child Actor Exited') self._addrManager.deadAddress(childAddress) self.transport.deadAddress(self._addrManager, childAddress) self._childExited(childAddress) self._children = [C for C in self._children if C != childAddress] if hasattr(self, '_exiting') and not self._children: # OK, all children are dead, can now exit this actor, but # make sure this final cleanup only occurs once # (e.g. transport.deadAddress above could recurse through # here as well. if not hasattr(self, '_exitedAlready'): self._exitedAlready = True self._sayGoodbye() self.transport.abort_run(drain=True) return True def _updateStatusResponse(self, resp): "Called to update a Thespian_SystemStatus or Thespian_ActorStatus with common information" for each in self.childAddresses: resp.addChild(each) for each in self._receiveQueue: resp.addReceivedMessage(each.sender, self.myAddress, each.message) self._sCBStats.copyToStatusResponse(resp) # Need to show _finalTransmitPending? where is head of chain? shown by transport? (no) resp.governer = str(self._governer) for addr in self._awaitingAddressUpdate: resp.addTXPendingAddressCount( addr, len(self._awaitingAddressUpdate[addr])) self.transport._updateStatusResponse(resp) def setLoggingControls(self, envelope): from thespian.system.utilis import thesplog_control msg = envelope.message thesplog_control(msg.threshold, msg.useLogging, msg.useFile) return True # ---------------------------------------------------------------------- # Transmit management def _send_intent(self, intent): self._governer.eventRatePause() # Check if there are any existing transmits in progress to # this address (on either the input address or the validated # address); if so, just add the new one to the list and # return. sendAddr = self._addrManager.sendToAddress(intent.targetAddr) finalIntent = self._finalTransmitPending.get( intent.targetAddr, self._finalTransmitPending.get(sendAddr, None)) self._finalTransmitPending[sendAddr or intent.targetAddr] = intent if finalIntent: finalIntent.nextIntent = intent self._sCBStats.inc('Actor.Message Send.Added to End of Sends') return self._send_intent_to_transport(intent) def _retryPendingChildOperations(self, childInstance, actualAddress): # actualAddress will be none if the child could not be created lcladdr = self._addrManager.getLocalAddress(childInstance) if not actualAddress: self._receiveQueue.append( ReceiveEnvelope(lcladdr, ChildActorExited(lcladdr))) if lcladdr in self._finalTransmitPending: # KWQ: what to do when actualAddress is None? self._finalTransmitPending[ actualAddress] = self._finalTransmitPending[lcladdr] del self._finalTransmitPending[lcladdr] if lcladdr in self._awaitingAddressUpdate: pending = self._awaitingAddressUpdate[lcladdr] del self._awaitingAddressUpdate[lcladdr] for each in pending: if actualAddress: # KWQ: confirm the following two lines can be removed; send_intent_to_transport should do this translation on its own. At that point, the changeTargetAddr method should be able to be removed. # if each.targetAddr == lcladdr: # each.changeTargetAddr(actualAddress) self._sCBStats.inc( 'Actor.Message Send.Transmit ReInitiated') self._send_intent(each) else: if not isinstance(each.message, PoisonMessage): self._receiveQueue.append( ReceiveEnvelope(self.myAddress, PoisonMessage(each.message))) self._sCBStats.inc( 'Actor.Message Send.Poison Return on Child Abort') each.result = SendStatus.Failed each.completionCallback() def _send_intent_to_transport(self, intent): thesplog('Attempting intent %s', intent.identify(), level=logging.DEBUG) if not hasattr(intent, '_addedCheckNextTransmitCB'): intent.addCallback(self._checkNextTransmit, self._checkNextTransmit) # Protection against duplicate callback additions in case # of a retry due to the CannotPickleAddress exception below. intent._addedCheckNextTransmitCB = True try: self.transport.scheduleTransmit(self._addrManager, intent) self._sCBStats.inc('Actor.Message Send.Transmit Started') except CannotPickleAddress as ex: thesplog('CannotPickleAddress, appending intent for %s (hash=%s)', ex.address, hash(ex.address), level=logging.DEBUG) self._awaitingAddressUpdate.setdefault(ex.address, []).append(intent) self._sCBStats.inc('Actor.Message Send.Postponed for Address') self._checkNextTransmit(0, intent) except Exception: import traceback thesplog('Declaring transmit of %s as Poison: %s', intent.identify(), traceback.format_exc(), exc_info=True, level=logging.ERROR) if not isinstance(intent.message, PoisonMessage): self._receiveQueue.append( ReceiveEnvelope(intent.targetAddr, PoisonMessage(intent.message))) self._sCBStats.inc('Actor.Message Send.Transmit Poison Rejection') intent.result = SendStatus.Failed intent.completionCallback() def _checkNextTransmit(self, result, completedIntent): # This is the callback for (all) TransmitIntents that will # send the next queued intent for that destination. if completedIntent.nextIntent: self._send_intent_to_transport(completedIntent.nextIntent) else: fkey = completedIntent.targetAddr if fkey not in self._finalTransmitPending: fkey = self._addrManager.sendToAddress( completedIntent.targetAddr) if fkey not in self._finalTransmitPending: if isinstance(completedIntent.message, DeadEnvelope): fkey = completedIntent.message.deadAddress if fkey not in self._finalTransmitPending: fkey = self._addrManager.sendToAddress(fkey) if fkey in self._finalTransmitPending: if self._finalTransmitPending[fkey] != completedIntent: thesplog( 'Completed final intent %s does not match recorded final intent: %s', completedIntent.identify(), self._finalTransmitPending[fkey].identify(), level=logging.WARNING) del self._finalTransmitPending[fkey] else: thesplog( 'Completed Transmit Intent %s for unrecorded destination %s / %s in %s', completedIntent.identify(), str( self._addrManager.sendToAddress( completedIntent.targetAddr)), fkey, str(map(str, self._finalTransmitPending.keys())), level=logging.WARNING) self._sCBStats.inc('Action.Message Send.Unknown Completion') return
class TestAddressManagerAddressRevocation(unittest.TestCase): scope = 'unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def _makeLocalAndAssociated(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(lclAddr)) self.am.associateUseableAddress( self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) return lclAddr, mainAddr def testLocalAddressRevocation(self): lcladdr = self.am.createLocalAddress() self.am.deadAddress(lcladdr) self.assertIsNone(self.am.sendToAddress(lcladdr)) self.assertTrue(self.am.isDeadAddress(lcladdr)) self.assertEqual( lcladdr, self.am.getLocalAddress(lcladdr.addressDetails.addressInstanceNum)) def testMainAddressRevocation(self): addr = ActorAddress(id(self)) self.am.deadAddress(addr) self.assertEqual(addr, self.am.sendToAddress(addr)) self.assertTrue(self.am.isDeadAddress(addr)) def testLocalAddressRevocationAssociation(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.am.deadAddress(lclAddr) self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(lclAddr)) self.assertTrue(self.am.isDeadAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr))) def testNonLocalAddressRevocationAssociation(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.am.deadAddress(mainAddr) self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(lclAddr)) self.assertTrue(self.am.isDeadAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr))) def testAssociatedAddressRevocationIsUnique(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() lclAddr2, mainAddr2 = self._makeLocalAndAssociated() lclAddr3, mainAddr3 = self._makeLocalAndAssociated() self.assertFalse(self.am.isDeadAddress(lclAddr1)) self.assertFalse(self.am.isDeadAddress(mainAddr1)) self.assertFalse( self.am.isDeadAddress(self.am.sendToAddress(mainAddr1))) self.assertFalse(self.am.isDeadAddress( self.am.sendToAddress(lclAddr1))) self.assertFalse(self.am.isDeadAddress(lclAddr2)) self.assertFalse(self.am.isDeadAddress(mainAddr2)) self.assertFalse( self.am.isDeadAddress(self.am.sendToAddress(mainAddr2))) self.assertFalse(self.am.isDeadAddress( self.am.sendToAddress(lclAddr2))) self.assertFalse(self.am.isDeadAddress(lclAddr3)) self.assertFalse(self.am.isDeadAddress(mainAddr3)) self.assertFalse( self.am.isDeadAddress(self.am.sendToAddress(mainAddr3))) self.assertFalse(self.am.isDeadAddress( self.am.sendToAddress(lclAddr3))) self.am.deadAddress(lclAddr1) self.am.deadAddress(mainAddr2) self.assertTrue(self.am.isDeadAddress(lclAddr1)) self.assertTrue(self.am.isDeadAddress(mainAddr1)) self.assertTrue(self.am.isDeadAddress( self.am.sendToAddress(mainAddr1))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr1))) self.assertTrue(self.am.isDeadAddress(lclAddr2)) self.assertTrue(self.am.isDeadAddress(mainAddr2)) self.assertTrue(self.am.isDeadAddress( self.am.sendToAddress(mainAddr2))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr2))) self.assertFalse(self.am.isDeadAddress(lclAddr3)) self.assertFalse(self.am.isDeadAddress(mainAddr3)) self.assertFalse( self.am.isDeadAddress(self.am.sendToAddress(mainAddr3))) self.assertFalse(self.am.isDeadAddress( self.am.sendToAddress(lclAddr3)))
class TestAddressManagerAddressRevocation(unittest.TestCase): scope='unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def _makeLocalAndAssociated(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(lclAddr)) self.am.associateUseableAddress(self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) return lclAddr, mainAddr def testLocalAddressRevocation(self): lcladdr = self.am.createLocalAddress() self.am.deadAddress(lcladdr) self.assertIsNone(self.am.sendToAddress(lcladdr)) self.assertTrue(self.am.isDeadAddress(lcladdr)) self.assertEqual(lcladdr, self.am.getLocalAddress(lcladdr.addressDetails.addressInstanceNum)) def testMainAddressRevocation(self): addr = ActorAddress(id(self)) self.am.deadAddress(addr) self.assertEqual(addr, self.am.sendToAddress(addr)) self.assertTrue(self.am.isDeadAddress(addr)) def testLocalAddressRevocationAssociation(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.am.deadAddress(lclAddr) self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(lclAddr)) self.assertTrue(self.am.isDeadAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr))) def testNonLocalAddressRevocationAssociation(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.am.deadAddress(mainAddr) self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(lclAddr)) self.assertTrue(self.am.isDeadAddress(mainAddr)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr))) def testAssociatedAddressRevocationIsUnique(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() lclAddr2, mainAddr2 = self._makeLocalAndAssociated() lclAddr3, mainAddr3 = self._makeLocalAndAssociated() self.assertFalse(self.am.isDeadAddress(lclAddr1)) self.assertFalse(self.am.isDeadAddress(mainAddr1)) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(mainAddr1))) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(lclAddr1))) self.assertFalse(self.am.isDeadAddress(lclAddr2)) self.assertFalse(self.am.isDeadAddress(mainAddr2)) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(mainAddr2))) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(lclAddr2))) self.assertFalse(self.am.isDeadAddress(lclAddr3)) self.assertFalse(self.am.isDeadAddress(mainAddr3)) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(mainAddr3))) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(lclAddr3))) self.am.deadAddress(lclAddr1) self.am.deadAddress(mainAddr2) self.assertTrue(self.am.isDeadAddress(lclAddr1)) self.assertTrue(self.am.isDeadAddress(mainAddr1)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr1))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr1))) self.assertTrue(self.am.isDeadAddress(lclAddr2)) self.assertTrue(self.am.isDeadAddress(mainAddr2)) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(mainAddr2))) self.assertTrue(self.am.isDeadAddress(self.am.sendToAddress(lclAddr2))) self.assertFalse(self.am.isDeadAddress(lclAddr3)) self.assertFalse(self.am.isDeadAddress(mainAddr3)) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(mainAddr3))) self.assertFalse(self.am.isDeadAddress(self.am.sendToAddress(lclAddr3)))
def testAssociationUnique(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) self.testAssociationRemembered() lclAddr2 = am.createLocalAddress() assert am.sendToAddress(lclAddr2) is None
def testAssociationNotRequiredForUseableNonLocal(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) addr = ActorAddress(id(self)) assert addr == am.sendToAddress(addr)
def testAssociatedAddressRevocationIsUnique(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) lclAddr1, mainAddr1 = self._makeLocalAndAssociated(myAddress, am) print('1',str(lclAddr1),str(mainAddr1)) lclAddr2, mainAddr2 = self._makeLocalAndAssociated(myAddress, am) print('2',str(lclAddr2),str(mainAddr2)) lclAddr3, mainAddr3 = self._makeLocalAndAssociated(myAddress, am) print('3',str(lclAddr3),str(mainAddr3)) assert not am.isDeadAddress(lclAddr1) assert not am.isDeadAddress(mainAddr1) print('1sm',str(am.sendToAddress(mainAddr1))) assert not am.isDeadAddress(am.sendToAddress(mainAddr1)) print('1sl',str(am.sendToAddress(lclAddr1))) assert not am.isDeadAddress(am.sendToAddress(lclAddr1)) assert not am.isDeadAddress(lclAddr2) assert not am.isDeadAddress(mainAddr2) assert not am.isDeadAddress(am.sendToAddress(mainAddr2)) assert not am.isDeadAddress(am.sendToAddress(lclAddr2)) assert not am.isDeadAddress(lclAddr3) assert not am.isDeadAddress(mainAddr3) assert not am.isDeadAddress(am.sendToAddress(mainAddr3)) assert not am.isDeadAddress(am.sendToAddress(lclAddr3)) am.deadAddress(lclAddr1) am.deadAddress(mainAddr2) assert am.isDeadAddress(lclAddr1) assert am.isDeadAddress(mainAddr1) assert am.isDeadAddress(am.sendToAddress(mainAddr1)) assert am.isDeadAddress(am.sendToAddress(lclAddr1)) assert am.isDeadAddress(lclAddr2) assert am.isDeadAddress(mainAddr2) assert am.isDeadAddress(am.sendToAddress(mainAddr2)) assert am.isDeadAddress(am.sendToAddress(lclAddr2)) assert not am.isDeadAddress(lclAddr3) assert not am.isDeadAddress(mainAddr3) assert not am.isDeadAddress(am.sendToAddress(mainAddr3)) assert not am.isDeadAddress(am.sendToAddress(lclAddr3))
class systemCommonBase(object): def __init__(self, adminAddr, transport): self._adminAddr = adminAddr self.transport = transport self._addrManager = ActorAddressManager(adminAddr, self.transport.myAddress) self.transport.setAddressManager(self._addrManager) self._finalTransmitPending = {} # key = target ActorAddress, value=None or the last pending Intent self._awaitingAddressUpdate = {} # key = actorAddress waited on (usually local), value=array of transmit Intents self._receiveQueue = [] # array of ReceiveMessage to be processed self._children = [] # array of Addresses of children of this Actor/Admin self._governer = RateThrottle(RATE_THROTTLE) self._sCBStats = StatsManager() @property def address(self): return self.transport.myAddress @property def myAddress(self): return self.transport.myAddress @property def childAddresses(self): return self._children def _registerChild(self, childAddress): self._children.append(childAddress) def _handleChildExited(self, childAddress): self._sCBStats.inc('Common.Message Received.Child Actor Exited') self._addrManager.deadAddress(childAddress) self.transport.deadAddress(self._addrManager, childAddress) self._childExited(childAddress) self._children = [C for C in self._children if C != childAddress] if hasattr(self, '_exiting') and not self._children: # OK, all children are dead, can now exit this actor, but # make sure this final cleanup only occurs once # (e.g. transport.deadAddress above could recurse through # here as well. if not hasattr(self, '_exitedAlready'): self._exitedAlready = True self._sayGoodbye() self.transport.abort_run(drain=True) return True def _updateStatusResponse(self, resp): "Called to update a Thespian_SystemStatus or Thespian_ActorStatus with common information" for each in self.childAddresses: resp.addChild(each) for each in self._receiveQueue: resp.addReceivedMessage(each.sender, self.myAddress, each.message) self._sCBStats.copyToStatusResponse(resp) # Need to show _finalTransmitPending? where is head of chain? shown by transport? (no) resp.governer = str(self._governer) for addr in self._awaitingAddressUpdate: resp.addTXPendingAddressCount(addr, len(self._awaitingAddressUpdate[addr])) self.transport._updateStatusResponse(resp) def setLoggingControls(self, envelope): from thespian.system.utilis import thesplog_control msg = envelope.message thesplog_control(msg.threshold, msg.useLogging, msg.useFile) return True # ---------------------------------------------------------------------- # Transmit management def _send_intent(self, intent): self._governer.eventRatePause() # Check if there are any existing transmits in progress to # this address (on either the input address or the validated # address); if so, just add the new one to the list and # return. sendAddr = self._addrManager.sendToAddress(intent.targetAddr) finalIntent = self._finalTransmitPending.get( intent.targetAddr, self._finalTransmitPending.get(sendAddr, None)) self._finalTransmitPending[sendAddr or intent.targetAddr] = intent if finalIntent: finalIntent.nextIntent = intent self._sCBStats.inc('Actor.Message Send.Added to End of Sends') return self._send_intent_to_transport(intent) def _retryPendingChildOperations(self, childInstance, actualAddress): # actualAddress will be none if the child could not be created lcladdr = self._addrManager.getLocalAddress(childInstance) if not actualAddress: self._receiveQueue.append(ReceiveEnvelope(lcladdr, ChildActorExited(lcladdr))) if lcladdr in self._finalTransmitPending: # KWQ: what to do when actualAddress is None? self._finalTransmitPending[actualAddress] = self._finalTransmitPending[lcladdr] del self._finalTransmitPending[lcladdr] if lcladdr in self._awaitingAddressUpdate: pending = self._awaitingAddressUpdate[lcladdr] del self._awaitingAddressUpdate[lcladdr] for each in pending: if actualAddress: # KWQ: confirm the following two lines can be removed; send_intent_to_transport should do this translation on its own. At that point, the changeTargetAddr method should be able to be removed. # if each.targetAddr == lcladdr: # each.changeTargetAddr(actualAddress) self._sCBStats.inc('Actor.Message Send.Transmit ReInitiated') self._send_intent(each) else: if not isinstance(each.message, PoisonMessage): self._receiveQueue.append( ReceiveEnvelope(self.myAddress, PoisonMessage(each.message))) self._sCBStats.inc('Actor.Message Send.Poison Return on Child Abort') each.result = SendStatus.Failed each.completionCallback() def _send_intent_to_transport(self, intent): thesplog('Attempting intent %s', intent.identify(), level=logging.DEBUG) if not hasattr(intent, '_addedCheckNextTransmitCB'): intent.addCallback(self._checkNextTransmit, self._checkNextTransmit) # Protection against duplicate callback additions in case # of a retry due to the CannotPickleAddress exception below. intent._addedCheckNextTransmitCB = True try: self.transport.scheduleTransmit(self._addrManager, intent) self._sCBStats.inc('Actor.Message Send.Transmit Started') except CannotPickleAddress as ex: thesplog('CannotPickleAddress, appending intent for %s (hash=%s)', ex.address, hash(ex.address), level=logging.DEBUG) self._awaitingAddressUpdate.setdefault(ex.address, []).append(intent) self._sCBStats.inc('Actor.Message Send.Postponed for Address') self._checkNextTransmit(0, intent) except Exception: import traceback thesplog('Declaring transmit of %s as Poison: %s', intent.identify(), traceback.format_exc(), exc_info=True, level=logging.ERROR) if not isinstance(intent.message, PoisonMessage): self._receiveQueue.append(ReceiveEnvelope(intent.targetAddr, PoisonMessage(intent.message))) self._sCBStats.inc('Actor.Message Send.Transmit Poison Rejection') intent.result = SendStatus.Failed intent.completionCallback() def _checkNextTransmit(self, result, completedIntent): # This is the callback for (all) TransmitIntents that will # send the next queued intent for that destination. if completedIntent.nextIntent: self._send_intent_to_transport(completedIntent.nextIntent) else: fkey = completedIntent.targetAddr if fkey not in self._finalTransmitPending: fkey = self._addrManager.sendToAddress(completedIntent.targetAddr) if fkey not in self._finalTransmitPending: if isinstance(completedIntent.message, DeadEnvelope): fkey = completedIntent.message.deadAddress if fkey not in self._finalTransmitPending: fkey = self._addrManager.sendToAddress(fkey) if fkey in self._finalTransmitPending: if self._finalTransmitPending[fkey] != completedIntent: thesplog('Completed final intent %s does not match recorded final intent: %s', completedIntent.identify(), self._finalTransmitPending[fkey].identify(), level=logging.WARNING) del self._finalTransmitPending[fkey] else: thesplog('Completed Transmit Intent %s for unrecorded destination %s / %s in %s', completedIntent.identify(), str(self._addrManager.sendToAddress(completedIntent.targetAddr)), fkey, str(map(str,self._finalTransmitPending.keys())), level=logging.WARNING) self._sCBStats.inc('Action.Message Send.Unknown Completion') return
class TestAddressManagerLocalAddressAssociations(unittest.TestCase): scope = 'unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def testMakeAssociation(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(self)) self.am.associateUseableAddress( self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) # No exception thrown self.assertTrue(True) def _makeLocalAndAssociated(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(lclAddr)) self.am.associateUseableAddress( self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) return lclAddr, mainAddr def testAssociationRemembered(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) def testAssociationUnique(self): self.testAssociationRemembered() lclAddr2 = self.am.createLocalAddress() self.assertIsNone(self.am.sendToAddress(lclAddr2)) def testAssociationNotRequiredForUseableNonLocal(self): addr = ActorAddress(id(self)) self.assertEqual(addr, self.am.sendToAddress(addr)) def testAssociationEquality(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(self)) self.assertNotEqual(lclAddr, mainAddr) self.assertNotEqual(mainAddr, lclAddr) self.am.associateUseableAddress( self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) self.assertEqual(lclAddr, mainAddr) self.assertEqual(mainAddr, lclAddr) def testAssociationEqualityWithReconstitutedNonLocalAddress(self): lclAddr = self.am.createLocalAddress() mainAddr1 = ActorAddress(None) mainAddr2 = ActorAddress(9) self.assertNotEqual(mainAddr1, mainAddr2) self.am.associateUseableAddress( self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr1) self.assertEqual(lclAddr, mainAddr1) self.assertEqual(mainAddr1, lclAddr) self.assertNotEqual(lclAddr, mainAddr2) self.assertNotEqual(mainAddr2, lclAddr) mainAddr1_dup = ActorAddress(None) self.assertEqual(mainAddr1, mainAddr1_dup) self.assertNotEqual(mainAddr1_dup, lclAddr) self.assertEqual(lclAddr, mainAddr1_dup) self.am.importAddr(mainAddr1_dup) self.assertEqual(mainAddr1_dup, lclAddr) self.assertEqual(lclAddr, mainAddr1_dup) self.assertEqual(mainAddr1_dup, mainAddr1) def testAssociatedAddressesDoNotMatchArbitraryStuff(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() self.assertNotEqual(None, lclAddr1) self.assertNotEqual(id(self), lclAddr1) self.assertNotEqual(0, lclAddr1) self.assertNotEqual("hi", lclAddr1) self.assertNotEqual(unittest.TestCase, lclAddr1) self.assertNotEqual(None, mainAddr1) self.assertNotEqual(id(self), mainAddr1) self.assertNotEqual(0, mainAddr1) self.assertNotEqual("hi", mainAddr1) self.assertNotEqual(unittest.TestCase, mainAddr1) self.assertNotEqual(lclAddr1, None) self.assertNotEqual(lclAddr1, id(self)) self.assertNotEqual(lclAddr1, 0) self.assertNotEqual(lclAddr1, "hi") self.assertNotEqual(lclAddr1, unittest.TestCase) self.assertNotEqual(mainAddr1, None) self.assertNotEqual(mainAddr1, id(self)) self.assertNotEqual(mainAddr1, 0) self.assertNotEqual(mainAddr1, "hi") self.assertNotEqual(mainAddr1, unittest.TestCase) def testAssociatedAddressEqualityIsUnique(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() print('Set 1: %s --> %s' % (str(lclAddr1), str(mainAddr1))) lclAddr2, mainAddr2 = self._makeLocalAndAssociated() print('Set 2: %s --> %s' % (str(lclAddr2), str(mainAddr2))) lclAddr3, mainAddr3 = self._makeLocalAndAssociated() print('Set 3: %s --> %s' % (str(lclAddr3), str(mainAddr3))) self.assertEqual(lclAddr1, lclAddr1) self.assertEqual(lclAddr2, lclAddr2) self.assertEqual(lclAddr3, lclAddr3) self.assertEqual(mainAddr1, mainAddr1) self.assertEqual(mainAddr2, mainAddr2) self.assertEqual(mainAddr3, mainAddr3) self.assertEqual(lclAddr1, mainAddr1) self.assertEqual(lclAddr2, mainAddr2) self.assertEqual(lclAddr3, mainAddr3) self.assertEqual(mainAddr1, lclAddr1) self.assertEqual(mainAddr2, lclAddr2) self.assertEqual(mainAddr3, lclAddr3) self.assertNotEqual(lclAddr1, lclAddr2) self.assertNotEqual(lclAddr2, lclAddr1) self.assertNotEqual(lclAddr3, lclAddr2) self.assertNotEqual(lclAddr2, lclAddr3) self.assertNotEqual(lclAddr3, lclAddr1) self.assertNotEqual(lclAddr1, lclAddr3) self.assertNotEqual(mainAddr1, mainAddr2) self.assertNotEqual(mainAddr2, mainAddr1) self.assertNotEqual(mainAddr3, mainAddr2) self.assertNotEqual(mainAddr2, mainAddr3) self.assertNotEqual(mainAddr3, mainAddr1) self.assertNotEqual(mainAddr1, mainAddr3) self.assertNotEqual(mainAddr1, lclAddr2) self.assertNotEqual(mainAddr2, lclAddr1) self.assertNotEqual(mainAddr3, lclAddr2) self.assertNotEqual(mainAddr2, lclAddr3) self.assertNotEqual(mainAddr3, lclAddr1) self.assertNotEqual(mainAddr1, lclAddr3) self.assertNotEqual(lclAddr1, mainAddr2) self.assertNotEqual(lclAddr2, mainAddr1) self.assertNotEqual(lclAddr3, mainAddr2) self.assertNotEqual(lclAddr2, mainAddr3) self.assertNotEqual(lclAddr3, mainAddr1) self.assertNotEqual(lclAddr1, mainAddr3)
def testAssociatedAddressRevocationIsUnique(self): myAddress = 'me' am = ActorAddressManager(None, myAddress) lclAddr1, mainAddr1 = self._makeLocalAndAssociated(myAddress, am) print('1', str(lclAddr1), str(mainAddr1)) lclAddr2, mainAddr2 = self._makeLocalAndAssociated(myAddress, am) print('2', str(lclAddr2), str(mainAddr2)) lclAddr3, mainAddr3 = self._makeLocalAndAssociated(myAddress, am) print('3', str(lclAddr3), str(mainAddr3)) assert not am.isDeadAddress(lclAddr1) assert not am.isDeadAddress(mainAddr1) print('1sm', str(am.sendToAddress(mainAddr1))) assert not am.isDeadAddress(am.sendToAddress(mainAddr1)) print('1sl', str(am.sendToAddress(lclAddr1))) assert not am.isDeadAddress(am.sendToAddress(lclAddr1)) assert not am.isDeadAddress(lclAddr2) assert not am.isDeadAddress(mainAddr2) assert not am.isDeadAddress(am.sendToAddress(mainAddr2)) assert not am.isDeadAddress(am.sendToAddress(lclAddr2)) assert not am.isDeadAddress(lclAddr3) assert not am.isDeadAddress(mainAddr3) assert not am.isDeadAddress(am.sendToAddress(mainAddr3)) assert not am.isDeadAddress(am.sendToAddress(lclAddr3)) am.deadAddress(lclAddr1) am.deadAddress(mainAddr2) assert am.isDeadAddress(lclAddr1) assert am.isDeadAddress(mainAddr1) assert am.isDeadAddress(am.sendToAddress(mainAddr1)) assert am.isDeadAddress(am.sendToAddress(lclAddr1)) assert am.isDeadAddress(lclAddr2) assert am.isDeadAddress(mainAddr2) assert am.isDeadAddress(am.sendToAddress(mainAddr2)) assert am.isDeadAddress(am.sendToAddress(lclAddr2)) assert not am.isDeadAddress(lclAddr3) assert not am.isDeadAddress(mainAddr3) assert not am.isDeadAddress(am.sendToAddress(mainAddr3)) assert not am.isDeadAddress(am.sendToAddress(lclAddr3))
class TestAddressManagerLocalAddressAssociations(unittest.TestCase): scope='unit' def setUp(self): self.myAddress = 'me' self.am = ActorAddressManager(None, self.myAddress) def testMakeAssociation(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(self)) self.am.associateUseableAddress(self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) # No exception thrown self.assertTrue(True) def _makeLocalAndAssociated(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(lclAddr)) self.am.associateUseableAddress(self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) return lclAddr, mainAddr def testAssociationRemembered(self): lclAddr, mainAddr = self._makeLocalAndAssociated() self.assertEqual(mainAddr, self.am.sendToAddress(lclAddr)) self.assertEqual(mainAddr, self.am.sendToAddress(mainAddr)) def testAssociationUnique(self): self.testAssociationRemembered() lclAddr2 = self.am.createLocalAddress() self.assertIsNone(self.am.sendToAddress(lclAddr2)) def testAssociationNotRequiredForUseableNonLocal(self): addr = ActorAddress(id(self)) self.assertEqual(addr, self.am.sendToAddress(addr)) def testAssociationEquality(self): lclAddr = self.am.createLocalAddress() mainAddr = ActorAddress(id(self)) self.assertNotEqual(lclAddr, mainAddr) self.assertNotEqual(mainAddr, lclAddr) self.am.associateUseableAddress(self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr) self.assertEqual(lclAddr, mainAddr) self.assertEqual(mainAddr, lclAddr) def testAssociationEqualityWithReconstitutedNonLocalAddress(self): lclAddr = self.am.createLocalAddress() mainAddr1 = ActorAddress(None) mainAddr2 = ActorAddress(9) self.assertNotEqual(mainAddr1, mainAddr2) self.am.associateUseableAddress(self.myAddress, lclAddr.addressDetails.addressInstanceNum, mainAddr1) self.assertEqual(lclAddr, mainAddr1) self.assertEqual(mainAddr1, lclAddr) self.assertNotEqual(lclAddr, mainAddr2) self.assertNotEqual(mainAddr2, lclAddr) mainAddr1_dup = ActorAddress(None) self.assertEqual(mainAddr1, mainAddr1_dup) self.assertNotEqual(mainAddr1_dup, lclAddr) self.assertEqual(lclAddr, mainAddr1_dup) self.am.importAddr(mainAddr1_dup) self.assertEqual(mainAddr1_dup, lclAddr) self.assertEqual(lclAddr, mainAddr1_dup) self.assertEqual(mainAddr1_dup, mainAddr1) def testAssociatedAddressesDoNotMatchArbitraryStuff(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() self.assertNotEqual(None, lclAddr1) self.assertNotEqual(id(self), lclAddr1) self.assertNotEqual(0, lclAddr1) self.assertNotEqual("hi", lclAddr1) self.assertNotEqual(unittest.TestCase, lclAddr1) self.assertNotEqual(None, mainAddr1) self.assertNotEqual(id(self), mainAddr1) self.assertNotEqual(0, mainAddr1) self.assertNotEqual("hi", mainAddr1) self.assertNotEqual(unittest.TestCase, mainAddr1) self.assertNotEqual(lclAddr1, None) self.assertNotEqual(lclAddr1, id(self)) self.assertNotEqual(lclAddr1, 0) self.assertNotEqual(lclAddr1, "hi") self.assertNotEqual(lclAddr1, unittest.TestCase) self.assertNotEqual(mainAddr1, None) self.assertNotEqual(mainAddr1, id(self)) self.assertNotEqual(mainAddr1, 0) self.assertNotEqual(mainAddr1, "hi") self.assertNotEqual(mainAddr1, unittest.TestCase) def testAssociatedAddressEqualityIsUnique(self): lclAddr1, mainAddr1 = self._makeLocalAndAssociated() print('Set 1: %s --> %s'%(str(lclAddr1), str(mainAddr1))) lclAddr2, mainAddr2 = self._makeLocalAndAssociated() print('Set 2: %s --> %s'%(str(lclAddr2), str(mainAddr2))) lclAddr3, mainAddr3 = self._makeLocalAndAssociated() print('Set 3: %s --> %s'%(str(lclAddr3), str(mainAddr3))) self.assertEqual(lclAddr1, lclAddr1) self.assertEqual(lclAddr2, lclAddr2) self.assertEqual(lclAddr3, lclAddr3) self.assertEqual(mainAddr1, mainAddr1) self.assertEqual(mainAddr2, mainAddr2) self.assertEqual(mainAddr3, mainAddr3) self.assertEqual(lclAddr1, mainAddr1) self.assertEqual(lclAddr2, mainAddr2) self.assertEqual(lclAddr3, mainAddr3) self.assertEqual(mainAddr1, lclAddr1) self.assertEqual(mainAddr2, lclAddr2) self.assertEqual(mainAddr3, lclAddr3) self.assertNotEqual(lclAddr1, lclAddr2) self.assertNotEqual(lclAddr2, lclAddr1) self.assertNotEqual(lclAddr3, lclAddr2) self.assertNotEqual(lclAddr2, lclAddr3) self.assertNotEqual(lclAddr3, lclAddr1) self.assertNotEqual(lclAddr1, lclAddr3) self.assertNotEqual(mainAddr1, mainAddr2) self.assertNotEqual(mainAddr2, mainAddr1) self.assertNotEqual(mainAddr3, mainAddr2) self.assertNotEqual(mainAddr2, mainAddr3) self.assertNotEqual(mainAddr3, mainAddr1) self.assertNotEqual(mainAddr1, mainAddr3) self.assertNotEqual(mainAddr1, lclAddr2) self.assertNotEqual(mainAddr2, lclAddr1) self.assertNotEqual(mainAddr3, lclAddr2) self.assertNotEqual(mainAddr2, lclAddr3) self.assertNotEqual(mainAddr3, lclAddr1) self.assertNotEqual(mainAddr1, lclAddr3) self.assertNotEqual(lclAddr1, mainAddr2) self.assertNotEqual(lclAddr2, mainAddr1) self.assertNotEqual(lclAddr3, mainAddr2) self.assertNotEqual(lclAddr2, mainAddr3) self.assertNotEqual(lclAddr3, mainAddr1) self.assertNotEqual(lclAddr1, mainAddr3)