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 <assert.h>
00026 #include <iostream>
00027 #include <iomanip>
00028 #include "VestaSource.H"
00029 #include "VDirChangeable.H"
00030 #include "VDirVolatileRoot.H"
00031 #include "VDirEvaluator.H"
00032 #include "VForward.H"
00033 #include "SourceOrDerived.H"
00034 #include "Recovery.H"
00035 #include "VRWeed.H"
00036 #include "VRConcurrency.H"
00037 #include "VestaConfig.H"
00038 #include "VLeaf.H"
00039 #include "DirShortId.H"
00040 #include "FdCache.H"
00041 #include "VLogHelp.H"
00042 #include "FPShortId.H"
00043 #include "logging.H"
00044 #include "UniqueId.H"
00045 #include "VestaSourceImpl.H"
00046 #include "CopyShortId.H"
00047 #include "MutableSidref.H"
00048
00049 #include "timing.H"
00050 #include "lock_timing.H"
00051
00052 #include <BufStream.H>
00053 #include <FdStream.H>
00054
00055 using std::cerr;
00056 using std::endl;
00057 using std::fstream;
00058 using Basics::OBufStream;
00059
00060
00061 VestaLog VRLog;
00062 int VRLogVersion = 1;
00063 static const int LogMaxVersion = 3;
00064
00065 ReadersWritersLock StableLock(true);
00066 ReadersWritersLock VolatileRootLock(true);
00067
00068
00069 static VestaSource* repositoryRoot;
00070 static VestaSource* mutableRoot;
00071 static VDirVolatileRoot* volatileRoot;
00072 static Bit32 repositoryRootAttribsRep = 0;
00073 static Bit32 mutableRootAttribsRep = 0;
00074 static Bit32 volatileRootAttribsRep = 0;
00075 static Bit32 emptyAttribsRep = 0;
00076
00077
00078
00079
00080 const FP::Tag contentsFPTag("TextD");
00081 const FP::Tag executableFPTag("TextX");
00082 const FP::Tag pathnameFPTag("(PATHNAME)/vesta");
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 bool VestaSource::doLogging = false;
00106
00107
00108
00109
00110 VestaSource*
00111 LongId::lookup(LongId::lockKindTag lockKind, ReadersWritersLock** lock)
00112 throw (SRPC::failure )
00113 {
00114 VestaSource* vs;
00115 VestaSource* child;
00116 const Bit8* next = &value.byte[0];
00117 int kind;
00118 if (*next == 0) {
00119 kind = next[1];
00120 switch (kind) {
00121 case 0:
00122
00123 vs = VestaSource::repositoryRoot(lockKind, lock);
00124 if (vs == NULL) return NULL;
00125 break;
00126 case 1:
00127
00128 vs = VestaSource::mutableRoot(lockKind, lock);
00129 if (vs == NULL) return NULL;
00130 next += 2;
00131 break;
00132 case 2:
00133
00134 if (next[2] == 0) {
00135
00136 vs = VestaSource::volatileRoot(lockKind, lock);
00137 } else {
00138 ReadersWritersLock* dummy;
00139
00140 switch (lockKind) {
00141 case LongId::writeLock:
00142 case LongId::readLock:
00143
00144
00145
00146
00147
00148 vs = VestaSource::volatileRoot(LongId::readLock, &dummy);
00149 RWLOCK_LOCKED_REASON(dummy, "LongId::lookup below volatile");
00150 break;
00151 case LongId::writeLockV:
00152 case LongId::readLockV:
00153 case LongId::checkLock:
00154 case LongId::noLock:
00155
00156 vs = VestaSource::volatileRoot(LongId::noLock);
00157 break;
00158 }
00159 }
00160 if (vs == NULL) return NULL;
00161 next += 2;
00162 break;
00163 case 3:
00164
00165
00166 vs = VestaSource::repositoryRoot(lockKind, lock);
00167 if (vs == NULL) return NULL;
00168 next += 2;
00169 break;
00170 case 4:
00171
00172
00173 vs = NULL;
00174 if (lockKind == LongId::readLock ||
00175 lockKind == LongId::writeLock ||
00176 lockKind == LongId::readLockV ||
00177 lockKind == LongId::writeLockV) {
00178 *lock = NULL;
00179 }
00180 next += 2;
00181
00182 break;
00183 case 255:
00184
00185 default:
00186 if (lockKind == LongId::readLock ||
00187 lockKind == LongId::writeLock ||
00188 lockKind == LongId::readLockV ||
00189 lockKind == LongId::writeLockV) {
00190 *lock = NULL;
00191 }
00192 return NULL;
00193 }
00194 } else {
00195
00196 kind = 0;
00197 vs = VestaSource::repositoryRoot(lockKind, lock);
00198 if (vs == NULL) return NULL;
00199 }
00200 for (;;) {
00201
00202 unsigned int index = 0;
00203 int shift = 0;
00204 while (next < &value.byte[sizeof(value)]) {
00205 index |= (*next & 0x7f) << shift;
00206 shift += 7;
00207 if ((*next++ & 0x80) == 0) break;
00208 }
00209 if (index == 0) break;
00210 VestaSource::errorCode err;
00211 switch (kind) {
00212 default:
00213 err = vs->lookupIndex(index, child, NULL);
00214 break;
00215
00216 case 2:
00217
00218 RECORD_TIME_POINT;
00219 err = ((VDirVolatileRoot*)vs)->
00220 lookupIndexAndLock(index, child, lockKind, lock);
00221 RECORD_TIME_POINT;
00222 if (lockKind == LongId::readLock ||
00223 lockKind == LongId::writeLock) {
00224 VolatileRootLock.releaseRead();
00225 RECORD_TIME_POINT;
00226 }
00227 kind = -2;
00228 break;
00229
00230 case 3:
00231
00232 if (SourceOrDerived::dirShortId((ShortId) index)) {
00233 Bit32 childSP = GetDirShortId((ShortId) index);
00234 if (childSP == 0) {
00235 err = VestaSource::notFound;
00236 } else {
00237 VDirChangeable* vdc =
00238 NEW_CONSTR(VDirChangeable,
00239 (VestaSource::immutableDirectory,
00240 (Bit8*) VMemPool::lengthenPointer(childSP)));
00241 child = vdc;
00242 memset(child->longid.value.byte, 0, sizeof(value));
00243 memcpy(child->longid.value.byte, value.byte, next - value.byte);
00244 child->master = true;
00245 child->fptag = vdc->fptag();
00246 child->ac.owner.attribs = (Bit8*) &emptyAttribsRep;
00247 child->ac.group.attribs = (Bit8*) &emptyAttribsRep;
00248 child->ac.mode = 0555;
00249 child->pseudoInode = index;
00250 err = VestaSource::ok;
00251 }
00252 kind = -2;
00253 } else {
00254 err = VestaSource::notFound;
00255 }
00256 break;
00257
00258 case 4:
00259
00260 if (!SourceOrDerived::dirShortId((ShortId) index)) {
00261
00262 child = NEW_CONSTR(VLeaf,
00263 (VestaSource::mutableFile, (ShortId)index));
00264 child->longid = *this;
00265 child->master = true;
00266 child->fptag.FromBytes(&this->value.byte[8]);
00267 child->ac.owner.attribs = (Bit8*) &volatileRootAttribsRep;
00268 child->ac.group.attribs = (Bit8*) &volatileRootAttribsRep;
00269 child->ac.mode = 0666;
00270 child->pseudoInode = index;
00271 err = VestaSource::ok;
00272 next = &this->value.byte[24];
00273 } else {
00274 err = VestaSource::notFound;
00275 }
00276 break;
00277 }
00278 if (vs != ::repositoryRoot && vs != ::mutableRoot &&
00279 vs != ::volatileRoot && vs != NULL)
00280 delete vs;
00281 if (err != VestaSource::ok) {
00282 if (lock && *lock &&
00283 (lockKind == LongId::readLock ||
00284 lockKind == LongId::writeLock ||
00285 lockKind == LongId::readLockV ||
00286 lockKind == LongId::writeLockV)) {
00287 (*lock)->release();
00288 *lock = NULL;
00289 }
00290 return NULL;
00291 }
00292 vs = child;
00293 }
00294 if (vs == ::repositoryRoot || vs == ::mutableRoot || vs == ::volatileRoot) {
00295
00296 vs = vs->copy();
00297 }
00298 return vs;
00299 }
00300
00301
00302 bool
00303 LongId::valid()
00304 throw (SRPC::failure )
00305 {
00306
00307
00308
00309
00310
00311
00312 VestaSource *vs = lookup();
00313 if (vs) {
00314 delete vs;
00315 return true;
00316 } else {
00317 return false;
00318 }
00319 }
00320
00321
00322
00323 static void
00324 VersCallback(RecoveryReader* rr, char& c)
00325 throw(VestaLog::Error, VestaLog::Eof)
00326 {
00327 long lversion;
00328 rr->getLong(c, lversion);
00329 VRLogVersion = lversion;
00330 if (VRLogVersion > LogMaxVersion) {
00331 Repos::dprintf(DBG_ALWAYS, "log version is %d; max supported version is %d\n",
00332 VRLogVersion, LogMaxVersion);
00333 exit(2);
00334 }
00335 }
00336
00337 static void
00338 DelCallback(RecoveryReader* rr, char& c)
00339 throw(VestaLog::Error, VestaLog::Eof)
00340 {
00341 LongId longid;
00342 char arc[MAX_ARC_LEN+1];
00343 long ltimestamp;
00344 rr->getLongId(c, longid.value);
00345 rr->getQuotedString(c, arc, sizeof(arc));
00346 rr->getLong(c, ltimestamp);
00347 VestaSource* vs = longid.lookup();
00348
00349 if(vs == 0)
00350 {
00351 cerr << "FATAL ERROR in recovery: invalid LongId in \"del\":" << endl
00352 << "\tlongid = " << longid << endl;
00353 abort();
00354 }
00355 VestaSource::errorCode
00356 err = vs->reallyDelete(arc, NULL, false, ltimestamp);
00357 assert(err == VestaSource::ok);
00358 delete vs;
00359 }
00360
00361 static void
00362 InsfCallback(RecoveryReader* rr, char& c)
00363 throw(VestaLog::Error, VestaLog::Eof)
00364 {
00365 LongId longid;
00366 char arc[MAX_ARC_LEN+1];
00367 unsigned long ulsid;
00368 long lmaster;
00369 long ltimestamp;
00370 FP::Tag fptag;
00371 FP::Tag* pfptag;
00372
00373 rr->getLongId(c, longid.value);
00374 rr->getQuotedString(c, arc, sizeof(arc));
00375 rr->getULong(c, ulsid);
00376 rr->getLong(c, lmaster);
00377 rr->getLong(c, ltimestamp);
00378 rr->skipWhite(c);
00379 if (c == ')') {
00380 pfptag = NULL;
00381 } else {
00382 GetFPTag(rr, c, fptag);
00383 pfptag = &fptag;
00384 }
00385 VestaSource* vs = longid.lookup();
00386
00387 if(vs == 0)
00388 {
00389 cerr << "FATAL ERROR in recovery: invalid LongId in \"insf\":" << endl
00390 << "\tlongid = " << longid << endl;
00391 abort();
00392 }
00393 VestaSource::errorCode err =
00394 vs->insertFile(arc, (ShortId) ulsid, (bool) lmaster,
00395 NULL, VestaSource::replaceDiff, NULL, ltimestamp, pfptag);
00396 assert(err == VestaSource::ok);
00397 delete vs;
00398 }
00399
00400 static void
00401 InsuCallback(RecoveryReader* rr, char& c)
00402 throw(VestaLog::Error, VestaLog::Eof)
00403 {
00404 LongId longid;
00405 char arc[MAX_ARC_LEN+1];
00406 unsigned long ulsid;
00407 long lmaster;
00408 long ltimestamp;
00409 rr->getLongId(c, longid.value);
00410 rr->getQuotedString(c, arc, sizeof(arc));
00411 rr->getULong(c, ulsid);
00412 rr->getLong(c, lmaster);
00413 rr->getLong(c, ltimestamp);
00414 VestaSource* vs = longid.lookup();
00415
00416 if(vs == 0)
00417 {
00418 cerr << "FATAL ERROR in recovery: invalid LongId in \"insu\":" << endl
00419 << "\tlongid = " << longid << endl;
00420 abort();
00421 }
00422 VestaSource::errorCode err =
00423 vs->insertMutableFile(arc, (ShortId) ulsid, (bool) lmaster,
00424 NULL, VestaSource::replaceDiff, NULL, ltimestamp);
00425 assert(err == VestaSource::ok);
00426 delete vs;
00427 }
00428
00429 static void
00430 InsiCallback(RecoveryReader* rr, char& c)
00431 throw(VestaLog::Error, VestaLog::Eof)
00432 {
00433 LongId pLongid, cLongid;
00434 char arc[MAX_ARC_LEN+1];
00435 long lmaster;
00436 long ltimestamp;
00437 FP::Tag fptag;
00438 FP::Tag* pfptag;
00439
00440 rr->getLongId(c, pLongid.value);
00441 rr->getQuotedString(c, arc, sizeof(arc));
00442 rr->getLongId(c, cLongid.value);
00443 rr->getLong(c, lmaster);
00444 rr->getLong(c, ltimestamp);
00445 rr->skipWhite(c);
00446 if (c == ')') {
00447 pfptag = NULL;
00448 } else {
00449 GetFPTag(rr, c, fptag);
00450 pfptag = &fptag;
00451 }
00452 VestaSource* pvs = pLongid.lookup();
00453
00454 if(pvs == 0)
00455 {
00456 cerr << "FATAL ERROR in recovery: invalid parent LongId in \"insi\":"
00457 << endl
00458 << "\tparent longid = " << pLongid << endl;
00459 abort();
00460 }
00461 VestaSource* cvs = cLongid.lookup();
00462
00463 if(!(cLongid == NullLongId) && (cvs == 0))
00464 {
00465 cerr << "FATAL ERROR in recovery: invalid child LongId in \"insi\":"
00466 << endl
00467 << "\tchild longid = " << cLongid << endl;
00468 abort();
00469 }
00470 VestaSource::errorCode err =
00471 pvs->insertImmutableDirectory(arc, cvs, (bool) lmaster,
00472 NULL, VestaSource::replaceDiff, NULL, ltimestamp, pfptag);
00473 assert(err == VestaSource::ok);
00474 delete pvs;
00475 delete cvs;
00476 }
00477
00478 static void
00479 InsmCallback(RecoveryReader* rr, char& c)
00480 throw(VestaLog::Error, VestaLog::Eof)
00481 {
00482 LongId pLongid, cLongid;
00483 char arc[MAX_ARC_LEN+1];
00484 long lmaster;
00485 long ltimestamp;
00486 rr->getLongId(c, pLongid.value);
00487 rr->getQuotedString(c, arc, sizeof(arc));
00488 rr->getLongId(c, cLongid.value);
00489 rr->getLong(c, lmaster);
00490 rr->getLong(c, ltimestamp);
00491 VestaSource* pvs = pLongid.lookup();
00492
00493 if(pvs == 0)
00494 {
00495 cerr << "FATAL ERROR in recovery: invalid parent LongId in \"insm\":"
00496 << endl
00497 << "\tparent longid = " << pLongid << endl;
00498 abort();
00499 }
00500 VestaSource* cvs = cLongid.lookup();
00501
00502 if(!(cLongid == NullLongId) && (cvs == 0))
00503 {
00504 cerr << "FATAL ERROR in recovery: invalid child LongId in \"insm\":"
00505 << endl
00506 << "\tchild longid = " << cLongid << endl;
00507 abort();
00508 }
00509 VestaSource::errorCode err =
00510 pvs->insertMutableDirectory(arc, cvs, (bool) lmaster, NULL,
00511 VestaSource::replaceDiff, NULL, ltimestamp);
00512 assert(err == VestaSource::ok);
00513 delete pvs;
00514 delete cvs;
00515 }
00516
00517 static void
00518 InsaCallback(RecoveryReader* rr, char& c)
00519 throw(VestaLog::Error, VestaLog::Eof)
00520 {
00521 LongId longid;
00522 char arc[MAX_ARC_LEN+1];
00523 long lmaster;
00524 long ltimestamp;
00525 rr->getLongId(c, longid.value);
00526 rr->getQuotedString(c, arc, sizeof(arc));
00527 rr->getLong(c, lmaster);
00528 rr->getLong(c, ltimestamp);
00529 VestaSource* vs = longid.lookup();
00530
00531 if(vs == 0)
00532 {
00533 cerr << "FATAL ERROR in recovery: invalid LongId in \"insa\":" << endl
00534 << "\tlongid = " << longid << endl;
00535 abort();
00536 }
00537 VestaSource::errorCode err =
00538 vs->insertAppendableDirectory(arc, (bool) lmaster, NULL,
00539 VestaSource::replaceDiff, NULL, ltimestamp);
00540 assert(err == VestaSource::ok);
00541 delete vs;
00542 }
00543
00544 static void
00545 InsgCallback(RecoveryReader* rr, char& c)
00546 throw(VestaLog::Error, VestaLog::Eof)
00547 {
00548 LongId longid;
00549 char arc[MAX_ARC_LEN+1];
00550 long lmaster;
00551 long ltimestamp;
00552 rr->getLongId(c, longid.value);
00553 rr->getQuotedString(c, arc, sizeof(arc));
00554 rr->getLong(c, lmaster);
00555 rr->getLong(c, ltimestamp);
00556 VestaSource* vs = longid.lookup();
00557
00558 if(vs == 0)
00559 {
00560 cerr << "FATAL ERROR in recovery: invalid LongId in \"insg\":" << endl
00561 << "\tlongid = " << longid << endl;
00562 abort();
00563 }
00564 VestaSource::errorCode err =
00565 vs->insertGhost(arc, (bool) lmaster, NULL,
00566 VestaSource::replaceDiff, NULL, ltimestamp);
00567 assert(err == VestaSource::ok);
00568 delete vs;
00569 }
00570
00571 static void
00572 InssCallback(RecoveryReader* rr, char& c)
00573 throw(VestaLog::Error, VestaLog::Eof)
00574 {
00575 LongId longid;
00576 char arc[MAX_ARC_LEN+1];
00577 long lmaster;
00578 long ltimestamp;
00579 rr->getLongId(c, longid.value);
00580 rr->getQuotedString(c, arc, sizeof(arc));
00581 rr->getLong(c, lmaster);
00582 rr->getLong(c, ltimestamp);
00583 VestaSource* vs = longid.lookup();
00584
00585 if(vs == 0)
00586 {
00587 cerr << "FATAL ERROR in recovery: invalid LongId in \"inss\":" << endl
00588 << "\tlongid = " << longid << endl;
00589 abort();
00590 }
00591 VestaSource::errorCode err =
00592 vs->insertStub(arc, (bool) lmaster, NULL,
00593 VestaSource::replaceDiff, NULL, ltimestamp);
00594 assert(err == VestaSource::ok);
00595 delete vs;
00596 }
00597
00598 static void
00599 RenCallback(RecoveryReader* rr, char& c)
00600 throw(VestaLog::Error, VestaLog::Eof)
00601 {
00602 LongId tLongid, fLongid;
00603 char tArc[MAX_ARC_LEN+1], fArc[MAX_ARC_LEN+1];
00604 long ltimestamp;
00605 rr->getLongId(c, tLongid.value);
00606 rr->getQuotedString(c, tArc, sizeof(tArc));
00607 rr->getLongId(c, fLongid.value);
00608 rr->getQuotedString(c, fArc, sizeof(fArc));
00609 rr->getLong(c, ltimestamp);
00610 VestaSource* tvs = tLongid.lookup();
00611
00612 if(tvs == 0)
00613 {
00614 cerr << "FATAL ERROR in recovery: invalid 'to' LongId in \"ren\":"
00615 << endl
00616 << "\t'to' longid = " << tLongid << endl;
00617 abort();
00618 }
00619 VestaSource* fvs = fLongid.lookup();
00620
00621 if(fvs == 0)
00622 {
00623 cerr << "FATAL ERROR in recovery: invalid 'from' LongId in \"ren\":"
00624 << endl
00625 << "\t'from' longid = " << fLongid << endl;
00626 abort();
00627 }
00628 VestaSource::errorCode err =
00629 tvs->renameTo(tArc, fvs, fArc, NULL,
00630 VestaSource::replaceDiff, ltimestamp);
00631 assert(err == VestaSource::ok);
00632 delete tvs;
00633 delete fvs;
00634 }
00635
00636 static void
00637 MakmCallback(RecoveryReader* rr, char& c)
00638 throw(VestaLog::Error, VestaLog::Eof)
00639 {
00640 LongId longid;
00641 unsigned long ulindex, ulsid;
00642 rr->getLongId(c, longid.value);
00643 rr->getULong(c, ulindex);
00644 rr->getULong(c, ulsid);
00645 VestaSource* vs = longid.lookup();
00646
00647 if(vs == 0)
00648 {
00649 cerr << "FATAL ERROR in recovery: invalid LongId in \"makm\":" << endl
00650 << "\tlongid = " << longid << endl;
00651 abort();
00652 }
00653 VestaSource* newvs;
00654 VestaSource::errorCode err =
00655 ((VDirChangeable*) vs)->makeIndexMutable((unsigned int) ulindex, newvs,
00656 (ShortId) ulsid);
00657 assert(err == VestaSource::ok);
00658 delete vs;
00659 delete newvs;
00660 }
00661
00662 static void
00663 MakiCallback(RecoveryReader* rr, char& c)
00664 throw(VestaLog::Error, VestaLog::Eof)
00665 {
00666 LongId longid;
00667 unsigned long ulindex;
00668 unsigned long ulsid;
00669 FP::Tag fptag;
00670 FP::Tag* pfptag;
00671
00672 rr->getLongId(c, longid.value);
00673 rr->getULong(c, ulindex);
00674 rr->skipWhite(c);
00675 pfptag = NULL;
00676 ulsid = NullShortId;
00677 if (c != ')') {
00678 GetFPTag(rr, c, fptag);
00679 pfptag = &fptag;
00680 rr->skipWhite(c);
00681 if (c != ')') {
00682 rr->getULong(c, ulsid);
00683 }
00684 }
00685 VestaSource* vs = longid.lookup();
00686
00687 if(vs == 0)
00688 {
00689 cerr << "FATAL ERROR in recovery: invalid LongId in \"maki\":" << endl
00690 << "\tlongid = " << longid << endl;
00691 abort();
00692 }
00693 ((VDirChangeable*) vs)->
00694 makeIndexImmutable((unsigned int) ulindex, pfptag, (ShortId) ulsid);
00695 delete vs;
00696 }
00697
00698 static void
00699 Copy2mCallback(RecoveryReader* rr, char& c)
00700 throw(VestaLog::Error, VestaLog::Eof)
00701 {
00702 LongId longid;
00703 unsigned long ulindex, ulsid;
00704 rr->getLongId(c, longid.value);
00705 rr->getULong(c, ulindex);
00706 VestaSource* vs = longid.lookup();
00707
00708 if(vs == 0)
00709 {
00710 cerr << "FATAL ERROR in recovery: invalid LongId in \"copy2m\":" << endl
00711 << "\tlongid = " << longid << endl;
00712 abort();
00713 }
00714 VestaSource* newvs;
00715 VestaSource::errorCode err =
00716 ((VDirChangeable*) vs)->copyIndexToMutable((unsigned int) ulindex, newvs);
00717 assert(err == VestaSource::ok);
00718 delete vs;
00719 delete newvs;
00720 }
00721
00722 static void
00723 MastCallback(RecoveryReader* rr, char& c)
00724 throw(VestaLog::Error, VestaLog::Eof)
00725 {
00726 LongId longid;
00727 unsigned long ulindex, ulstate;
00728
00729 rr->getLongId(c, longid.value);
00730 rr->getULong(c, ulindex);
00731 rr->getULong(c, ulstate);
00732 VestaSource* vs = longid.lookup();
00733
00734 if(vs == 0)
00735 {
00736 cerr << "FATAL ERROR in recovery: invalid LongId in \"mast\":" << endl
00737 << "\tlongid = " << longid << endl;
00738 abort();
00739 }
00740 VestaSource::errorCode err =
00741 ((VDirChangeable*) vs)->
00742 setIndexMaster((unsigned int) ulindex, (bool)ulstate);
00743 assert(err == VestaSource::ok);
00744 delete vs;
00745 }
00746
00747 static void
00748 AttrCallback(RecoveryReader* rr, char& c)
00749 throw(VestaLog::Error, VestaLog::Eof)
00750 {
00751 LongId longid;
00752 long lop, ltimestamp;
00753 char* name;
00754 char* value;
00755 rr->getLongId(c, longid.value);
00756 rr->getLong(c, lop);
00757 rr->getNewQuotedString(c, name);
00758 rr->getNewQuotedString(c, value);
00759 rr->getLong(c, ltimestamp);
00760 VestaSource* vs = longid.lookup();
00761
00762 if(vs == 0)
00763 {
00764 cerr << "FATAL ERROR in recovery: invalid LongId in \"attr\":" << endl
00765 << "\tlongid = " << longid << endl;
00766 abort();
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776 if(!vs->hasAttribs() && MutableRootLongId.isAncestorOf(vs->longid))
00777 {
00778 char longid_buf[65];
00779 OBufStream longid_ost(longid_buf, sizeof(longid_buf));
00780 longid_ost << longid;
00781 Repos::dprintf(DBG_ALWAYS,
00782 "WARNING: skipping replay of attribute write"
00783 "on object below mutable root without attributes: "
00784 "(attr %s %d \"%s\" \"%s\" %d)\n",
00785 longid_ost.str(), lop, name, value, ltimestamp);
00786 }
00787 else
00788 {
00789 VestaSource::errorCode err =
00790 vs->writeAttrib((VestaSource::attribOp) lop, name, value, NULL,
00791 ltimestamp);
00792 assert(err == VestaSource::ok);
00793 }
00794 delete [] name;
00795 delete [] value;
00796 delete vs;
00797 }
00798
00799 static void
00800 TimeCallback(RecoveryReader* rr, char& c)
00801 throw(VestaLog::Error, VestaLog::Eof)
00802 {
00803 LongId longid;
00804 unsigned long ultime;
00805
00806 rr->getLongId(c, longid.value);
00807 rr->getULong(c, ultime);
00808 VestaSource* vs = longid.lookup();
00809
00810 if(vs == 0)
00811 {
00812 cerr << "FATAL ERROR in recovery: invalid LongId in \"time\":" << endl
00813 << "\tlongid = " << longid << endl;
00814 abort();
00815 }
00816 VestaSource::errorCode err =
00817 ((VDirChangeable*) vs)->setTimestamp((time_t)ultime);
00818 assert(err == VestaSource::ok);
00819 delete vs;
00820 }
00821
00822 static void
00823 ColbCallback(RecoveryReader* rr, char& c)
00824 throw(VestaLog::Error, VestaLog::Eof)
00825 {
00826 LongId cLongid;
00827
00828 rr->getLongId(c, cLongid.value);
00829 VestaSource *cvs = cLongid.lookup();
00830
00831 if(cvs == 0)
00832 {
00833 cerr << "FATAL ERROR in recovery: invalid LongId in \"colb\":"
00834 << endl
00835 << "\tlongid = " << cLongid << endl;
00836 abort();
00837 }
00838 VestaSource::errorCode err = cvs->collapseBase();
00839 assert(err == VestaSource::ok);
00840 delete cvs;
00841 }
00842
00843 static void
00844 CorrectRootModes(VestaSource* dir)
00845 {
00846 const char* val;
00847 if ((val = dir->getAttribConst("#mode")) == NULL) {
00848 dir->ac.mode = 0755;
00849 } else {
00850 dir->ac.mode = AccessControl::parseModeBits(val);
00851 }
00852 }
00853
00854
00855
00856 VestaSource*
00857 VestaSource::repositoryRoot(LongId::lockKindTag lockKind,
00858 ReadersWritersLock** lock)
00859 throw (SRPC::failure )
00860 {
00861 switch (lockKind) {
00862 case LongId::noLock:
00863 if (lock != NULL) *lock = NULL;
00864 break;
00865 case LongId::readLock:
00866 case LongId::readLockV:
00867 RECORD_TIME_POINT;
00868 StableLock.acquireRead();
00869 RECORD_TIME_POINT;
00870 *lock = &StableLock;
00871 break;
00872 case LongId::writeLock:
00873 case LongId::writeLockV:
00874 RECORD_TIME_POINT;
00875 StableLock.acquireWrite();
00876 RECORD_TIME_POINT;
00877 *lock = &StableLock;
00878 break;
00879 case LongId::checkLock:
00880 if (*lock != &StableLock) return NULL;
00881 break;
00882 }
00883 ::repositoryRoot->resync();
00884 CorrectRootModes(::repositoryRoot);
00885 return ::repositoryRoot;
00886 }
00887
00888 VestaSource*
00889 VestaSource::mutableRoot(LongId::lockKindTag lockKind,
00890 ReadersWritersLock** lock)
00891 throw (SRPC::failure )
00892 {
00893 switch (lockKind) {
00894 case LongId::noLock:
00895 if (lock != NULL) *lock = NULL;
00896 break;
00897 case LongId::readLock:
00898 case LongId::readLockV:
00899 RECORD_TIME_POINT;
00900 StableLock.acquireRead();
00901 RECORD_TIME_POINT;
00902 *lock = &StableLock;
00903 break;
00904 case LongId::writeLock:
00905 case LongId::writeLockV:
00906 RECORD_TIME_POINT;
00907 StableLock.acquireWrite();
00908 RECORD_TIME_POINT;
00909 *lock = &StableLock;
00910 break;
00911 case LongId::checkLock:
00912 if (*lock != &StableLock) return NULL;
00913 break;
00914 }
00915 ::mutableRoot->resync();
00916 CorrectRootModes(::mutableRoot);
00917 return ::mutableRoot;
00918 }
00919
00920 VestaSource*
00921 VestaSource::volatileRoot(LongId::lockKindTag lockKind,
00922 ReadersWritersLock** lock)
00923 throw (SRPC::failure )
00924 {
00925 switch (lockKind) {
00926 case LongId::noLock:
00927 case LongId::readLockV:
00928 case LongId::writeLockV:
00929 if (lock != NULL) *lock = NULL;
00930 break;
00931 case LongId::readLock:
00932 RECORD_TIME_POINT;
00933 VolatileRootLock.acquireRead();
00934 RECORD_TIME_POINT;
00935 *lock = &VolatileRootLock;
00936 break;
00937 case LongId::writeLock:
00938 RECORD_TIME_POINT;
00939 VolatileRootLock.acquireWrite();
00940 RECORD_TIME_POINT;
00941 *lock = &VolatileRootLock;
00942 break;
00943 case LongId::checkLock:
00944 if (*lock != &VolatileRootLock) return NULL;
00945 break;
00946 }
00947 return ::volatileRoot;
00948 }
00949
00950 void
00951 VestaSource::init() throw ()
00952 {
00953
00954 doLogging = false;
00955
00956
00957
00958 ::repositoryRoot = NEW_CONSTR(VDirChangeable,
00959 (VestaSource::appendableDirectory));
00960 ::repositoryRoot->longid = RootLongId;
00961 ::repositoryRoot->pseudoInode = 1;
00962 ::repositoryRoot->attribs = (Bit8*) &repositoryRootAttribsRep;
00963 ::repositoryRoot->ac.owner.attribs = (Bit8*) &repositoryRootAttribsRep;
00964 ::repositoryRoot->ac.group.attribs = (Bit8*) &repositoryRootAttribsRep;
00965 ::repositoryRoot->fptag = pathnameFPTag;
00966
00967 ::mutableRoot = NEW_CONSTR(VDirChangeable,
00968 (VestaSource::mutableDirectory));
00969 ::mutableRoot->longid = MutableRootLongId;
00970 ::mutableRoot->pseudoInode = 2;
00971 ::mutableRoot->attribs = (Bit8*) &mutableRootAttribsRep;
00972 ::mutableRoot->ac.owner.attribs = (Bit8*) &mutableRootAttribsRep;
00973 ::mutableRoot->ac.group.attribs = (Bit8*) &mutableRootAttribsRep;
00974 ::mutableRoot->fptag = FP::Tag("");
00975 ::mutableRoot->master = true;
00976
00977 VDirVolatileRoot::init();
00978 ::volatileRoot = NEW(VDirVolatileRoot);
00979 ::volatileRoot->type = VestaSource::volatileDirectory;
00980 ::volatileRoot->longid = VolatileRootLongId;
00981 ::volatileRoot->pseudoInode = 3;
00982 ::volatileRoot->fptag = FP::Tag("");
00983 ::volatileRoot->attribs = (Bit8*) &volatileRootAttribsRep;
00984 ::volatileRoot->ac.owner.attribs = (Bit8*) &volatileRootAttribsRep;
00985 ::volatileRoot->ac.group.attribs = (Bit8*) &volatileRootAttribsRep;
00986 ::volatileRoot->ac.mode = 0755;
00987 ::volatileRoot->master = true;
00988
00989
00990 RegisterRecoveryCallback("del", DelCallback);
00991 RegisterRecoveryCallback("insf", InsfCallback);
00992 RegisterRecoveryCallback("insu", InsuCallback);
00993 RegisterRecoveryCallback("insi", InsiCallback);
00994 RegisterRecoveryCallback("insm", InsmCallback);
00995 RegisterRecoveryCallback("insa", InsaCallback);
00996 RegisterRecoveryCallback("insg", InsgCallback);
00997 RegisterRecoveryCallback("inss", InssCallback);
00998 RegisterRecoveryCallback("ren", RenCallback);
00999 RegisterRecoveryCallback("makm", MakmCallback);
01000 RegisterRecoveryCallback("maki", MakiCallback);
01001 RegisterRecoveryCallback("copy2m", Copy2mCallback);
01002 RegisterRecoveryCallback("mast", MastCallback);
01003 RegisterRecoveryCallback("attr", AttrCallback);
01004 RegisterRecoveryCallback("time", TimeCallback);
01005 RegisterRecoveryCallback("vers", VersCallback);
01006 RegisterRecoveryCallback("colb", ColbCallback);
01007
01008
01009 InitVRWeed();
01010 }
01011
01012 void
01013 VestaSource::recoveryDone() throw ()
01014 {
01015 ::repositoryRoot->resync();
01016 ::mutableRoot->resync();
01017
01018
01019
01020
01021
01022 ::volatileRoot->writeAttrib(VestaAttribs::opSet, "#owner",
01023 AccessControl::runtoolUser);
01024 ::volatileRoot->writeAttrib(VestaAttribs::opSet, "#group",
01025 AccessControl::vadminGroup);
01026
01027
01028
01029 if(!MutableSidrefRecoveryCheck())
01030 {
01031 MutableSidrefInit();
01032 }
01033 doLogging = true;
01034 if (VRLogVersion < LogMaxVersion) {
01035
01036 VRLogVersion = LogMaxVersion;
01037 char logrec[512];
01038 OBufStream ost(logrec, sizeof(logrec));
01039
01040 ost << "(vers " << VRLogVersion << ")\n";
01041 VRLog.start();
01042 VRLog.put(ost.str());
01043 VRLog.commit();
01044 }
01045
01046 }
01047
01048 VestaSource::errorCode
01049 VestaSource::makeMutable(VestaSource*& result, ShortId sid,
01050 Basics::uint64 copyMax,
01051 AccessControl::Identity who)
01052 throw (SRPC::failure )
01053 {
01054 if (!ac.check(who, AccessControl::write))
01055 return VestaSource::noPermission;
01056 if (!(MutableRootLongId.isAncestorOf(longid) ||
01057 VolatileRootLongId.isAncestorOf(longid))) {
01058 return VestaSource::inappropriateOp;
01059 }
01060 unsigned int index;
01061 VestaSource* parent = longid.getParent(&index).lookup();
01062 if (parent == NULL)
01063 return VestaSource::inappropriateOp;
01064 VestaSource::errorCode err;
01065 if (parent->type == VestaSource::immutableDirectory ||
01066 parent->type == VestaSource::evaluatorDirectory ||
01067 parent->type == VestaSource::evaluatorROEDirectory) {
01068 VestaSource* muparent;
01069 err = parent->makeMutable(muparent, NullShortId,
01070 (Basics::uint64) -1, who);
01071 if (err != VestaSource::ok) return err;
01072 delete parent;
01073 parent = muparent;
01074 }
01075 err = ((VDirChangeable*) parent)->
01076 makeIndexMutable(index, result, sid, copyMax, who);
01077 delete parent;
01078 return err;
01079 }
01080
01081 VestaSource::errorCode
01082 VestaSource::copyToMutable(VestaSource*& result,
01083 AccessControl::Identity who)
01084 throw (SRPC::failure )
01085 {
01086 if (!ac.check(who, AccessControl::write))
01087 return VestaSource::noPermission;
01088 if (!MutableRootLongId.isAncestorOf(longid)) {
01089 return VestaSource::inappropriateOp;
01090 }
01091 unsigned int index;
01092 VestaSource* parent = longid.getParent(&index).lookup();
01093 if (parent == NULL)
01094 return VestaSource::inappropriateOp;
01095 VestaSource::errorCode err;
01096 if (parent->type != VestaSource::mutableDirectory) {
01097 VestaSource* muparent;
01098 err = parent->makeMutable(muparent, NullShortId,
01099 (Basics::uint64) -1, who);
01100 if (err != VestaSource::ok) return err;
01101 delete parent;
01102 parent = muparent;
01103 }
01104 err = ((VDirChangeable*) parent)->
01105 copyIndexToMutable(index, result, who);
01106 delete parent;
01107 return err;
01108 }
01109
01110 struct MakeFilesImmutableClosure {
01111 VestaSource *vs;
01112 VestaSource::errorCode err;
01113 unsigned int fpThreshold;
01114 };
01115
01116 const FP::Tag uidFPTag("Textd");
01117
01118 static bool
01119 MakeFilesImmutableCallback(void* closure, VestaSource::typeTag type, Arc arc,
01120 unsigned int index, Bit32 pseudoInode,
01121 ShortId filesid, bool master)
01122 {
01123 MakeFilesImmutableClosure *cl = (MakeFilesImmutableClosure *) closure;
01124 MakeFilesImmutableClosure newcl;
01125 int fd, res;
01126 FP::Tag fptag;
01127 FP::Tag* newfptag = NULL;
01128 FdCache::OFlag ofl;
01129 struct stat st;
01130 ShortId dupsid = NullShortId;
01131
01132 switch (type) {
01133 case VestaSource::mutableFile:
01134
01135
01136
01137 fd = FdCache::open(filesid, FdCache::rw, &ofl);
01138 if(fd < 0)
01139
01140 fd = FdCache::open(filesid, FdCache::any, &ofl);
01141 assert(fd >= 0);
01142 res = fstat(fd, &st);
01143 assert(res >= 0);
01144 if(cl->vs->type != VestaSource::mutableDirectory &&
01145 cl->vs->type != VestaSource::volatileDirectory &&
01146 cl->vs->type != VestaSource::volatileROEDirectory)
01147 {
01148
01149
01150 Repos::dprintf(DBG_ALWAYS,
01151 "warning: makeFilesImmutable found mutable file "
01152 "\"%s\" in unexpected directory type (%s)\n",
01153 arc, VestaSource::typeTagString(cl->vs->type));
01154 }
01155 if (st.st_size < cl->fpThreshold) {
01156
01157 lseek(fd, 0, SEEK_SET);
01158 FS::IFdStream fs(fd);
01159 if (st.st_mode & 0111) {
01160 fptag = executableFPTag;
01161 } else {
01162 fptag = contentsFPTag;
01163 }
01164
01165 FP::FileContents(fs, fptag);
01166 newfptag = &fptag;
01167 dupsid = GetFPShortId(fptag);
01168 }
01169
01170 if (dupsid == NullShortId) {
01171
01172
01173 if(((VDirChangeable*)cl->vs)->getRefCount(filesid) > 1)
01174 {
01175
01176
01177
01178 int err;
01179 dupsid = CopyShortId(filesid, err,
01180 ((Basics::uint64)-1), ((Basics::uint64 *) 0),
01181 false);
01182 assert(dupsid != NullShortId);
01183 }
01184 else
01185 {
01186
01187 if (st.st_mode & 0222)
01188 {
01189
01190 assert(ofl == FdCache::rw);
01191
01192 res = fchmod(fd, st.st_mode & ~0222);
01193 assert(res >= 0);
01194
01195
01196 FdCache::flush(filesid, FdCache::rw);
01197
01198 res = fsync(fd);
01199 assert(res != -1);
01200
01201 }
01202 }
01203
01204
01205 if(ofl == FdCache::rw)
01206 {
01207
01208
01209 do
01210 res = close(fd);
01211 while ((res == -1) && (errno == EINTR));
01212 assert(res != -1);
01213 }
01214 else
01215 {
01216
01217
01218
01219
01220 FdCache::close(filesid, fd, ofl);
01221 }
01222 if (newfptag == NULL)
01223 {
01224
01225
01226
01227
01228
01229
01230
01231
01232 fptag = uidFPTag;
01233 fptag.Extend(UniqueId());
01234 newfptag = &fptag;
01235 }
01236
01237
01238 ((VDirChangeable*)cl->vs)->makeIndexImmutable(index, newfptag, dupsid);
01239 } else {
01240
01241 FdCache::close(filesid, fd, ofl);
01242 ((VDirChangeable*)cl->vs)->
01243 makeIndexImmutable(index, newfptag, dupsid);
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 if ((VRLog.nesting() == 0) &&
01255
01256
01257 (((VDirChangeable*)cl->vs)->getRefCount(filesid) == 0))
01258 {
01259
01260 FdCache::flush(filesid, FdCache::any);
01261 char* name = SourceOrDerived::shortIdToName(filesid);
01262 Repos::dprintf(DBG_SIDDISP, "unlinking: 0x%08x\n", filesid);
01263 int ret = unlink(name);
01264 if (ret < 0) {
01265 int saved_errno = errno;
01266 Text err_txt = Basics::errno_Text(saved_errno);
01267 Repos::dprintf(DBG_ALWAYS,
01268 "unlink %s: %s (errno = %d)\n", name,
01269 err_txt.cchars(), saved_errno);
01270 }
01271 delete[] name;
01272 }
01273 }
01274 break;
01275
01276 case VestaSource::mutableDirectory:
01277 case VestaSource::volatileDirectory:
01278 case VestaSource::volatileROEDirectory:
01279 cl->err = cl->vs->lookupIndex(index, newcl.vs);
01280 if (cl->err != VestaSource::ok) return false;
01281 newcl.err = VestaSource::ok;
01282 newcl.fpThreshold = cl->fpThreshold;
01283 cl->err =
01284 newcl.vs->list(0, MakeFilesImmutableCallback, &newcl, NULL, true);
01285 delete newcl.vs;
01286 if (cl->err != VestaSource::ok) return false;
01287 if (newcl.err != VestaSource::ok) {
01288 cl->err = newcl.err;
01289 return false;
01290 }
01291 break;
01292
01293 default:
01294 break;
01295 }
01296 return true;
01297 }
01298
01299
01300 VestaSource::errorCode
01301 VestaSource::makeFilesImmutable(unsigned int fpThreshold,
01302 AccessControl::Identity who)
01303 throw (SRPC::failure )
01304 {
01305 if (!ac.check(who, AccessControl::write))
01306 return VestaSource::noPermission;
01307
01308 MakeFilesImmutableClosure cl;
01309 switch (type) {
01310 case VestaSource::mutableDirectory:
01311 case VestaSource::volatileDirectory:
01312 case VestaSource::volatileROEDirectory:
01313 break;
01314 case VestaSource::immutableFile:
01315 return VestaSource::ok;
01316 case VestaSource::mutableFile:
01317 {
01318 unsigned int index;
01319 LongId plongid = this->longid.getParent(&index);
01320 cl.vs = plongid.lookup();
01321 if (cl.vs == NULL) return VestaSource::inappropriateOp;
01322 cl.err = VestaSource::ok;
01323 cl.fpThreshold = fpThreshold;
01324 MakeFilesImmutableCallback(&cl, type, NULL, index,
01325 pseudoInode, shortId(), master);
01326 delete cl.vs;
01327 return cl.err;
01328 }
01329 default:
01330 return VestaSource::inappropriateOp;
01331 }
01332 cl.vs = this;
01333 cl.err = VestaSource::ok;
01334 cl.fpThreshold = fpThreshold;
01335 VestaSource::errorCode err =
01336 list(0, MakeFilesImmutableCallback, &cl, NULL, true);
01337 if (err != VestaSource::ok) return err;
01338 return cl.err;
01339 }
01340
01341 VestaSource::errorCode
01342 VestaSource::lookupPathname(const char* pathname, VestaSource*& result,
01343 AccessControl::Identity who, char pathnameSep)
01344 throw (SRPC::failure )
01345 {
01346 VestaSource* cur = this;
01347 while (*pathname) {
01348 char arcbuf[MAX_ARC_LEN+1];
01349 char* slash = strchr(pathname, pathnameSep);
01350 if (slash != NULL) {
01351 strncpy(arcbuf, pathname, slash - pathname);
01352 arcbuf[slash - pathname] = '\000';
01353 pathname = slash + 1;
01354 } else {
01355 strcpy(arcbuf, pathname);
01356 pathname = "";
01357 }
01358 if (*arcbuf) {
01359 VestaSource* child;
01360 VestaSource::errorCode err = cur->lookup(arcbuf, child, who);
01361 if (cur != this) delete cur;
01362 cur = child;
01363 if (err != VestaSource::ok) return err;
01364 }
01365 }
01366 if (cur == this) {
01367
01368 result = cur->longid.lookup();
01369 } else {
01370 result = cur;
01371 }
01372 return VestaSource::ok;
01373 }
01374
01375 VestaSource::errorCode
01376 VestaSource::writeAttrib(VestaAttribs::attribOp op, const char* name,
01377 const char* value,
01378 AccessControl::Identity who, time_t timestamp)
01379 throw (SRPC::failure )
01380 {
01381 if (!hasAttribs()) return VestaSource::invalidArgs;
01382
01383 VestaSource::errorCode err = VestaSource::ok;
01384 if (name[0] == '#') {
01385 AccessControl::Class acc;
01386 if (strcmp(name, "#replicate-from") == 0 ||
01387 strcmp(name, "#mastership-from") == 0 ||
01388 strcmp(name, "#mastership-to") == 0) {
01389 acc = AccessControl::administrative;
01390 } else if ((op == opSet || op == opAdd) &&
01391 strcmp(name, "#setuid") == 0) {
01392 acc = AccessControl::setuid;
01393 } else if ((op == opSet || op == opAdd) &&
01394 strcmp(name, "#setgid") == 0) {
01395 acc = AccessControl::setgid;
01396 } else {
01397 acc = AccessControl::ownership;
01398 }
01399 if (!ac.check(who, acc, value)) {
01400 err = VestaSource::noPermission;
01401 }
01402 } else {
01403 if (!ac.check(who, AccessControl::write)) {
01404 err = VestaSource::noPermission;
01405 }
01406 }
01407 if (err != VestaSource::ok) {
01408
01409
01410 if (wouldWriteAttrib(op, name, value, timestamp)) {
01411 return err;
01412 } else {
01413 return VestaSource::ok;
01414 }
01415 }
01416
01417 err = VestaAttribs::writeAttrib(op, name, value, timestamp);
01418
01419 if (err == VestaSource::ok && VestaSource::doLogging &&
01420 !VolatileRootLongId.isAncestorOf(longid)) {
01421
01422 char buf[512];
01423
01424 VRLog.start();
01425 {
01426 OBufStream ost(buf, sizeof(buf));
01427 ost << "(attr " << longid << " " << ((int) op) << " ";
01428 VRLog.put(ost.str());
01429 }
01430 LogPutQuotedString(VRLog, name);
01431 VRLog.put(" ");
01432 LogPutQuotedString(VRLog, value);
01433 {
01434 OBufStream ost(buf, sizeof(buf));
01435 ost << " " << timestamp << ")\n";
01436 VRLog.put(ost.str());
01437 }
01438 VRLog.commit();
01439 }
01440
01441
01442 if(err == VestaSource::nameInUse)
01443 err = VestaSource::ok;
01444
01445 return err;
01446 }