WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2002 Net Integration Technologies, Inc. 00004 * 00005 * A UniConfGen that reconnects to an inner generator whenever the inner 00006 * generator is no longer OK. 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 /***** UniRetryGen *****/ 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 // here we assume that at least the mount point exists 00218 // see void UniMountGen::makemount() that create all the keys with 00219 // an empty string 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 }