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

Generated on Fri Oct 5 18:20:26 2007 for WvStreams by  doxygen 1.5.3