WvStreams
|
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