2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002 Net Integration Technologies, Inc.
5 * A UniConf generator that replicates multiple generators, prioritized
9 #include "unireplicategen.h"
10 #include "wvmoniker.h"
11 #include "wvstringlist.h"
12 #include "wvtclstring.h"
13 #include "wvlinkerhack.h"
15 WV_LINK(UniReplicateGen
);
19 #define DPRINTF(format, args...) fprintf(stderr, format ,##args);
21 #define DPRINTF if (0) printf
25 static IUniConfGen
*creator(WvStringParm s
, IObject
*_obj
)
29 DPRINTF("encoded_monikers = %s\n", s
.cstr());
30 WvStringList monikers
;
31 wvtcl_decode(monikers
, s
);
32 DPRINTF("monikers = %s\n", monikers
.join(",").cstr());
34 WvStringList::Iter
i(monikers
);
35 for (i
.rewind(); i
.next(); )
37 if (_obj
) _obj
->addRef();
38 IUniConfGen
*gen
= wvcreate
<IUniConfGen
>(*i
, _obj
);
40 gens
.append(gen
, false);
42 if (_obj
) _obj
->release();
44 return new UniReplicateGen(gens
);
47 static WvMoniker
<IUniConfGen
> reg("replicate", creator
);
50 /***** UniReplicateGen *****/
52 UniReplicateGen::UniReplicateGen() : processing_callback(false)
57 UniReplicateGen::UniReplicateGen(const IUniConfGenList
&_gens
,
58 bool auto_free
) : processing_callback(false)
60 IUniConfGenList::Iter
i(_gens
);
62 for (i
.rewind(); i
.next(); )
64 Gen
*gen
= new Gen(i
.ptr(), auto_free
);
67 gens
.append(gen
, true);
68 gen
->gen
->add_callback(this,
69 wv::bind(&UniReplicateGen::deltacallback
,
78 UniReplicateGen::~UniReplicateGen()
80 GenList::Iter
i(gens
);
81 for (i
.rewind(); i
.next(); )
82 i
->gen
->del_callback(this);
86 void UniReplicateGen::prepend(IUniConfGen
*_gen
, bool auto_free
)
88 Gen
*gen
= new Gen(_gen
, auto_free
);
91 gens
.prepend(gen
, true);
92 gen
->gen
->add_callback(this, wv::bind(&UniReplicateGen::deltacallback
,
100 void UniReplicateGen::append(IUniConfGen
*_gen
, bool auto_free
)
102 Gen
*gen
= new Gen(_gen
, auto_free
);
105 gens
.append(gen
, true);
106 gen
->gen
->add_callback(this, wv::bind(&UniReplicateGen::deltacallback
,
114 bool UniReplicateGen::isok()
116 return first_ok() != NULL
;
120 bool UniReplicateGen::refresh()
124 replicate_if_any_have_become_ok();
126 GenList::Iter
i(gens
);
127 for (i
.rewind(); i
.next(); )
129 if (!i
->gen
->refresh())
137 void UniReplicateGen::commit()
139 replicate_if_any_have_become_ok();
141 GenList::Iter
i(gens
);
142 for (i
.rewind(); i
.next(); )
149 void UniReplicateGen::deltacallback(Gen
*src_gen
, const UniConfKey
&key
,
152 DPRINTF("UniReplicateGen::deltacallback(%s, %s)\n",
153 key
.printable().cstr(), value
.cstr());
155 if (!processing_callback
)
157 DPRINTF("UniReplicateGen::deltacallback(): !processing_callback\n");
159 processing_callback
= true;
161 GenList::Iter
j(gens
);
162 for (j
.rewind(); j
.next(); )
167 if (j
.ptr() != src_gen
)
169 DPRINTF("UniReplicateGen::deltacallback: %p->set(%s, %s)\n",
170 j
.ptr(), key
.printable().cstr(), value
.cstr());
171 j
->gen
->set(key
, value
);
177 processing_callback
= false;
181 DPRINTF("UniReplicateGen::deltacallback(): processing_callback\n");
186 void UniReplicateGen::set(const UniConfKey
&key
, WvStringParm value
)
188 DPRINTF("UniReplicateGen::set(%s, %s)\n",
189 key
.printable().cstr(), value
.cstr());
191 replicate_if_any_have_become_ok();
193 Gen
*first
= first_ok();
195 first
->gen
->set(key
, value
);
197 DPRINTF("UniReplicateGen::set: first == NULL\n");
201 void UniReplicateGen::setv(const UniConfPairList
&pairs
)
203 DPRINTF("UniReplicateGen::setv\n");
205 replicate_if_any_have_become_ok();
207 Gen
*first
= first_ok();
209 first
->gen
->setv(pairs
);
211 DPRINTF("UniReplicateGen::setv: first == NULL\n");
215 WvString
UniReplicateGen::get(const UniConfKey
&key
)
219 replicate_if_any_have_become_ok();
221 Gen
*first
= first_ok();
224 WvString result
= first
->gen
->get(key
);
226 // It's possible that first has become !isok(); we must
227 // take care of this case carefully
228 if (!result
&& !first
->isok())
230 Gen
*new_first
= first_ok();
231 if (new_first
== first
)
239 return WvString::null
;
244 UniConfGen::Iter
*UniReplicateGen::iterator(const UniConfKey
&key
)
246 replicate_if_any_have_become_ok();
248 Gen
*first
= first_ok();
250 return first
->gen
->iterator(key
);
256 UniReplicateGen::Gen
*UniReplicateGen::first_ok() const
258 GenList::Iter
j(gens
);
259 for (j
.rewind(); j
.next(); )
269 void UniReplicateGen::replicate(const UniConfKey
&key
)
271 DPRINTF("UniReplicateGen::replicate(%s)\n", key
.printable().cstr());
275 Gen
*first
= first_ok();
277 GenList::Iter
j(gens
);
278 for (j
.rewind(); j
.next(); )
280 DPRINTF("UniReplicateGen::replicate: %p\n", j
.ptr());
284 DPRINTF("UniReplicateGen::replicate: !isok()\n");
288 UniConfGen::Iter
*i
= j
->gen
->recursiveiterator(key
);
291 DPRINTF("UniReplicateGen::replicate: no iterator\n");
295 for (i
->rewind(); i
->next(); )
297 DPRINTF("UniReplicateGen::replicate: key=%s, value=%s\n",
298 i
->key().printable().cstr(), i
->value().cstr());
300 if (j
.ptr() == first
)
302 DPRINTF("UniReplicateGen::replicate: deltacallback()\n");
303 deltacallback(first
, i
->key(), i
->value());
307 if (!first
->gen
->exists(i
->key()))
309 DPRINTF("UniReplicateGen::replicate: !exists()\n");
310 first
->gen
->set(i
->key(), i
->value());
314 DPRINTF("UniReplicateGen::replicate: exists()\n");
324 DPRINTF("UniReplicateGen::replicate: done\n");
327 void UniReplicateGen::replicate_if_any_have_become_ok()
329 bool should_replicate
= false;
331 GenList::Iter
j(gens
);
332 for (j
.rewind(); j
.next(); )
334 if (!j
->was_ok
&& j
->gen
->isok())
338 should_replicate
= true;
342 if (should_replicate
)
344 DPRINTF("UniReplicateGen::replicate_if_any_have_become_ok: replicating\n");