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