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.printable().cstr(), value.cstr());
00157 
00158     if (!processing_callback)
00159     {
00160         DPRINTF("UniReplicateGen::deltacallback(): !processing_callback\n");
00161 
00162         processing_callback = true;
00163         
00164         GenList::Iter j(gens);
00165         for (j.rewind(); j.next(); )
00166         {
00167             if (!j->isok())
00168                 continue;
00169                 
00170             if (j.ptr() != src_gen)
00171             {
00172                 DPRINTF("UniReplicateGen::deltacallback: %p->set(%s, %s)\n",
00173                         j.ptr(), key.printable().cstr(), value.cstr());
00174                 j->gen->set(key, value);
00175             }
00176         }
00177         
00178         delta(key, value);
00179         
00180         processing_callback = false;
00181     }
00182     else
00183     {
00184         DPRINTF("UniReplicateGen::deltacallback(): processing_callback\n");
00185     }
00186 }
00187 
00188 
00189 void UniReplicateGen::set(const UniConfKey &key, WvStringParm value)
00190 {
00191     DPRINTF("UniReplicateGen::set(%s, %s)\n",
00192             key.printable().cstr(), value.cstr());
00193     
00194     replicate_if_any_have_become_ok();
00195     
00196     Gen *first = first_ok();
00197     if (first)
00198         first->gen->set(key, value);
00199     else
00200         DPRINTF("UniReplicateGen::set: first == NULL\n");
00201 }
00202 
00203 
00204 void UniReplicateGen::setv(const UniConfPairList &pairs)
00205 {
00206     DPRINTF("UniReplicateGen::setv\n");
00207 
00208     replicate_if_any_have_become_ok();
00209 
00210     Gen *first = first_ok();
00211     if (first)
00212         first->gen->setv(pairs);
00213     else
00214         DPRINTF("UniReplicateGen::setv: first == NULL\n");
00215 }
00216 
00217 
00218 WvString UniReplicateGen::get(const UniConfKey &key)
00219 {
00220     for (;;)
00221     {
00222         replicate_if_any_have_become_ok();
00223     
00224         Gen *first = first_ok();
00225         if (first)
00226         {
00227             WvString result = first->gen->get(key);
00228 
00229             // It's possible that first has become !isok(); we must
00230             // take care of this case carefully
00231             if (!result && !first->isok())
00232             {
00233                 Gen *new_first = first_ok();
00234                 if (new_first == first)
00235                     return result;
00236                 first = new_first; 
00237             }
00238             else
00239                 return result;
00240         }
00241         else
00242             return WvString::null;
00243     }
00244 }
00245 
00246 
00247 UniConfGen::Iter *UniReplicateGen::iterator(const UniConfKey &key)
00248 {
00249     replicate_if_any_have_become_ok();
00250     
00251     Gen *first = first_ok();
00252     if (first)
00253         return first->gen->iterator(key);
00254     else
00255         return NULL;
00256 }
00257 
00258 
00259 UniReplicateGen::Gen *UniReplicateGen::first_ok() const
00260 {
00261     GenList::Iter j(gens);
00262     for (j.rewind(); j.next(); )
00263     {
00264         if (j->isok())
00265             return j.ptr();
00266     }
00267             
00268     return NULL;
00269 }
00270 
00271 
00272 void UniReplicateGen::replicate(const UniConfKey &key)
00273 {
00274     DPRINTF("UniReplicateGen::replicate(%s)\n", key.printable().cstr());
00275        
00276     hold_delta();
00277     
00278     Gen *first = first_ok();
00279     
00280     GenList::Iter j(gens);
00281     for (j.rewind(); j.next(); )
00282     {
00283         DPRINTF("UniReplicateGen::replicate: %p\n", j.ptr());
00284         
00285         if (!j->isok())
00286         {
00287             DPRINTF("UniReplicateGen::replicate: !isok()\n");
00288             continue;
00289         }
00290             
00291         UniConfGen::Iter *i = j->gen->recursiveiterator(key);
00292         if (!i)
00293         {
00294             DPRINTF("UniReplicateGen::replicate: no iterator\n");
00295             continue;
00296         }
00297     
00298         for (i->rewind(); i->next(); )
00299         {
00300             DPRINTF("UniReplicateGen::replicate: key=%s, value=%s\n",
00301                     i->key().printable().cstr(), i->value().cstr());
00302 
00303             if (j.ptr() == first)
00304             {
00305                 DPRINTF("UniReplicateGen::replicate: deltacallback()\n");
00306                 deltacallback(first, i->key(), i->value());
00307             }
00308             else
00309             {
00310                 if (!first->gen->exists(i->key()))
00311                 {
00312                     DPRINTF("UniReplicateGen::replicate: !exists()\n");
00313                     first->gen->set(i->key(), i->value());
00314                 }
00315                 else
00316                 {
00317                     DPRINTF("UniReplicateGen::replicate: exists()\n");
00318                 }
00319             }
00320         }
00321     
00322         delete i;
00323     }
00324     
00325     unhold_delta();
00326 
00327     DPRINTF("UniReplicateGen::replicate: done\n");
00328 }
00329 
00330 void UniReplicateGen::replicate_if_any_have_become_ok()
00331 {
00332     bool should_replicate = false;
00333     
00334     GenList::Iter j(gens);
00335     for (j.rewind(); j.next(); )
00336     {
00337         if (!j->was_ok && j->gen->isok())
00338         {
00339             j->was_ok = true;
00340             
00341             should_replicate = true;
00342         }
00343     }
00344     
00345     if (should_replicate)
00346     {
00347         DPRINTF("UniReplicateGen::replicate_if_any_have_become_ok: replicating\n");
00348         replicate();
00349     }
00350 }
00351 

Generated on Thu Jan 24 16:50:55 2008 for WvStreams by  doxygen 1.5.4