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)
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
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
00230
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