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.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
00233
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