WvStreams
uniretrygen.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002 Net Integration Technologies, Inc.
4 *
5 * A UniConfGen that reconnects to an inner generator whenever the inner
6 * generator is no longer OK.
7 */
8#include "uniretrygen.h"
9#include "wvmoniker.h"
10#include "wvtclstring.h"
11#include "wvstringlist.h"
12#include "wvlinkerhack.h"
13
14WV_LINK(UniRetryGen);
15
16
17#if 0
18#define DPRINTF(format, args...) fprintf(stderr, format ,##args);
19#else
20#define DPRINTF if (0) printf
21#endif
22
23
24static IUniConfGen *creator(WvStringParm encoded_params, IObject *_obj)
25{
26 DPRINTF("encoded_params = %s\n", encoded_params.cstr());
27 WvStringList params;
28 wvtcl_decode(params, encoded_params);
29 if (params.count() == 0)
30 return NULL;
31
32 WvString moniker = params.popstr();
33 if (params.count() == 0)
34 return new UniRetryGen(moniker);
35
36 WvString retry_interval_ms_str = params.popstr();
37 time_t retry_interval_ms = retry_interval_ms_str.num();
38 if (retry_interval_ms < 0)
39 retry_interval_ms = 0;
40 return new UniRetryGen(moniker,
41 UniRetryGen::ReconnectCallback(),
42 retry_interval_ms);
43}
44
45static WvMoniker<IUniConfGen> reg("retry", creator);
46
47
48/***** UniRetryGen *****/
49
50UniRetryGen::UniRetryGen(WvStringParm _moniker,
51 ReconnectCallback _reconnect_callback,
52 time_t _retry_interval_ms)
53 : UniFilterGen(NULL),
54 log(WvString("UniRetryGen %s", _moniker), WvLog::Debug1),
55 moniker(_moniker),
56 reconnect_callback(_reconnect_callback),
57 retry_interval_ms(_retry_interval_ms),
58 next_reconnect_attempt(wvtime())
59{
60 DPRINTF("UniRetryGen::UniRetryGen(%s, %ld)\n",
61 moniker.cstr(), retry_interval_ms);
62
63 maybe_reconnect();
64}
65
66
67void UniRetryGen::maybe_reconnect()
68{
69 if (!inner())
70 {
71 if (!(wvtime() < next_reconnect_attempt))
72 {
73 IUniConfGen *gen = wvcreate<IUniConfGen>(moniker);
74
75 if (!gen)
76 {
77 DPRINTF("UniRetryGen::maybe_reconnect: !gen\n");
78 return;
79 }
80
81 if (gen->isok())
82 {
83 DPRINTF("UniRetryGen::maybe_reconnect: gen->isok()\n");
84
85 log("Connected\n");
86
87 setinner(gen);
88
89 if (!!reconnect_callback) reconnect_callback(*this);
90 }
91 else
92 {
93 DPRINTF("UniRetryGen::maybe_reconnect: !gen->isok()\n");
94
95 WVRELEASE(gen);
96
97 next_reconnect_attempt =
98 msecadd(next_reconnect_attempt, retry_interval_ms);
99 }
100 }
101 }
102}
103
104
105void UniRetryGen::maybe_disconnect()
106{
107 if (inner() && !inner()->isok())
108 {
109 DPRINTF("UniRetryGen::maybe_disconnect: inner() && !inner()->isok()\n");
110
111 log("Disconnected\n");
112
113 IUniConfGen *old_inner = inner();
114
115 setinner(NULL);
116
117 WVRELEASE(old_inner);
118
119 next_reconnect_attempt = msecadd(wvtime(), retry_interval_ms);
120 }
121}
122
123
125{
126 maybe_reconnect();
127
128 if (UniFilterGen::isok())
130
131 maybe_disconnect();
132}
133
134
136{
137 maybe_reconnect();
138
139 bool result;
140 if (UniFilterGen::isok())
141 result = UniFilterGen::refresh();
142 else
143 result = false;
144
145 maybe_disconnect();
146
147 return result;
148}
149
150
151void UniRetryGen::prefetch(const UniConfKey &key, bool recursive)
152{
153 maybe_reconnect();
154
155 if (UniFilterGen::isok())
156 UniFilterGen::prefetch(key, recursive);
157
158 maybe_disconnect();
159}
160
161
163{
164 maybe_reconnect();
165
166 WvString result;
167 if (UniFilterGen::isok())
168 {
169 result = UniFilterGen::get(key);
170 DPRINTF("UniRetryGen::get(%s) returns %s\n", key.printable().cstr(), result.cstr());
171 }
172 else if (key == "")
173 {
174 result = "";
175 DPRINTF("UniRetryGen::get(%s) returns %s because it is root key\n", key.printable().cstr(), result.cstr());
176 }
177 else
178 {
179 DPRINTF("UniRetryGen::get(%s): !isok()\n", key.printable().cstr());
180 result = WvString::null;
181 }
182
183 maybe_disconnect();
184
185 return result;
186}
187
188
190{
191 maybe_reconnect();
192
193 if (UniFilterGen::isok())
194 UniFilterGen::set(key, value);
195
196 maybe_disconnect();
197}
198
199
201{
202 maybe_reconnect();
203
204 DPRINTF("UniRetryGen::exists(%s)\n", key.printable().cstr());
205
206 bool result;
207 if (UniFilterGen::isok())
208 {
209 result = UniFilterGen::exists(key);
210 DPRINTF("UniRetryGen::exists: returns %s\n", result? "true": "false");
211 }
212 else
213 {
214 DPRINTF("UniRetryGen::exists: !isok()\n");
215 if (key == "")
216 {
217 // here we assume that at least the mount point exists
218 // see void UniMountGen::makemount() that create all the keys with
219 // an empty string
220 result = true;
221 }
222 else
223 {
224 result = false;
225 }
226 }
227
228 maybe_disconnect();
229
230 return result;
231}
232
233
235{
236 maybe_reconnect();
237
238 bool result;
239 if (UniFilterGen::isok())
240 result = UniFilterGen::haschildren(key);
241 else
242 result = false;
243
244 maybe_disconnect();
245
246 return result;
247}
248
249
251{
252 maybe_reconnect();
253
254 bool result = UniFilterGen::isok();
255
256 maybe_disconnect();
257
258 return result;
259}
260
261
263{
264 maybe_reconnect();
265
266 Iter *result;
267 if (UniFilterGen::isok())
268 result = UniFilterGen::iterator(key);
269 else
270 result = NULL;
271
272 maybe_disconnect();
273
274 return result;
275}
276
277
279{
280 maybe_reconnect();
281
283
284 maybe_disconnect();
285
286 return result;
287}
The basic interface which is included by all other XPLC interfaces and objects.
An abstract data container that backs a UniConf tree.
virtual bool isok()=0
Determines if the generator is usable and working properly.
An abstract iterator over keys and values in a generator.
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
WvString printable() const
Returns the canonical string representation of the path.
A UniConfGen that delegates all requests to an inner generator.
virtual void prefetch(const UniConfKey &key, bool recursive)
Indicate that we will eventually be interested in doing get(), haschildren(), or other "get-like" ope...
void setinner(IUniConfGen *inner)
Rebinds the inner generator and prepares its callback.
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
IUniConfGen * inner() const
Returns the inner generator.
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
virtual bool refresh()
Refreshes information about a key recursively.
virtual void commit()
Commits any changes.
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
virtual bool isok()
Determines if the generator is usable and working properly.
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
A UniConfGen that reconnects to an inner generator specified by a moniker whenever the inner generato...
virtual bool haschildren(const UniConfKey &key)
Returns true if a key has children.
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
virtual void prefetch(const UniConfKey &key, bool recursive)
Indicate that we will eventually be interested in doing get(), haschildren(), or other "get-like" ope...
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
virtual bool isok()
Determines if the generator is usable and working properly.
virtual bool refresh()
Refreshes information about a key recursively.
virtual Iter * recursiveiterator(const UniConfKey &key)
Like iterator(), but the returned iterator is recursive, that is, it will return children of the imme...
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
virtual bool exists(const UniConfKey &key)
Without fetching its value, returns true if a key exists.
virtual void commit()
Commits any changes.
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
int num() const
Return a stdc++ string with the contents of this string.
const char * cstr() const
return a (const char *) for this string.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
WvString is an implementation of a simple and efficient printable-string class.
void wvtcl_decode(WvList< WvString > &l, WvStringParm _s, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
split a tcl-style list.