WvStreams
unireplicategen.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2002 Net Integration Technologies, Inc.
00004  * 
00005  * A UniConf generator that replicates multiple generators, prioritized
00006  * by order.
00007  */
00008 #include "uniconf.h"
00009 #include "unireplicategen.h"
00010 #include "wvmoniker.h"
00011 #include "wvstringlist.h"
00012 #include "wvtclstring.h"
00013 #include "wvlinkerhack.h"
00014 
00015 WV_LINK(UniReplicateGen);
00016 
00017 
00018 #if 0
00019 #define DPRINTF(format, args...) fprintf(stderr, format ,##args);
00020 #else
00021 #define DPRINTF if (0) printf
00022 #endif
00023 
00024 
00025 static IUniConfGen *creator(WvStringParm s, IObject *_obj)
00026 {
00027     IUniConfGenList gens;
00028     
00029     DPRINTF("encoded_monikers = %s\n", s.cstr());
00030     WvStringList monikers;
00031     wvtcl_decode(monikers, s);
00032     DPRINTF("monikers = %s\n", monikers.join(",").cstr());
00033     
00034     WvStringList::Iter i(monikers);
00035     for (i.rewind(); i.next(); )
00036     {
00037         if (_obj) _obj->addRef();
00038         IUniConfGen *gen = wvcreate<IUniConfGen>(*i, _obj);
00039         if (gen)
00040             gens.append(gen, false);
00041     }
00042     if (_obj) _obj->release();
00043 
00044     return new UniReplicateGen(gens);
00045 }
00046 
00047 static WvMoniker<IUniConfGen> reg("replicate", creator);
00048 
00049 
00050 /***** UniReplicateGen *****/
00051 
00052 UniReplicateGen::UniReplicateGen() : processing_callback(false)
00053 {
00054 }
00055 
00056 
00057 UniReplicateGen::UniReplicateGen(const IUniConfGenList &_gens,
00058         bool auto_free) : processing_callback(false)
00059 {
00060     IUniConfGenList::Iter i(_gens);
00061     
00062     for (i.rewind(); i.next(); )
00063     {
00064         Gen *gen = new Gen(i.ptr(), auto_free);
00065         if (gen)
00066         {
00067             gens.append(gen, true);
00068             gen->gen->add_callback(this,
00069                                    wv::bind(&UniReplicateGen::deltacallback,
00070                                             this, gen, _1, _2));
00071         }
00072     }
00073     
00074     replicate();
00075 }
00076 
00077 
00078 UniReplicateGen::~UniReplicateGen()
00079 {
00080     GenList::Iter i(gens);
00081     for (i.rewind(); i.next(); )
00082         i->gen->del_callback(this);
00083 }
00084 
00085 
00086 void UniReplicateGen::prepend(IUniConfGen *_gen, bool auto_free)
00087 {
00088     Gen *gen = new Gen(_gen, auto_free);
00089     if (gen)
00090     {
00091         gens.prepend(gen, true);
00092         gen->gen->add_callback(this, wv::bind(&UniReplicateGen::deltacallback,
00093                                               this, gen, _1, _2));
00094             
00095         replicate();
00096     }
00097 }
00098 
00099 
00100 void UniReplicateGen::append(IUniConfGen *_gen, bool auto_free)
00101 {
00102     Gen *gen = new Gen(_gen, auto_free);
00103     if (gen)
00104     {
00105         gens.append(gen, true);
00106         gen->gen->add_callback(this, wv::bind(&UniReplicateGen::deltacallback,
00107                                               this, gen, _1, _2));
00108             
00109         replicate();
00110     }
00111 }
00112 
00113 
00114 bool UniReplicateGen::isok()
00115 {
00116     return first_ok() != NULL;
00117 }
00118 
00119 
00120 bool UniReplicateGen::refresh()
00121 {
00122     bool result = true;
00123     
00124     replicate_if_any_have_become_ok();
00125     
00126     GenList::Iter i(gens);
00127     for (i.rewind(); i.next(); )
00128     {
00129         if (!i->gen->refresh())
00130             result = false;
00131     }
00132     
00133     return result;
00134 }
00135 
00136 
00137 void UniReplicateGen::commit()
00138 {
00139     replicate_if_any_have_become_ok();
00140     
00141     GenList::Iter i(gens);
00142     for (i.rewind(); i.next(); )
00143     {
00144         i->gen->commit();
00145     }
00146 }
00147 
00148 
00149 void UniReplicateGen::deltacallback(Gen *src_gen, const UniConfKey &key,
00150                                     WvStringParm value)
00151 {
00152     DPRINTF("UniReplicateGen::deltacallback(%s, %s)\n",
00153             key.printable().cstr(), value.cstr());
00154 
00155     if (!processing_callback)
00156     {
00157         DPRINTF("UniReplicateGen::deltacallback(): !processing_callback\n");
00158 
00159         processing_callback = true;
00160         
00161         GenList::Iter j(gens);
00162         for (j.rewind(); j.next(); )
00163         {
00164             if (!j->isok())
00165                 continue;
00166                 
00167             if (j.ptr() != src_gen)
00168             {
00169                 DPRINTF("UniReplicateGen::deltacallback: %p->set(%s, %s)\n",
00170                         j.ptr(), key.printable().cstr(), value.cstr());
00171                 j->gen->set(key, value);
00172             }
00173         }
00174         
00175         delta(key, value);
00176         
00177         processing_callback = false;
00178     }
00179     else
00180     {
00181         DPRINTF("UniReplicateGen::deltacallback(): processing_callback\n");
00182     }
00183 }
00184 
00185 
00186 void UniReplicateGen::set(const UniConfKey &key, WvStringParm value)
00187 {
00188     DPRINTF("UniReplicateGen::set(%s, %s)\n",
00189             key.printable().cstr(), value.cstr());
00190     
00191     replicate_if_any_have_become_ok();
00192     
00193     Gen *first = first_ok();
00194     if (first)
00195         first->gen->set(key, value);
00196     else
00197         DPRINTF("UniReplicateGen::set: first == NULL\n");
00198 }
00199 
00200 
00201 void UniReplicateGen::setv(const UniConfPairList &pairs)
00202 {
00203     DPRINTF("UniReplicateGen::setv\n");
00204 
00205     replicate_if_any_have_become_ok();
00206 
00207     Gen *first = first_ok();
00208     if (first)
00209         first->gen->setv(pairs);
00210     else
00211         DPRINTF("UniReplicateGen::setv: first == NULL\n");
00212 }
00213 
00214 
00215 WvString UniReplicateGen::get(const UniConfKey &key)
00216 {
00217     for (;;)
00218     {
00219         replicate_if_any_have_become_ok();
00220     
00221         Gen *first = first_ok();
00222         if (first)
00223         {
00224             WvString result = first->gen->get(key);
00225 
00226             // It's possible that first has become !isok(); we must
00227             // take care of this case carefully
00228             if (!result && !first->isok())
00229             {
00230                 Gen *new_first = first_ok();
00231                 if (new_first == first)
00232                     return result;
00233                 first = new_first; 
00234             }
00235             else
00236                 return result;
00237         }
00238         else
00239             return WvString::null;
00240     }
00241 }
00242 
00243 
00244 UniConfGen::Iter *UniReplicateGen::iterator(const UniConfKey &key)
00245 {
00246     replicate_if_any_have_become_ok();
00247     
00248     Gen *first = first_ok();
00249     if (first)
00250         return first->gen->iterator(key);
00251     else
00252         return NULL;
00253 }
00254 
00255 
00256 UniReplicateGen::Gen *UniReplicateGen::first_ok() const
00257 {
00258     GenList::Iter j(gens);
00259     for (j.rewind(); j.next(); )
00260     {
00261         if (j->isok())
00262             return j.ptr();
00263     }
00264             
00265     return NULL;
00266 }
00267 
00268 
00269 void UniReplicateGen::replicate(const UniConfKey &key)
00270 {
00271     DPRINTF("UniReplicateGen::replicate(%s)\n", key.printable().cstr());
00272        
00273     hold_delta();
00274     
00275     Gen *first = first_ok();
00276     
00277     GenList::Iter j(gens);
00278     for (j.rewind(); j.next(); )
00279     {
00280         DPRINTF("UniReplicateGen::replicate: %p\n", j.ptr());
00281         
00282         if (!j->isok())
00283         {
00284             DPRINTF("UniReplicateGen::replicate: !isok()\n");
00285             continue;
00286         }
00287             
00288         UniConfGen::Iter *i = j->gen->recursiveiterator(key);
00289         if (!i)
00290         {
00291             DPRINTF("UniReplicateGen::replicate: no iterator\n");
00292             continue;
00293         }
00294     
00295         for (i->rewind(); i->next(); )
00296         {
00297             DPRINTF("UniReplicateGen::replicate: key=%s, value=%s\n",
00298                     i->key().printable().cstr(), i->value().cstr());
00299 
00300             if (j.ptr() == first)
00301             {
00302                 DPRINTF("UniReplicateGen::replicate: deltacallback()\n");
00303                 deltacallback(first, i->key(), i->value());
00304             }
00305             else
00306             {
00307                 if (!first->gen->exists(i->key()))
00308                 {
00309                     DPRINTF("UniReplicateGen::replicate: !exists()\n");
00310                     first->gen->set(i->key(), i->value());
00311                 }
00312                 else
00313                 {
00314                     DPRINTF("UniReplicateGen::replicate: exists()\n");
00315                 }
00316             }
00317         }
00318     
00319         delete i;
00320     }
00321     
00322     unhold_delta();
00323 
00324     DPRINTF("UniReplicateGen::replicate: done\n");
00325 }
00326 
00327 void UniReplicateGen::replicate_if_any_have_become_ok()
00328 {
00329     bool should_replicate = false;
00330     
00331     GenList::Iter j(gens);
00332     for (j.rewind(); j.next(); )
00333     {
00334         if (!j->was_ok && j->gen->isok())
00335         {
00336             j->was_ok = true;
00337             
00338             should_replicate = true;
00339         }
00340     }
00341     
00342     if (should_replicate)
00343     {
00344         DPRINTF("UniReplicateGen::replicate_if_any_have_become_ok: replicating\n");
00345         replicate();
00346     }
00347 }
00348