WvStreams
uniretrygen.cc
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 }