00001
00002
00003
00004
00005
00006
00007
00008 #include "uniretrygen.h"
00009 #include "wvmoniker.h"
00010 #include "wvtclstring.h"
00011 #include "wvstringlist.h"
00012 #include "wvlinkerhack.h"
00013
00014 WV_LINK(UniRetryGen);
00015
00016
00017 #if 0
00018 #define DPRINTF(format, args...) fprintf(stderr, format ,##args);
00019 #else
00020 #define DPRINTF if (0) printf
00021 #endif
00022
00023
00024 static IUniConfGen *creator(WvStringParm encoded_params)
00025 {
00026 DPRINTF("encoded_params = %s\n", encoded_params.cstr());
00027 WvStringList params;
00028 wvtcl_decode(params, encoded_params);
00029 if (params.count() == 0)
00030 return NULL;
00031
00032 WvString moniker = params.popstr();
00033 if (params.count() == 0)
00034 return new UniRetryGen(moniker);
00035
00036 WvString retry_interval_ms_str = params.popstr();
00037 time_t retry_interval_ms = retry_interval_ms_str.num();
00038 if (retry_interval_ms < 0)
00039 retry_interval_ms = 0;
00040 return new UniRetryGen(moniker, UniRetryGen::ReconnectCallback(),
00041 retry_interval_ms);
00042 }
00043
00044 static WvMoniker<IUniConfGen> reg("retry", creator);
00045
00046
00047
00048
00049 UniRetryGen::UniRetryGen(WvStringParm _moniker,
00050 ReconnectCallback _reconnect_callback,
00051 time_t _retry_interval_ms)
00052 : UniFilterGen(NULL),
00053 log(WvString("UniRetryGen %s", _moniker), WvLog::Debug1),
00054 moniker(_moniker),
00055 reconnect_callback(_reconnect_callback),
00056 retry_interval_ms(_retry_interval_ms),
00057 next_reconnect_attempt(wvtime())
00058 {
00059 DPRINTF("UniRetryGen::UniRetryGen(%s, %ld)\n",
00060 moniker.cstr(), retry_interval_ms);
00061
00062 maybe_reconnect();
00063 }
00064
00065
00066 void UniRetryGen::maybe_reconnect()
00067 {
00068 if (!inner())
00069 {
00070 if (!(wvtime() < next_reconnect_attempt))
00071 {
00072 IUniConfGen *gen = wvcreate<IUniConfGen>(moniker);
00073
00074 if (!gen)
00075 {
00076 DPRINTF("UniRetryGen::maybe_reconnect: !gen\n");
00077 return;
00078 }
00079
00080 if (gen->isok())
00081 {
00082 DPRINTF("UniRetryGen::maybe_reconnect: gen->isok()\n");
00083
00084 log("Connected\n");
00085
00086 setinner(gen);
00087
00088 if (!!reconnect_callback) reconnect_callback(*this);
00089 }
00090 else
00091 {
00092 DPRINTF("UniRetryGen::maybe_reconnect: !gen->isok()\n");
00093
00094 WVRELEASE(gen);
00095
00096 next_reconnect_attempt =
00097 msecadd(next_reconnect_attempt, retry_interval_ms);
00098 }
00099 }
00100 }
00101 }
00102
00103
00104 void UniRetryGen::maybe_disconnect()
00105 {
00106 if (inner() && !inner()->isok())
00107 {
00108 DPRINTF("UniRetryGen::maybe_disconnect: inner() && !inner()->isok()\n");
00109
00110 log("Disconnected\n");
00111
00112 IUniConfGen *old_inner = inner();
00113
00114 setinner(NULL);
00115
00116 WVRELEASE(old_inner);
00117
00118 next_reconnect_attempt = msecadd(wvtime(), retry_interval_ms);
00119 }
00120 }
00121
00122
00123 void UniRetryGen::commit()
00124 {
00125 maybe_reconnect();
00126
00127 if (UniFilterGen::isok())
00128 UniFilterGen::commit();
00129
00130 maybe_disconnect();
00131 }
00132
00133
00134 bool UniRetryGen::refresh()
00135 {
00136 maybe_reconnect();
00137
00138 bool result;
00139 if (UniFilterGen::isok())
00140 result = UniFilterGen::refresh();
00141 else
00142 result = false;
00143
00144 maybe_disconnect();
00145
00146 return result;
00147 }
00148
00149
00150 void UniRetryGen::prefetch(const UniConfKey &key, bool recursive)
00151 {
00152 maybe_reconnect();
00153
00154 if (UniFilterGen::isok())
00155 UniFilterGen::prefetch(key, recursive);
00156
00157 maybe_disconnect();
00158 }
00159
00160
00161 WvString UniRetryGen::get(const UniConfKey &key)
00162 {
00163 maybe_reconnect();
00164
00165 WvString result;
00166 if (UniFilterGen::isok())
00167 {
00168 result = UniFilterGen::get(key);
00169 DPRINTF("UniRetryGen::get(%s) returns %s\n", key.printable().cstr(), result.cstr());
00170 }
00171 else if (key == "")
00172 {
00173 result = "";
00174 DPRINTF("UniRetryGen::get(%s) returns %s because it is root key\n", key.printable().cstr(), result.cstr());
00175 }
00176 else
00177 {
00178 DPRINTF("UniRetryGen::get(%s): !isok()\n", key.printable().cstr());
00179 result = WvString::null;
00180 }
00181
00182 maybe_disconnect();
00183
00184 return result;
00185 }
00186
00187
00188 void UniRetryGen::set(const UniConfKey &key, WvStringParm value)
00189 {
00190 maybe_reconnect();
00191
00192 if (UniFilterGen::isok())
00193 UniFilterGen::set(key, value);
00194
00195 maybe_disconnect();
00196 }
00197
00198
00199 bool UniRetryGen::exists(const UniConfKey &key)
00200 {
00201 maybe_reconnect();
00202
00203 DPRINTF("UniRetryGen::exists(%s)\n", key.printable().cstr());
00204
00205 bool result;
00206 if (UniFilterGen::isok())
00207 {
00208 result = UniFilterGen::exists(key);
00209 DPRINTF("UniRetryGen::exists: returns %s\n", result? "true": "false");
00210 }
00211 else
00212 {
00213 DPRINTF("UniRetryGen::exists: !isok()\n");
00214 if (key == "")
00215 {
00216
00217
00218
00219 result = true;
00220 }
00221 else
00222 {
00223 result = false;
00224 }
00225 }
00226
00227 maybe_disconnect();
00228
00229 return result;
00230 }
00231
00232
00233 bool UniRetryGen::haschildren(const UniConfKey &key)
00234 {
00235 maybe_reconnect();
00236
00237 bool result;
00238 if (UniFilterGen::isok())
00239 result = UniFilterGen::haschildren(key);
00240 else
00241 result = false;
00242
00243 maybe_disconnect();
00244
00245 return result;
00246 }
00247
00248
00249 bool UniRetryGen::isok()
00250 {
00251 maybe_reconnect();
00252
00253 bool result = UniFilterGen::isok();
00254
00255 maybe_disconnect();
00256
00257 return result;
00258 }
00259
00260
00261 UniConfGen::Iter *UniRetryGen::iterator(const UniConfKey &key)
00262 {
00263 maybe_reconnect();
00264
00265 Iter *result;
00266 if (UniFilterGen::isok())
00267 result = UniFilterGen::iterator(key);
00268 else
00269 result = NULL;
00270
00271 maybe_disconnect();
00272
00273 return result;
00274 }
00275
00276
00277 UniConfGen::Iter *UniRetryGen::recursiveiterator(const UniConfKey &key)
00278 {
00279 maybe_reconnect();
00280
00281 Iter *result = UniFilterGen::recursiveiterator(key);
00282
00283 maybe_disconnect();
00284
00285 return result;
00286 }