Package buildslave :: Module pbutil
[frames] | no frames]

Source Code for Module buildslave.pbutil

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16   
 17  """Base classes handy for use with PB clients. 
 18  """ 
 19   
 20  from twisted.spread import pb 
 21   
 22  from twisted.spread.pb import PBClientFactory 
 23  from twisted.internet import protocol, reactor 
 24  from twisted.python import log 
 25   
26 -class ReconnectingPBClientFactory(PBClientFactory, 27 protocol.ReconnectingClientFactory):
28 """Reconnecting client factory for PB brokers. 29 30 Like PBClientFactory, but if the connection fails or is lost, the factory 31 will attempt to reconnect. 32 33 Instead of using f.getRootObject (which gives a Deferred that can only 34 be fired once), override the gotRootObject method. 35 36 Instead of using the newcred f.login (which is also one-shot), call 37 f.startLogin() with the credentials and client, and override the 38 gotPerspective method. 39 40 gotRootObject and gotPerspective will be called each time the object is 41 received (once per successful connection attempt). You will probably want 42 to use obj.notifyOnDisconnect to find out when the connection is lost. 43 44 If an authorization error occurs, failedToGetPerspective() will be 45 invoked. 46 47 To use me, subclass, then hand an instance to a connector (like 48 TCPClient). 49 """ 50 51 # hung connections wait for a relatively long time, since a busy master may 52 # take a while to get back to us. 53 hungConnectionTimer = None 54 HUNG_CONNECTION_TIMEOUT = 120 55
56 - def clientConnectionFailed(self, connector, reason):
57 PBClientFactory.clientConnectionFailed(self, connector, reason) 58 if self.continueTrying: 59 self.connector = connector 60 self.retry()
61
62 - def clientConnectionLost(self, connector, reason):
63 PBClientFactory.clientConnectionLost(self, connector, reason, 64 reconnecting=True) 65 RCF = protocol.ReconnectingClientFactory 66 RCF.clientConnectionLost(self, connector, reason)
67
68 - def startedConnecting(self, connector):
70
71 - def clientConnectionMade(self, broker):
72 self.resetDelay() 73 PBClientFactory.clientConnectionMade(self, broker) 74 self.doLogin(self._root) 75 self.gotRootObject(self._root)
76 77 # newcred methods 78
79 - def login(self, *args):
80 raise RuntimeError, "login is one-shot: use startLogin instead"
81
82 - def startLogin(self, credentials, client=None):
83 self._credentials = credentials 84 self._client = client
85
86 - def doLogin(self, root):
87 # newcred login() 88 d = self._cbSendUsername(root, self._credentials.username, 89 self._credentials.password, self._client) 90 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
91 92 # timer for hung connections 93
94 - def startHungConnectionTimer(self, connector):
95 self.stopHungConnectionTimer() 96 def hungConnection(): 97 log.msg("connection attempt timed out (is the port number correct?)") 98 self.hungConnectionTimer = None 99 connector.disconnect()
100 # (this will trigger the retry) 101 self.hungConnectionTimer = reactor.callLater(self.HUNG_CONNECTION_TIMEOUT, hungConnection)
102
103 - def stopHungConnectionTimer(self):
104 if self.hungConnectionTimer: 105 self.hungConnectionTimer.cancel() 106 self.hungConnectionTimer = None
107 108 # methods to override 109
110 - def gotPerspective(self, perspective):
111 """The remote avatar or perspective (obtained each time this factory 112 connects) is now available.""" 113 self.stopHungConnectionTimer()
114
115 - def gotRootObject(self, root):
116 """The remote root object (obtained each time this factory connects) 117 is now available. This method will be called each time the connection 118 is established and the object reference is retrieved.""" 119 self.stopHungConnectionTimer()
120
121 - def failedToGetPerspective(self, why):
122 """The login process failed, most likely because of an authorization 123 failure (bad password), but it is also possible that we lost the new 124 connection before we managed to send our credentials. 125 """ 126 log.msg("ReconnectingPBClientFactory.failedToGetPerspective") 127 self.stopHungConnectionTimer() 128 if why.check(pb.PBConnectionLost): 129 log.msg("we lost the brand-new connection") 130 # retrying might help here, let clientConnectionLost decide 131 return 132 # probably authorization 133 self.stopTrying() # logging in harder won't help 134 log.err(why) 135 reactor.stop()
136