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
59
60 maxDelay = 300
61
63 PBClientFactory.__init__(self)
64 self._doingLogin = False
65 self._doingGetPerspective = False
66
68 PBClientFactory.clientConnectionFailed(self, connector, reason)
69
70
71
72 if self.continueTrying:
73 self.connector = connector
74 self.retry()
75
81
90
92
93 d = self.__dict__.copy()
94 d['connector'] = None
95 d['_callID'] = None
96 return d
97
98
99
101 raise RuntimeError( "getPerspective is one-shot: use startGettingPerspective instead" )
102
105 self._doingGetPerspective = True
106 if perspectiveName == None:
107 perspectiveName = username
108 self._oldcredArgs = (username, password, serviceName,
109 perspectiveName, client)
110
112
113 (username, password,
114 serviceName, perspectiveName, client) = self._oldcredArgs
115 d = self._cbAuthIdentity(root, username, password)
116 d.addCallback(self._cbGetPerspective,
117 serviceName, perspectiveName, client)
118 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
119
120
121
122
123 - def login(self, credentials, client=None):
124 from Products.ZenUtils.Utils import unused
125 unused(credentials, client)
126 raise RuntimeError( "Login is one-shot: use startLogin instead" )
127
129 self._credentials = credentials
130 self._client = client
131 self._doingLogin = True
132
139
140
141
142
144 """The remote avatar or perspective (obtained each time this factory
145 connects) is now available."""
146 pass
147
149 """The remote root object (obtained each time this factory connects)
150 is now available. This method will be called each time the connection
151 is established and the object reference is retrieved."""
152 pass
153
155 """The login process failed, most likely because of an authorization
156 failure (bad password), but it is also possible that we lost the new
157 connection before we managed to send our credentials.
158 """
159 log.msg("ReconnectingPBClientFactory.failedToGetPerspective")
160 if why.check(pb.PBConnectionLost):
161 log.msg("we lost the brand-new connection")
162
163 return
164
165 self.stopTrying()
166 log.err(why)
167