00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "VestaAttribs.H"
00026 #include "VestaAttribsRep.H"
00027 #include "CharsKey.H"
00028 #include "VestaLog.H"
00029 #include "VRConcurrency.H"
00030 #include "VLogHelp.H"
00031 #include "logging.H"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 typedef Table<CharsKey, bool>::Default CharsTable;
00057
00058 VestaAttribsRep*
00059 VestaAttribsRep::create(VestaSource::attribOp op, const char* name,
00060 const char* value, time_t timestamp) throw ()
00061 {
00062 int nameLen = strlen(name);
00063 int valueLen = strlen(value);
00064 VestaAttribsRep* ar = (VestaAttribsRep*)
00065 VMemPool::allocate(VMemPool::vAttrib,
00066 VATTR_MINSIZE + nameLen + valueLen);
00067 ar->setOp(op);
00068 ar->setNext(0);
00069 Bit32 tt = (Bit32) timestamp;
00070 memcpy(&ar->rep[VATTR_TIMESTAMP], &tt, 4);
00071 strcpy((char*) &ar->rep[VATTR_NAME], name);
00072 strcpy((char*) &ar->rep[VATTR_NAME + nameLen + 1], value);
00073 return ar;
00074 }
00075
00076
00077 Bit32
00078 VestaAttribs::firstAttrib() throw ()
00079 {
00080 if (attribs == NULL) return 0;
00081 Bit32 firstsp;
00082 memcpy(&firstsp, attribs, sizeof(Bit32));
00083 return firstsp;
00084 }
00085
00086 void
00087 VestaAttribs::setFirstAttrib(Bit32 newval) throw ()
00088 {
00089 Bit32 firstsp;
00090 memcpy(attribs, &newval, sizeof(Bit32));
00091 }
00092
00093 bool
00094 VestaAttribs::inAttribs(const char* name, const char* value)
00095 throw (SRPC::failure )
00096 {
00097
00098 VestaAttribsRep* cur =
00099 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00100 while (cur) {
00101 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00102 if (strcmp(cur->name(), name) == 0) {
00103 switch (cur->op()) {
00104 case opSet:
00105 if (strcmp(cur->value(), value) == 0) {
00106
00107 return true;
00108 } else {
00109
00110 return false;
00111 }
00112 case opClear:
00113
00114 return false;
00115 case opAdd:
00116 if (strcmp(cur->value(), value) == 0) {
00117
00118 return true;
00119 }
00120 break;
00121 case opRemove:
00122 if (strcmp(cur->value(), value) == 0) {
00123
00124 return false;
00125 }
00126 break;
00127 }
00128 }
00129 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00130 }
00131
00132 return false;
00133 }
00134
00135 const char*
00136 VestaAttribs::getAttribConst(const char* name) throw ()
00137 {
00138 VestaAttribsRep* cur =
00139 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00140 while (cur) {
00141 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00142 if (strcmp(cur->name(), name) == 0) {
00143 switch (cur->op()) {
00144 case opSet:
00145
00146
00147
00148
00149
00150
00151 return cur->value();
00152 case opClear:
00153
00154 return NULL;
00155 case opAdd:
00156
00157
00158
00159
00160
00161
00162 return cur->value();
00163 case opRemove:
00164
00165 break;
00166 }
00167 }
00168 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00169 }
00170
00171 return NULL;
00172 }
00173
00174 char*
00175 VestaAttribs::getAttrib(const char* name)
00176 throw (SRPC::failure )
00177 {
00178 const char* value = getAttribConst(name);
00179 if (value == NULL) return NULL;
00180 return strdup(value);
00181 }
00182
00183 void
00184 VestaAttribs::getAttrib(const char* name,
00185 VestaAttribs::valueCallback cb, void* cl)
00186 {
00187 VestaAttribsRep* cur =
00188 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00189 bool cont = true;
00190 while (cur && cont) {
00191 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00192 if (strcmp(cur->name(), name) == 0) {
00193 switch (cur->op()) {
00194 case opSet:
00195
00196
00197
00198
00199
00200
00201
00202 cont = cb(cl, cur->value());
00203 return;
00204 case opClear:
00205
00206 return;
00207 case opAdd:
00208
00209
00210
00211
00212
00213
00214 cont = cb(cl, cur->value());
00215 break;
00216 case opRemove:
00217
00218 break;
00219 }
00220 }
00221 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00222 }
00223 }
00224
00225 void
00226 VestaAttribs::listAttribs(VestaAttribs::valueCallback cb, void* cl)
00227 {
00228 CharsTable listed;
00229 CharsKey k;
00230 bool v;
00231 VestaAttribsRep* cur =
00232 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00233 bool cont = true;
00234 while (cur && cont) {
00235 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00236 switch (cur->op()) {
00237 case opSet:
00238 case opAdd:
00239
00240
00241
00242 k.s = cur->name();
00243 if (!listed.Get(k, v)) {
00244 cont = cb(cl, k.s);
00245 listed.Put(k, true);
00246 }
00247 break;
00248 case opClear:
00249 case opRemove:
00250
00251 break;
00252 }
00253 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00254 }
00255 }
00256
00257 void
00258 VestaAttribs::getAttribHistory(VestaAttribs::historyCallback cb, void* cl)
00259 {
00260 VestaAttribsRep* cur =
00261 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00262 bool cont = true;
00263 while (cur && cont) {
00264 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00265 attribOp curop = cur->op();
00266 cont = cb(cl, curop, cur->name(), cur->value(), cur->timestamp());
00267 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00268 }
00269 }
00270
00271 static int
00272 compareWrite(VestaAttribs::attribOp o1,
00273 const char* n1, const char* v1, time_t t1,
00274 VestaAttribs::attribOp o2,
00275 const char* n2, const char* v2, time_t t2)
00276 {
00277 if (t1 > t2) return 1;
00278 if (t1 < t2) return -1;
00279 int nc = strcmp(n1, n2);
00280 if (nc != 0) return nc;
00281 nc = strcmp(v1, v2);
00282 if (nc != 0) return nc;
00283
00284
00285 if (((int) o1) > ((int) o2)) return 1;
00286 if (((int) o1) < ((int) o2)) return -1;
00287 return 0;
00288 }
00289
00290
00291
00292 static time_t new_timestamp(VestaAttribsRep* first,
00293 VestaAttribs::attribOp op,
00294 const char* name, const char* value)
00295 {
00296 time_t result = time(NULL);
00297 if(first == 0) return result;
00298 if(compareWrite(op, name, value, result,
00299 first->op(), first->name(),
00300 first->value(), first->timestamp()) < 1)
00301 {
00302
00303
00304 result = first->timestamp() + 1;
00305 }
00306 return result;
00307 }
00308
00309
00310
00311
00312
00313 VestaSource::errorCode
00314 VestaAttribs::writeAttrib(VestaAttribs::attribOp op, const char* name,
00315 const char* value, time_t ×tamp) throw ()
00316 {
00317 if (!hasAttribs()) return VestaSource::invalidArgs;
00318
00319 VestaAttribsRep* prev = NULL;
00320 VestaAttribsRep* cur =
00321 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00322
00323 if (timestamp == 0) {
00324 timestamp = new_timestamp(cur, op, name, value);
00325 }
00326
00327 while (cur != NULL) {
00328 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00329 int cw = compareWrite(op, name, value, timestamp,
00330 cur->op(), cur->name(),
00331 cur->value(), cur->timestamp());
00332 if (cw == 1) {
00333 break;
00334 } else if (cw == 0) {
00335
00336 return VestaSource::nameInUse;
00337 }
00338
00339 if (strcmp(name, cur->name()) == 0) {
00340 switch (cur->op()) {
00341 case opSet:
00342 case opClear:
00343
00344 return VestaSource::ok;
00345 case opAdd:
00346 case opRemove:
00347 if (strcmp(value, cur->value()) == 0) {
00348 switch (op) {
00349 case opAdd:
00350 case opRemove:
00351
00352 return VestaSource::ok;
00353 case opSet:
00354
00355
00356
00357
00358
00359
00360 op = opClear;
00361 break;
00362 case opClear:
00363 break;
00364 }
00365 }
00366 break;
00367 }
00368 }
00369 prev = cur;
00370 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00371 }
00372
00373
00374
00375
00376 VestaAttribsRep* wr =
00377 VestaAttribsRep::create(op, name, value, timestamp);
00378 if (prev == NULL) {
00379 wr->setNext(firstAttrib());
00380 setFirstAttrib(VMemPool::shortenPointer(wr));
00381 } else {
00382 wr->setNext(prev->next());
00383 prev->setNext(VMemPool::shortenPointer(wr));
00384 }
00385
00386
00387 prev = wr;
00388 if (op == opSet || op == opClear) {
00389 while (cur != NULL) {
00390 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00391 if (strcmp(name, cur->name()) == 0) {
00392
00393 prev->setNext(cur->next());
00394 attribOp curop = cur->op();
00395 VMemPool::free(cur, VATTR_MINSIZE + strlen(cur->name())
00396 + strlen(cur->value()),
00397 VMemPool::vAttrib);
00398 cur = prev;
00399
00400 switch (curop) {
00401 case opAdd:
00402 case opRemove:
00403 break;
00404 case opSet:
00405 case opClear:
00406 return VestaSource::ok;
00407 }
00408 }
00409 prev = cur;
00410 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00411 }
00412 } else {
00413 while (cur != NULL) {
00414 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00415 if (strcmp(name, cur->name()) == 0) {
00416 switch (cur->op()) {
00417 case opAdd:
00418 case opRemove:
00419 if (strcmp(cur->value(), value) == 0) {
00420
00421 prev->setNext(cur->next());
00422 VMemPool::free(cur, VATTR_MINSIZE + strlen(cur->name())
00423 + strlen(cur->value()),
00424 VMemPool::vAttrib);
00425
00426 return VestaSource::ok;
00427 }
00428 break;
00429 case opSet:
00430 if (strcmp(cur->value(), value) == 0) {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 cur->setOp(opClear);
00443 }
00444
00445 return VestaSource::ok;
00446 case opClear:
00447
00448 return VestaSource::ok;
00449 }
00450 }
00451 prev = cur;
00452 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00453 }
00454 }
00455 return VestaSource::ok;
00456 }
00457
00458
00459
00460 bool
00461 VestaAttribs::wouldWriteAttrib(VestaAttribs::attribOp op, const char* name,
00462 const char* value, time_t ×tamp) throw ()
00463 {
00464 if (!hasAttribs()) return false;
00465
00466 VestaAttribsRep* prev = NULL;
00467 VestaAttribsRep* cur =
00468 (VestaAttribsRep*) VMemPool::lengthenPointer(firstAttrib());
00469
00470 if (timestamp == 0) {
00471 timestamp = new_timestamp(cur, op, name, value);
00472 }
00473
00474 while (cur != NULL) {
00475 assert(VMemPool::type(cur) == VMemPool::vAttrib);
00476 int cw = compareWrite(op, name, value, timestamp,
00477 cur->op(), cur->name(),
00478 cur->value(), cur->timestamp());
00479 if (cw == 1) {
00480 break;
00481 } else if (cw == 0) {
00482
00483 return false;
00484 }
00485
00486 if (strcmp(name, cur->name()) == 0) {
00487 switch (cur->op()) {
00488 case opSet:
00489 case opClear:
00490
00491 return false;
00492 case opAdd:
00493 case opRemove:
00494 if (strcmp(value, cur->value()) == 0) {
00495 switch (op) {
00496 case opAdd:
00497 case opRemove:
00498
00499 return false;
00500 case opSet:
00501
00502
00503
00504
00505
00506
00507 op = opClear;
00508 break;
00509 case opClear:
00510 break;
00511 }
00512 }
00513 break;
00514 }
00515 }
00516 prev = cur;
00517 cur = (VestaAttribsRep*) VMemPool::lengthenPointer(cur->next());
00518 }
00519 return true;
00520 }
00521
00522 Bit32
00523 VestaAttribs::copyAttribs(Bit32 from) throw ()
00524 {
00525 if (from == 0) return 0;
00526 VestaAttribsRep* fromp =
00527 (VestaAttribsRep*) VMemPool::lengthenPointer(from);
00528 assert(VMemPool::type(fromp) == VMemPool::vAttrib);
00529 VestaAttribsRep* first =
00530 VestaAttribsRep::create(fromp->op(), fromp->name(),
00531 fromp->value(), fromp->timestamp());
00532 VestaAttribsRep* prev = first;
00533 VestaAttribsRep* cur;
00534
00535 from = fromp->next();
00536 while (from != 0) {
00537 fromp = (VestaAttribsRep*) VMemPool::lengthenPointer(from);
00538 assert(VMemPool::type(fromp) == VMemPool::vAttrib);
00539 cur = VestaAttribsRep::create(fromp->op(), fromp->name(),
00540 fromp->value(), fromp->timestamp());
00541 prev->setNext(VMemPool::shortenPointer(cur));
00542 prev = cur;
00543 from = fromp->next();
00544 }
00545 return VMemPool::shortenPointer(first);
00546 }
00547
00548
00549 void
00550 VestaAttribsRep::mark() throw ()
00551 {
00552 VestaAttribsRep* ar = this;
00553 while (ar != NULL) {
00554 assert(VMemPool::type(ar) == VMemPool::vAttrib);
00555 ar->setVisited(true);
00556 ar = (VestaAttribsRep*) VMemPool::lengthenPointer(ar->next());
00557 }
00558 }
00559
00560
00561 void
00562 VestaAttribsRep::markCallback(void* closure, VMemPool::typeCode type)
00563 throw ()
00564 {
00565
00566
00567
00568 VestaAttribsRep* ar;
00569 ar = (VestaAttribsRep*)
00570 VMemPool::lengthenPointer(VestaSource::repositoryRoot()->firstAttrib());
00571 if (ar) ar->mark();
00572 ar = (VestaAttribsRep*)
00573 VMemPool::lengthenPointer(VestaSource::mutableRoot()->firstAttrib());
00574 if (ar) ar->mark();
00575 ar = (VestaAttribsRep*)
00576 VMemPool::lengthenPointer(VestaSource::volatileRoot()->firstAttrib());
00577 if (ar) ar->mark();
00578 }
00579
00580
00581 bool
00582 VestaAttribsRep::sweepCallback(void* closure, VMemPool::typeCode type,
00583 void* addr, Bit32& size) throw ()
00584 {
00585 VestaAttribsRep* ar = (VestaAttribsRep*) addr;
00586 int namelen = strlen(ar->name());
00587 size = VATTR_MINSIZE + namelen + strlen(ar->value(namelen));
00588 bool ret = ar->visited();
00589 ar->setVisited(false);
00590 return ret;
00591 }
00592
00593 void
00594 VestaAttribsRep::rebuildCallback(void* closure, VMemPool::typeCode type,
00595 void* addr, Bit32& size) throw ()
00596 {
00597
00598 VestaAttribsRep* ar = (VestaAttribsRep*) addr;
00599 int namelen = strlen(ar->name());
00600 size = VATTR_MINSIZE + namelen + strlen(ar->value(namelen));
00601 }
00602
00603 Bit32
00604 VestaAttribsRep::checkpoint(Bit32& nextSP, std::fstream& ckpt) throw ()
00605 {
00606 if (visited()) return next();
00607
00608 VestaAttribsRep *ar = this, *ar_next;
00609 while (ar != NULL) {
00610 assert(VMemPool::type(ar) == VMemPool::vAttrib);
00611 int namelen = strlen(ar->name());
00612 int size = VATTR_MINSIZE + namelen + strlen(ar->value(namelen));
00613 int pad = ((-size) & VMemPool::alignmentMask);
00614 Bit32 newSP = nextSP;
00615 nextSP += size + pad;
00616 Bit32 oldNextSP = ar->next();
00617 if (oldNextSP != 0)
00618 {
00619 ar_next =
00620 (VestaAttribsRep*) VMemPool::lengthenPointer(oldNextSP);
00621
00622
00623 if(ar_next->visited())
00624 {
00625
00626
00627
00628 Bit32 next_new_SP = ar_next->next();
00629 ar->setNext(next_new_SP);
00630 Repos::dprintf(DBG_ALWAYS,
00631 "WARNING: multiply referenced attribute chain; "
00632 "post-checkpoint short pointer = 0x%x\n",
00633 next_new_SP);
00634
00635
00636 ar_next = 0;
00637 }
00638 else
00639
00640
00641 ar->setNext(nextSP);
00642 }
00643 else
00644 ar_next = 0;
00645
00646 ckpt.write((char *) ar->rep, size);
00647 while (pad--) {
00648 ckpt.put(VMemPool::freeByte);
00649 }
00650 ar->setVisited(true);
00651 ar->setNext(newSP);
00652 ar = ar_next;
00653 }
00654 return next();
00655 }