00001
00002
00003
00004
00005
00006
00007
#include "unimounttreegen.h"
00008
#include "wvmoniker.h"
00009
00010
00011
00012 UniMountTreeGen::UniMountTreeGen()
00013 {
00014 mounts =
new UniMountTree(NULL, UniConfKey::EMPTY);
00015 }
00016
00017
00018 UniMountTreeGen::~UniMountTreeGen()
00019 {
00020
00021
delete mounts;
00022 }
00023
00024
00025 WvString UniMountTreeGen::get(
const UniConfKey &key)
00026 {
00027
00028
hold_delta();
00029
UniMountTree::GenIter it(*mounts, key);
00030
for (it.
rewind(); it.
next(); )
00031 {
00032
UniConfGen *gen = it.
ptr();
00033
WvString result = gen->
get(it.
tail());
00034
if (!result.
isnull())
00035 {
00036
unhold_delta();
00037
return result;
00038 }
00039 }
00040
unhold_delta();
00041
00042
00043
UniMountTree *node = mounts->
find(key);
00044
if (node)
00045
return "";
00046
00047
00048
return WvString::null;
00049 }
00050
00051
00052 void UniMountTreeGen::set(
const UniConfKey &key,
WvStringParm value)
00053 {
00054
00055
UniConfKey mountpoint;
00056
UniConfGen *provider =
whichmount(key, &mountpoint);
00057
if (provider)
00058 provider->
set(mountpoint, value);
00059 }
00060
00061
00062 bool UniMountTreeGen::exists(
const UniConfKey &key)
00063 {
00064
00065
UniMountTree *node = mounts->
find(key);
00066
if (node)
00067
return true;
00068
00069
00070
hold_delta();
00071
UniMountTree::GenIter it(*mounts, key);
00072
for (it.
rewind(); it.
next(); )
00073 {
00074
UniConfGen *gen = it.
ptr();
00075
if (gen->
exists(it.
tail()))
00076 {
00077
unhold_delta();
00078
return true;
00079 }
00080 }
00081
unhold_delta();
00082
00083
00084
return false;
00085 }
00086
00087
00088 bool UniMountTreeGen::haschildren(
const UniConfKey &key)
00089 {
00090
hold_delta();
00091
UniMountTree *node = mounts->
find(key);
00092
bool result = node && node->
haschildren();
00093
if (! result)
00094 {
00095
UniMountTree::GenIter it(*mounts, key);
00096
for (it.
rewind(); it.
next(); )
00097 {
00098
UniConfGen *gen = it.
ptr();
00099
if (gen->
haschildren(it.
tail()))
00100 {
00101 result =
true;
00102
break;
00103 }
00104 }
00105 }
00106
unhold_delta();
00107
return result;
00108 }
00109
00110
00111 bool UniMountTreeGen::refresh()
00112 {
00113
hold_delta();
00114
bool result =
true;
00115
00116 UniConfGenList::Iter i(mounts->
generators);
00117
for (i.rewind(); i.next();)
00118 result = result && i->refresh();
00119
00120
unhold_delta();
00121
return result;
00122 }
00123
00124
00125 void UniMountTreeGen::commit()
00126 {
00127
hold_delta();
00128
00129 UniConfGenList::Iter i(mounts->
generators);
00130
for (i.rewind(); i.next();)
00131 i->commit();
00132
00133
unhold_delta();
00134 }
00135
00136
00137 UniConfGen *
UniMountTreeGen::mount(
const UniConfKey &key,
00138
WvStringParm moniker,
bool refresh)
00139 {
00140
UniConfGen *gen = wvcreate<UniConfGen>(moniker);
00141
if (gen)
00142
mountgen(key, gen, refresh);
00143 assert(gen &&
"Moniker doesn't get us a generator!");
00144
return gen;
00145 }
00146
00147
00148 UniConfGen *
UniMountTreeGen::mountgen(
const UniConfKey &key,
00149
UniConfGen *gen,
bool refresh)
00150 {
00151
UniMountTree *node = mounts->
findormake(key);
00152 node->
generators.append(gen,
true);
00153
00154
hold_delta();
00155
00156 gen->
setcallback(
UniConfGenCallback(
this,
00157 &UniMountTreeGen::gencallback), node);
00158
if (gen && refresh)
00159 gen->
refresh();
00160
00161
unhold_delta();
00162
return gen;
00163 }
00164
00165
00166 void UniMountTreeGen::unmount(
const UniConfKey &key,
00167
UniConfGen *gen,
bool commit)
00168 {
00169
UniMountTree *node = mounts->
find(key);
00170
if (!node)
00171
return;
00172
00173 UniConfGenList::Iter genit(node->
generators);
00174
if (! genit.find(gen))
00175
return;
00176
00177
hold_delta();
00178
00179
if (commit)
00180 gen->
commit();
00181 gen->
setcallback(
UniConfGenCallback(), NULL);
00182
00183 node->
generators.unlink(gen);
00184
00185
unhold_delta();
00186 }
00187
00188
00189 UniConfGen *
UniMountTreeGen::whichmount(
const UniConfKey &key,
00190
UniConfKey *mountpoint)
00191 {
00192
hold_delta();
00193
00194
00195
UniMountTree::GenIter it(*mounts, key);
00196
for (it.
rewind(); it.
next(); )
00197 {
00198
UniConfGen *gen = it.
ptr();
00199
if (gen->
exists(it.
tail()))
00200
goto found;
00201 }
00202
00203 it.
rewind();
00204
if (! it.
next())
00205 {
00206
unhold_delta();
00207
return NULL;
00208 }
00209
00210 found:
00211
if (mountpoint)
00212 *mountpoint = it.
tail();
00213
unhold_delta();
00214
return it.
ptr();
00215 }
00216
00217
00218 bool UniMountTreeGen::ismountpoint(
const UniConfKey &key)
00219 {
00220
UniMountTree *node = mounts->
find(key);
00221
return node && ! node->
generators.isempty();
00222 }
00223
00224
00225 UniMountTreeGen::Iter *
UniMountTreeGen::iterator(
const UniConfKey &key)
00226 {
00227
return new KeyIter(*
this, key);
00228 }
00229
00230
00231
void UniMountTreeGen::prune(
UniMountTree *node)
00232 {
00233
while (node != mounts && !node->
isessential())
00234 {
00235
UniMountTree *next = node->
parent();
00236
delete node;
00237 node = next;
00238 }
00239 }
00240
00241
00242
void UniMountTreeGen::gencallback(
const UniConfKey &key,
WvStringParm value,
00243
void *userdata)
00244 {
00245
UniMountTree *node = static_cast<UniMountTree*>(userdata);
00246
delta(
UniConfKey(node->
fullkey(), key), value);
00247 }
00248
00249
00250
00251
00252
00253 UniMountTreeGen::KeyIter::KeyIter(
UniMountTreeGen &root,
const UniConfKey &key)
00254 : xroot(&root), xkey(key), genit(*root.mounts, key),
00255 hack(71), hackit(hack)
00256 {
00257 }
00258
00259
00260 void UniMountTreeGen::KeyIter::rewind()
00261 {
00262 xroot->
hold_delta();
00263 hack.zap();
00264
00265
00266
00267
00268
UniMountTree *node = xroot->
mounts->
find(xkey);
00269
if (node)
00270 {
00271 UniMountTree::Iter nodeit(*node);
00272
for (nodeit.rewind(); nodeit.next(); )
00273 hack.add(
new WvString(nodeit->key()),
true);
00274 }
00275
00276
00277
00278
for (genit.
rewind(); genit.
next(); )
00279 {
00280
UniConfGen *gen = genit.
ptr();
00281
UniConfGen::Iter *keyit = gen->
iterator(genit.
tail());
00282
for (keyit->
rewind(); keyit->
next(); )
00283 hack.add(
new WvString(keyit->
key()),
true);
00284
delete keyit;
00285 }
00286
00287 hackit.rewind();
00288 xroot->
unhold_delta();
00289 }
00290
00291
00292 bool UniMountTreeGen::KeyIter::next()
00293 {
00294
return hackit.next();
00295 }
00296
00297
00298 UniConfKey UniMountTreeGen::KeyIter::key()
const
00299
{
00300
return UniConfKey(hackit());
00301 }
00302
00303
00304
00305
00306
00307 UniMountTree::UniMountTree(
UniMountTree *parent,
00308
const UniConfKey &key) :
00309
UniConfTree<
UniMountTree>(parent, key)
00310 {
00311 }
00312
00313
00314 UniMountTree::~UniMountTree()
00315 {
00316 }
00317
00318
00319 UniMountTree *
UniMountTree::findnearest(
const UniConfKey &key,
00320
int &split)
00321 {
00322 split = 0;
00323
UniMountTree *node =
this;
00324
UniConfKey::Iter it(key);
00325
for (it.
rewind(); it.
next(); split++)
00326 {
00327
UniMountTree *next = node->
findchild(it());
00328
if (!next)
00329
break;
00330 node = next;
00331 }
00332
return node;
00333 }
00334
00335
00336 UniMountTree *
UniMountTree::findormake(
const UniConfKey &key)
00337 {
00338
UniMountTree *node =
this;
00339
UniConfKey::Iter it(key);
00340
for (it.
rewind(); it.
next(); )
00341 {
00342
UniMountTree *prev = node;
00343 node = prev->
findchild(it());
00344
if (!node)
00345 node =
new UniMountTree(prev, it());
00346 }
00347
return node;
00348 }
00349
00350
00351
00352
00353
00354 UniMountTree::MountIter::MountIter(
UniMountTree &root,
00355
const UniConfKey &key)
00356 : xkey(key)
00357 {
00358 bestnode = root.
findnearest(key, bestsplit);
00359 }
00360
00361
00362 void UniMountTree::MountIter::rewind()
00363 {
00364 xnode = NULL;
00365 }
00366
00367
00368 bool UniMountTree::MountIter::next()
00369 {
00370
if (! xnode)
00371 {
00372 xsplit = bestsplit;
00373 xnode = bestnode;
00374 }
00375
else if (xsplit != 0)
00376 {
00377 xsplit -= 1;
00378 xnode = xnode->
parent();
00379 }
00380
else
00381
return false;
00382
return true;
00383 }
00384
00385
00386
00387
00388
00389 UniMountTree::GenIter::GenIter(
UniMountTree &root,
00390
const UniConfKey &key) :
00391
UniMountTree::
MountIter(root, key),
00392 genit(NULL)
00393 {
00394 }
00395
00396
00397 UniMountTree::GenIter::~GenIter()
00398 {
00399
delete genit;
00400 }
00401
00402
00403 void UniMountTree::GenIter::rewind()
00404 {
00405
if (genit)
00406 {
00407
delete genit;
00408 genit = NULL;
00409 }
00410
UniMountTree::MountIter::rewind();
00411 }
00412
00413
00414 bool UniMountTree::GenIter::next()
00415 {
00416
for (;;)
00417 {
00418
if (genit && genit->next())
00419
return true;
00420
if (!
UniMountTree::MountIter::next())
00421
return false;
00422
00423 genit =
new UniConfGenList::Iter(
node()->generators);
00424 genit->rewind();
00425 }
00426
return false;
00427 }