00001
00002
00003
00004
00005
00006
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
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
00227
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