1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 __doc__ = """PBUtil
19 Base classes handy for use with PB clients.
20 """
21
22 from twisted.spread import pb
23
24 from twisted.spread.pb import PBClientFactory
25 from twisted.internet import protocol
26 from twisted.python import log
27
30 """Reconnecting client factory for PB brokers.
31
32 Like PBClientFactory, but if the connection fails or is lost, the factory
33 will attempt to reconnect.
34
35 Instead of using f.getRootObject (which gives a Deferred that can only
36 be fired once), override the gotRootObject method.
37
38 Instead of using the newcred f.login (which is also one-shot), call
39 f.startLogin() with the credentials and client, and override the
40 gotPerspective method.
41
42 Instead of using the oldcred f.getPerspective (also one-shot), call
43 f.startGettingPerspective() with the same arguments, and override
44 gotPerspective.
45
46 gotRootObject and gotPerspective will be called each time the object is
47 received (once per successful connection attempt). You will probably want
48 to use obj.notifyOnDisconnect to find out when the connection is lost.
49
50 If an authorization error occurs, failedToGetPerspective() will be
51 invoked.
52
53 To use me, subclass, then hand an instance to a connector (like
54 TCPClient).
55 """
56 __pychecker__='no-override'
57
58 maxdelay = 5
59
61 PBClientFactory.__init__(self)
62 self._doingLogin = False
63 self._doingGetPerspective = False
64
66 PBClientFactory.clientConnectionFailed(self, connector, reason)
67
68
69
70 if self.continueTrying:
71 self.connector = connector
72 self.retry()
73
79
88
90
91 d = self.__dict__.copy()
92 d['connector'] = None
93 d['_callID'] = None
94 return d
95
96
97
99 raise RuntimeError( "getPerspective is one-shot: use startGettingPerspective instead" )
100
103 self._doingGetPerspective = True
104 if perspectiveName == None:
105 perspectiveName = username
106 self._oldcredArgs = (username, password, serviceName,
107 perspectiveName, client)
108
110
111 (username, password,
112 serviceName, perspectiveName, client) = self._oldcredArgs
113 d = self._cbAuthIdentity(root, username, password)
114 d.addCallback(self._cbGetPerspective,
115 serviceName, perspectiveName, client)
116 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
117
118
119
120
121 - def login(self, credentials, client=None):
122 from Products.ZenUtils.Utils import unused
123 unused(credentials, client)
124 raise RuntimeError( "Login is one-shot: use startLogin instead" )
125
127 self._credentials = credentials
128 self._client = client
129 self._doingLogin = True
130
137
138
139
140
142 """The remote avatar or perspective (obtained each time this factory
143 connects) is now available."""
144 pass
145
147 """The remote root object (obtained each time this factory connects)
148 is now available. This method will be called each time the connection
149 is established and the object reference is retrieved."""
150 pass
151
153 """The login process failed, most likely because of an authorization
154 failure (bad password), but it is also possible that we lost the new
155 connection before we managed to send our credentials.
156 """
157 log.msg("ReconnectingPBClientFactory.failedToGetPerspective")
158 if why.check(pb.PBConnectionLost):
159 log.msg("we lost the brand-new connection")
160
161 return
162
163 self.stopTrying()
164 log.err(why)
165