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 
14 WV_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 
24 static 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 
45 static WvMoniker<IUniConfGen> reg("retry", creator);
46 
47 
48 /***** UniRetryGen *****/
49 
50 UniRetryGen::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 
67 void 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 
105 void 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 
151 void 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 
189 void UniRetryGen::set(const UniConfKey &key, WvStringParm value)
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 
282  Iter *result = UniFilterGen::recursiveiterator(key);
283 
284  maybe_disconnect();
285 
286  return result;
287 }