2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * ht_lookupEntry - tape ids
12 * Truncate Tape - tape id's
16 #include <afsconfig.h>
17 #include <afs/param.h>
22 #include <afs/bubasics.h>
29 #include <afs/cellconfig.h>
31 #include <afs/audit.h>
32 #include <afs/afsutil.h>
35 #include "budb_errs.h"
37 #include "budb_internal.h"
38 #include "error_macros.h"
45 extern struct ubik_dbase *BU_dbase;
46 extern struct afsconf_dir *BU_conf; /* for getting cell info */
48 afs_int32 AddVolume(struct rx_call *, struct budb_volumeEntry *);
49 afs_int32 AddVolumes(struct rx_call *, struct budb_volumeList *);
50 afs_int32 CreateDump(struct rx_call *, struct budb_dumpEntry *);
51 afs_int32 DoDeleteDump(struct rx_call *, dumpId, Date, Date, budb_dumpsList *);
52 afs_int32 DoDeleteTape(struct rx_call *, struct budb_tapeEntry *);
53 afs_int32 ListDumps(struct rx_call *, afs_int32, afs_int32, Date, Date,
54 budb_dumpsList *, budb_dumpsList *);
55 afs_int32 DeleteVDP(struct rx_call *, char *, char *, afs_int32);
56 afs_int32 FindClone(struct rx_call *, afs_int32, char *, afs_int32 *);
57 afs_int32 FindDump(struct rx_call *, char *, afs_int32,
58 struct budb_dumpEntry *);
59 afs_int32 FindLatestDump(struct rx_call *, char *, char *,
60 struct budb_dumpEntry *);
61 afs_int32 FinishDump(struct rx_call *, struct budb_dumpEntry *);
62 afs_int32 FinishTape(struct rx_call *, struct budb_tapeEntry *);
63 afs_int32 GetDumps(struct rx_call *, afs_int32, afs_int32, char *,
64 afs_int32, afs_int32, afs_int32, afs_int32 *,
65 afs_int32 *, budb_dumpList *);
66 afs_int32 getExpiration(struct ubik_trans *ut, struct tape *);
67 afs_int32 makeAppended(struct ubik_trans *ut, afs_int32, afs_int32,
69 afs_int32 MakeDumpAppended(struct rx_call *, afs_int32, afs_int32,
71 afs_int32 FindLastTape(struct rx_call *, afs_int32, struct budb_dumpEntry *,
72 struct budb_tapeEntry *, struct budb_volumeEntry *);
73 afs_int32 GetTapes(struct rx_call *, afs_int32, afs_int32, char *, afs_int32,
74 afs_int32, afs_int32, afs_int32 *, afs_int32 *,
76 afs_int32 GetVolumes(struct rx_call *, afs_int32, afs_int32, char *,
77 afs_int32, afs_int32, afs_int32, afs_int32 *,
78 afs_int32 *, budb_volumeList *);
79 afs_int32 UseTape(struct rx_call *, struct budb_tapeEntry *, int *);
80 afs_int32 T_DumpHashTable(struct rx_call *, int, char *);
81 afs_int32 T_GetVersion(struct rx_call *, int *);
82 afs_int32 T_DumpDatabase(struct rx_call *, char *);
84 int volFragsDump(struct ubik_trans *, FILE *, dbadr);
86 /* Text block management */
89 struct memTextBlock *mtb_next; /* next in chain */
90 afs_int32 mtb_nbytes; /* # of bytes in this block */
91 struct blockHeader mtb_blkHeader; /* in memory header */
92 dbadr mtb_addr; /* disk address of block */
95 typedef struct memTextBlock memTextBlockT;
96 typedef memTextBlockT *memTextBlockP;
98 /* These variable are for returning debugging info about the state of the
99 server. If they get trashed during multi-threaded operation it doesn't
102 /* This is global so COUNT_REQ in krb_udp.c can refer to it. */
103 char *lastOperation; /* name of last operation */
104 static Date lastTrans; /* time of last transaction */
106 /* procsInited is sort of a lock: during a transaction only one process runs
107 while procsInited is false. */
109 static int procsInited = 0;
111 /* This variable is protected by the procsInited flag. */
113 static int (*rebuildDatabase) (struct ubik_trans *);
115 /* AwaitInitialization
116 * Wait unitl budb has initialized (InitProcs). If it hasn't
117 * within 5 seconds, then return no quorum.
120 AwaitInitialization(void)
124 while (!procsInited) {
127 else if (time(0) - start > 5)
129 #ifdef AFS_PTHREAD_ENV
139 * name is a pathname style name, determine trailing name and return
144 tailCompPtr(char *pathNamePtr)
147 ptr = strrchr(pathNamePtr, '/');
149 /* this should never happen */
150 LogError(0, "tailCompPtr: could not find / in name(%s)\n",
152 return (pathNamePtr);
154 ptr++; /* skip the / */
159 * Check to see if the caller is a SuperUser.
166 callPermitted(struct rx_call *call)
169 struct afsconf_dir *acdir;
171 acdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
175 if (afsconf_SuperUser(acdir, call, NULL))
179 afsconf_Close(acdir);
184 * This is called by every RPC interface to create a Ubik transaction
185 * and read the database header into core
191 * sets a lock on byte 1 of the database. Looks like it enforces
192 * single threading by use of the lock.
196 InitRPC(struct ubik_trans **ut,
197 int lock, /* indicate read/write transaction */
198 int this_op) /* opcode of RCP, for COUNT_ABO */
201 float wait = 0.91; /* start waiting for 1 second */
204 /* wait for server initialization to finish if this is not InitProcs calling */
206 if ((code = AwaitInitialization()))
209 for (code = UNOQUORUM; code == UNOQUORUM;) {
211 ubik_BeginTrans(BU_dbase,
213 LOCKREAD) ? UBIK_READTRANS : UBIK_WRITETRANS),
215 if (code == UNOQUORUM) { /* no quorum elected */
217 Log("Waiting for quorum election\n");
220 #ifdef AFS_PTHREAD_ENV
223 IOMGR_Sleep((int)wait);
230 Log("Have established quorum\n");
232 /* set lock at posiion 1, for 1 byte of type lock */
233 if ((code = ubik_SetLock(*ut, 1, 1, lock))) {
234 ubik_AbortTrans(*ut);
238 /* check that dbase is initialized and setup cheader */
239 if (lock == LOCKREAD) {
240 /* init but don't fix because this is read only */
241 if ((code = CheckInit(*ut, 0))) {
242 ubik_AbortTrans(*ut);
243 if ((code = InitRPC(ut, LOCKWRITE, 0))) { /* Now fix the database */
244 LogError(code, "InitRPC: InitRPC failed\n");
247 if ((code = ubik_EndTrans(*ut))) {
248 LogError(code, "InitRPC: ubik_EndTrans failed\n");
251 goto start; /* now redo the read transaction */
254 if ((code = CheckInit(*ut, rebuildDatabase))) {
255 ubik_AbortTrans(*ut);
263 /* This is called to initialize a newly created database */
265 initialize_database(struct ubik_trans *ut)
270 static int noAuthenticationRequired; /* global state */
271 static int recheckNoAuth; /* global state */
276 struct ubik_trans *ut;
281 if ((globalConfPtr->myHost == 0) || (BU_conf == 0))
282 ERROR(BUDB_INTERNALERROR);
286 if (globalConfPtr->debugFlags & DF_NOAUTH)
287 noAuthenticationRequired = 1;
289 if (globalConfPtr->debugFlags & DF_RECHECKNOAUTH)
293 noAuthenticationRequired = afsconf_GetNoAuthFlag(BU_conf);
295 if (noAuthenticationRequired)
296 LogError(0, "Running server with security disabled\n");
300 rebuildDatabase = initialize_database;
302 if ((code = InitRPC(&ut, LOCKREAD, 0))) {
303 LogError(code, "InitProcs: InitRPC failed\n");
306 code = ubik_EndTrans(ut);
308 LogError(code, "InitProcs: ubik_EndTrans failed\n");
312 rebuildDatabase = 0; /* only do this during init */
320 int nElements; /* number in list */
321 int allocSize; /* number of elements allocated */
322 dbadr *elements; /* array of addresses */
326 InitReturnList(struct returnList *list)
330 list->elements = (dbadr *) 0;
334 FreeReturnList(struct returnList *list)
337 free(list->elements);
338 list->elements = (dbadr *) 0;
342 /* As entries are collected, they are added to a return list. Once all
343 * entries have been collected, it is then placed in the return buffer
344 * with SendReturnList(). The first *to_skipP are not recorded.
347 AddToReturnList(struct returnList *list, dbadr a, afs_int32 *to_skipP)
359 /* Up to 5 plus a maximum so SendReturnList() knows if we
360 * need to come back for more.
362 if (list->nElements >= BUDB_MAX_RETURN_LIST + 5)
363 return BUDB_LIST2BIG;
365 if (list->nElements >= list->allocSize) {
366 if (list->elements == 0) {
368 tmp = (char *)malloc(sizeof(dbadr) * size);
370 size = list->allocSize + 10;
371 tmp = (char *)realloc(list->elements, sizeof(dbadr) * size);
375 list->elements = (dbadr *) tmp;
376 list->allocSize = size;
379 list->elements[list->nElements] = a;
385 FillVolEntry(struct ubik_trans *ut, dbadr va, void *rock)
387 struct budb_volumeEntry *vol = (struct budb_volumeEntry *) rock;
391 struct volFragment vf;
393 if (dbread(ut, va, &vf, sizeof(vf)))
394 return BUDB_IO; /* The volFrag */
395 if (dbread(ut, ntohl(vf.vol), &vi, sizeof(vi)))
396 return BUDB_IO; /* The volInfo */
397 if (dbread(ut, ntohl(vf.tape), &t, sizeof(t)))
398 return BUDB_IO; /* The tape */
399 if (dbread(ut, ntohl(t.dump), &d, sizeof(d)))
400 return BUDB_IO; /* The dump */
402 strcpy(vol->name, vi.name);
403 strcpy(vol->server, vi.server);
404 strcpy(vol->tape, t.name);
405 vol->tapeSeq = ntohl(t.seq);
406 vol->dump = ntohl(d.id);
407 vol->position = ntohl(vf.position);
408 vol->clone = ntohl(vf.clone);
409 vol->incTime = ntohl(vf.incTime);
410 vol->nBytes = ntohl(vf.nBytes);
411 vol->startByte = ntohl(vf.startByte);
412 vol->flags = (ntohs(vf.flags) & VOLFRAGMENTFLAGS); /* low 16 bits here */
413 vol->flags |= (ntohl(vi.flags) & VOLINFOFLAGS); /* high 16 bits here */
414 vol->seq = ntohs(vf.sequence);
415 vol->id = ntohl(vi.id);
416 vol->partition = ntohl(vi.partition);
422 FillDumpEntry(struct ubik_trans *ut, dbadr da, void *rock)
424 struct budb_dumpEntry *dump = (struct budb_dumpEntry *)rock;
427 if (dbread(ut, da, &d, sizeof(d)))
429 dump->id = ntohl(d.id);
430 dump->flags = ntohl(d.flags);
431 dump->created = ntohl(d.created);
432 strncpy(dump->name, d.dumpName, sizeof(dump->name));
433 strncpy(dump->dumpPath, d.dumpPath, sizeof(dump->dumpPath));
434 strncpy(dump->volumeSetName, d.volumeSet, sizeof(dump->volumeSetName));
436 dump->parent = ntohl(d.parent);
437 dump->level = ntohl(d.level);
438 dump->nVolumes = ntohl(d.nVolumes);
440 tapeSet_ntoh(&d.tapes, &dump->tapes);
442 if (strlen(d.dumper.name) < sizeof(dump->dumper.name))
443 strcpy(dump->dumper.name, d.dumper.name);
444 if (strlen(d.dumper.instance) < sizeof(dump->dumper.instance))
445 strcpy(dump->dumper.instance, d.dumper.instance);
446 if (strlen(d.dumper.cell) < sizeof(dump->dumper.cell))
447 strcpy(dump->dumper.cell, d.dumper.cell);
449 /* Get the initial dumpid and the appended dump id */
450 dump->initialDumpID = ntohl(d.initialDumpID);
451 if (d.appendedDumpChain) {
452 if (dbread(ut, ntohl(d.appendedDumpChain), &ad, sizeof(ad)))
454 dump->appendedDumpID = ntohl(ad.id);
456 dump->appendedDumpID = 0;
458 /* printf("dump name %s, parent %d, level %d\n",
459 * d.dumpName, ntohl(d.parent), ntohl(d.level)); */
465 FillTapeEntry(struct ubik_trans *ut, dbadr ta, void *rock)
467 struct budb_tapeEntry *tape=(struct budb_tapeEntry *) rock;
472 if (dbread(ut, ta, &t, sizeof(t)))
475 /* Get the tape's expiration date */
476 if ((code = getExpiration(ut, &t)))
479 strcpy(tape->name, t.name);
480 tape->flags = ntohl(t.flags);
481 tape->written = ntohl(t.written);
482 tape->expires = ntohl(t.expires);
483 tape->nMBytes = ntohl(t.nMBytes);
484 tape->nBytes = ntohl(t.nBytes);
485 tape->nFiles = ntohl(t.nFiles);
486 tape->nVolumes = ntohl(t.nVolumes);
487 tape->seq = ntohl(t.seq);
488 tape->labelpos = ntohl(t.labelpos);
489 tape->useCount = ntohl(t.useCount);
490 tape->useKBytes = ntohl(t.useKBytes);
492 if (dbread(ut, ntohl(t.dump), &d, sizeof(d)))
494 tape->dump = ntohl(d.id);
498 #define returnList_t budb_dumpList *
501 * A list of elements of size e_size is in list, collected
502 * with AddToReturnList(). We will move this to a correspoding
503 * return list, eList, via FillProc(). nextInodeP tells us
504 * if there are more and how many to skip on the next request.
507 SendReturnList(struct ubik_trans *ut,
508 struct returnList *list, /* list of elements to return */
509 afs_int32(*FillProc) (struct ubik_trans *, dbadr da,
511 /* proc to fill entry */
512 int e_size, /* size of each element */
513 afs_int32 index, /* index from previous call */
514 afs_int32 *nextIndexP, /* if more elements are available */
515 afs_int32 *dbTimeP, /* time of last db update */
516 budb_dumpList *eList) /* rxgen list structure (e.g.) */
524 *dbTimeP = ntohl(db.h.lastUpdate);
526 /* Calculate how many to return. Don't let if go over
527 * BUDB_MAX_RETURN_LIST nor the size of our return list.
529 to_return = list->nElements;
530 if (to_return > BUDB_MAX_RETURN_LIST)
531 to_return = BUDB_MAX_RETURN_LIST;
532 if (eList->budb_dumpList_len && (to_return > eList->budb_dumpList_len))
533 to_return = eList->budb_dumpList_len;
535 /* Allocate space for the return values if needed and zero it */
536 if (eList->budb_dumpList_val == 0) {
537 eList->budb_dumpList_val =
538 (struct budb_dumpEntry *)malloc(e_size * to_return);
539 if (!eList->budb_dumpList_val)
542 memset(eList->budb_dumpList_val, 0, e_size * to_return);
543 eList->budb_dumpList_len = to_return;
545 e = (char *)(eList->budb_dumpList_val);
546 for (i = 0; i < to_return; i++, e += e_size) {
547 code = (*FillProc) (ut, list->elements[i], (budb_dumpEntry *) e);
552 if (list->nElements > i)
553 *nextIndexP = index + i;
557 /* Come here to delete a volInfo structure. */
560 DeleteVolInfo(struct ubik_trans *ut, dbadr via, struct volInfo *vi)
566 if (vi->firstFragment)
567 return 0; /* still some frags, don't free yet */
568 if (vi->sameNameHead == 0) { /* this is the head */
569 if (vi->sameNameChain)
570 return 0; /* empty head, some non-heads left */
572 code = ht_HashOut(ut, &db.volName, via, vi);
575 code = FreeStructure(ut, volInfo_BLOCK, via);
578 hvia = ntohl(vi->sameNameHead);
579 if (dbread(ut, hvia, &hvi, sizeof(hvi)))
582 RemoveFromList(ut, hvia, &hvi, &hvi.sameNameChain, via, vi,
585 return BUDB_DATABASEINCONSISTENT;
587 code = FreeStructure(ut, volInfo_BLOCK, via);
591 /* Detach a volume fragment from its volInfo structure. Its tape chain is
592 already freed. This routine frees the structure and the caller must not
596 DeleteVolFragment(struct ubik_trans *ut, dbadr va, struct volFragment *v)
603 if (dbread(ut, via, &vi, sizeof(vi)))
606 RemoveFromList(ut, via, &vi, &vi.firstFragment, va, v,
609 return BUDB_DATABASEINCONSISTENT;
612 if (vi.firstFragment == 0)
613 if ((code = DeleteVolInfo(ut, via, &vi)))
615 if ((code = FreeStructure(ut, volFragment_BLOCK, va)))
618 /* decrement frag counter */
620 set_word_addr(ut, via, &vi, &vi.nFrags, htonl(ntohl(vi.nFrags) - 1));
626 /* DeleteTape - by freeing all its volumes and removing it from its dump chain.
627 * The caller will remove it from the hash table if necessary. The caller is
628 * also responsible for writing the tape out if necessary. */
631 DeleteTape(struct ubik_trans *ut, dbadr ta, struct tape *t)
639 return BUDB_DATABASEINCONSISTENT;
640 if (dbread(ut, da, &d, sizeof(d)))
642 if (d.firstTape == 0)
643 return BUDB_DATABASEINCONSISTENT;
645 code = RemoveFromList(ut, da, &d, &d.firstTape, ta, t, &t->nextTape);
647 return BUDB_DATABASEINCONSISTENT;
651 /* Since the tape should have been truncated there should never be any
652 * volumes in the tape. */
653 if (t->firstVol || t->nVolumes)
654 return BUDB_DATABASEINCONSISTENT;
660 DeleteDump(struct ubik_trans *ut, dbadr da, struct dump *d)
664 code = ht_HashOut(ut, &db.dumpIden, da, d);
668 code = ht_HashOut(ut, &db.dumpName, da, d);
672 /* Since the tape should have been truncated this should never happen. */
673 if (d->firstTape || d->nVolumes)
674 ERROR(BUDB_DATABASEINCONSISTENT);
676 code = FreeStructure(ut, dump_BLOCK, da);
687 * This is called with a volumeEntry and a volInfo structure and compares
688 * them. It returns non-zero if they are equal. It is used by GetVolInfo to
689 * search volInfo structures once it has the head volInfo structure from the
690 * volName hash table.
692 * When called from GetVolInfo the name compare is redundant.
693 * Always AND the flags with VOLINFOFLAGS for backwards compatability (3.3).
697 VolInfoMatch(struct budb_volumeEntry *vol, struct volInfo *vi)
699 return ((strcmp(vol->name, vi->name) == 0) && /* same volume name */
700 (vol->id == ntohl(vi->id)) && /* same volume id */
701 ((vol->flags & VOLINFOFLAGS) == (ntohl(vi->flags) & VOLINFOFLAGS)) && /* same flags */
702 (vol->partition == ntohl(vi->partition)) && /* same partition (N/A) */
703 (strcmp(vol->server, vi->server) == 0)); /* same server (N/A) */
708 * This routine takes a volumeEntry structure from an RPC interface and
709 * returns the corresponding volInfo structure, creating it if necessary.
711 * The caller must write the entry out.
715 GetVolInfo(struct ubik_trans *ut, struct budb_volumeEntry *volP, dbadr *viaP,
720 afs_int32 eval, code = 0;
722 eval = ht_LookupEntry(ut, &db.volName, volP->name, &via, viP);
727 /* allocate a new volinfo structure */
728 eval = AllocStructure(ut, volInfo_BLOCK, 0, &via, viP);
732 strcpy(viP->name, volP->name);
733 strcpy(viP->server, volP->server);
734 viP->sameNameHead = 0; /* The head of same name chain */
735 viP->sameNameChain = 0; /* Same name chain is empty */
736 viP->firstFragment = 0;
738 viP->id = htonl(volP->id);
739 viP->partition = htonl(volP->partition);
740 viP->flags = htonl(volP->flags & VOLINFOFLAGS);
742 /* Chain onto volname hash table */
743 eval = ht_HashIn(ut, &db.volName, via, viP);
747 LogDebug(4, "volume Info for %s placed at %d\n", volP->name, via);
750 else if (!VolInfoMatch(volP, viP)) { /* Not the head volinfo struct */
751 hvia = via; /* remember the head volinfo struct */
752 memcpy(&hvi, viP, sizeof(hvi));
754 /* Search the same name chain for the correct volinfo structure */
755 for (via = ntohl(viP->sameNameChain); via;
756 via = ntohl(viP->sameNameChain)) {
757 eval = dbread(ut, via, viP, sizeof(*viP));
761 if (VolInfoMatch(volP, viP))
762 break; /* found the one */
765 /* if the correct volinfo struct isn't found, create one */
767 eval = AllocStructure(ut, volInfo_BLOCK, 0, &via, viP);
771 strcpy(viP->name, volP->name);
772 strcpy(viP->server, volP->server);
773 viP->nameHashChain = 0; /* not in hash table */
774 viP->sameNameHead = htonl(hvia); /* chain to head of sameNameChain */
775 viP->sameNameChain = hvi.sameNameChain;
776 viP->firstFragment = 0;
778 viP->id = htonl(volP->id);
779 viP->partition = htonl(volP->partition);
780 viP->flags = htonl(volP->flags & VOLINFOFLAGS);
782 /* write the head entry's sameNameChain link */
784 set_word_addr(ut, hvia, &hvi, &hvi.sameNameChain, htonl(via));
796 /* deletesomevolumesfromtape
797 * Deletes a specified number of volumes from a tape. The tape
798 * and dump are modified to reflect the smaller number of volumes.
799 * The transaction is not terminated, it is up to the caller to
800 * finish the transaction and start a new one (if desired).
802 * maxvolumestodelete - don't delete more than this many volumes
806 deleteSomeVolumesFromTape(struct ubik_trans *ut, dbadr tapeAddr,
807 struct tape *tapePtr, int maxVolumesToDelete)
809 dbadr volFragAddr, nextVolFragAddr, dumpAddr;
810 struct volFragment volFrag;
812 int volumesDeleted = 0;
813 afs_int32 eval, code = 0;
818 for (volFragAddr = ntohl(tapePtr->firstVol);
819 (volFragAddr && (maxVolumesToDelete > 0));
820 volFragAddr = nextVolFragAddr) {
821 eval = dbread(ut, volFragAddr, &volFrag, sizeof(volFrag));
825 nextVolFragAddr = ntohl(volFrag.sameTapeChain);
827 eval = DeleteVolFragment(ut, volFragAddr, &volFrag);
831 maxVolumesToDelete--;
835 /* reset the volume fragment pointer in the tape */
836 tapePtr->firstVol = htonl(volFragAddr);
838 /* diminish the tape's volume count */
839 tapePtr->nVolumes = htonl(ntohl(tapePtr->nVolumes) - volumesDeleted);
841 eval = dbwrite(ut, tapeAddr, tapePtr, sizeof(*tapePtr));
845 /* diminish the dump's volume count */
846 dumpAddr = ntohl(tapePtr->dump);
847 eval = dbread(ut, dumpAddr, &dump, sizeof(dump));
851 dump.nVolumes = htonl(ntohl(dump.nVolumes) - volumesDeleted);
852 eval = dbwrite(ut, dumpAddr, &dump, sizeof(dump));
861 * deletes a dump in stages, by repeatedly deleting a small number of
862 * volumes from the dump until none are left. The dump is then deleted.
864 * In the case where multiple calls are made to delete the same
865 * dump, the operation will succeed but contention for structures
866 * will result in someone getting back an error.
869 * id - id of dump to delete
873 deleteDump(struct rx_call *call, dumpId id, budb_dumpsList *dumps)
875 struct ubik_trans *ut;
876 dbadr dumpAddr, tapeAddr, appendedDump;
880 afs_int32 eval, code = 0;
883 /* iterate until the dump is truly deleted */
889 eval = InitRPC(&ut, LOCKWRITE, 1);
891 ERROR(eval); /* can't start transaction */
894 ht_LookupEntry(ut, &db.dumpIden, &dumpid, &dumpAddr, &dump);
898 ABORT(BUDB_NOENT); /* can't find dump */
900 if ((dumpid == id) && (dump.initialDumpID)) /* can't be an appended dump */
901 ABORT(BUDB_NOTINITIALDUMP);
903 tapeAddr = ntohl(dump.firstTape);
907 /* there is a tape to delete */
908 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
912 if (ntohl(tape.nVolumes)) {
913 /* tape is not empty */
914 eval = deleteSomeVolumesFromTape(ut, tapeAddr, &tape, 10);
919 if (ntohl(tape.nVolumes) == 0) {
920 /* tape is now empty, delete it */
921 eval = DeleteTape(ut, tapeAddr, &tape);
924 eval = ht_HashOut(ut, &db.tapeName, tapeAddr, &tape);
927 eval = FreeStructure(ut, tape_BLOCK, tapeAddr);
932 eval = ubik_EndTrans(ut);
936 } /* next deletion portion */
938 /* Record the dump just deleted */
939 if (dumps && (dumps->budb_dumpsList_len < BUDB_MAX_RETURN_LIST)) {
940 if (dumps->budb_dumpsList_len == 0)
941 dumps->budb_dumpsList_val =
942 (afs_int32 *) malloc(sizeof(afs_int32));
944 dumps->budb_dumpsList_val =
945 (afs_int32 *) realloc(dumps->budb_dumpsList_val,
946 (dumps->budb_dumpsList_len +
947 1) * sizeof(afs_int32));
949 if (!dumps->budb_dumpsList_val)
952 dumps->budb_dumpsList_val[dumps->budb_dumpsList_len] = dumpid;
953 dumps->budb_dumpsList_len++;
956 appendedDump = ntohl(dump.appendedDumpChain);
958 /* finally done. No more tapes left in the dump. Delete the dump itself */
959 eval = DeleteDump(ut, dumpAddr, &dump);
963 /* Now delete the appended dump too */
965 eval = dbread(ut, appendedDump, &dump, sizeof(dump));
969 dumpid = ntohl(dump.id);
973 eval = ubik_EndTrans(ut);
977 Log("Delete dump %s (DumpID %u), path %s\n", dump.dumpName,
978 ntohl(dump.id), dump.dumpPath);
982 if (code && partialDel) {
983 Log("Delete dump %s (DumpID %u), path %s - INCOMPLETE (code = %u)\n",
984 dump.dumpName, ntohl(dump.id), dump.dumpPath, code);
994 * dump selection routines - used by BUDB_GetDumps
998 /* most recent dump selection */
1001 struct chosenDump *next;
1006 struct wantDumpRock {
1007 int maxDumps; /* max wanted */
1008 int ndumps; /* actual in chain */
1009 struct chosenDump *chain;
1014 wantDump(dbadr dumpAddr, void *dumpParam, void *dumpListPtrParam)
1016 struct dump *dumpPtr;
1017 struct wantDumpRock *rockPtr;
1019 dumpPtr = (struct dump *)dumpParam;
1020 rockPtr = (struct wantDumpRock *)dumpListPtrParam;
1022 /* if we don't have our full complement, just add another */
1023 if (rockPtr->ndumps < rockPtr->maxDumps)
1026 /* got the number we need, select based on date */
1027 if ((afs_uint32) ntohl(dumpPtr->created) > rockPtr->chain->date)
1034 rememberDump(dbadr dumpAddr, void *dumpParam, void *dumpListPtrParam)
1036 struct dump *dumpPtr;
1037 struct wantDumpRock *rockPtr;
1038 struct chosenDump *ptr, *deletedPtr, **nextPtr;
1040 dumpPtr = (struct dump *)dumpParam;
1041 rockPtr = (struct wantDumpRock *)dumpListPtrParam;
1043 ptr = (struct chosenDump *)malloc(sizeof(*ptr));
1046 memset(ptr, 0, sizeof(*ptr));
1047 ptr->addr = dumpAddr;
1048 ptr->date = (afs_uint32) ntohl(dumpPtr->created);
1050 /* Don't overflow the max */
1051 while (rockPtr->ndumps >= rockPtr->maxDumps) {
1052 /* have to drop one */
1053 deletedPtr = rockPtr->chain;
1054 rockPtr->chain = deletedPtr->next;
1059 /* now insert in the right place */
1060 for (nextPtr = &rockPtr->chain; *nextPtr; nextPtr = &((*nextPtr)->next)) {
1061 if (ptr->date < (*nextPtr)->date)
1064 ptr->next = *nextPtr;
1072 /* ---------------------------------------------
1073 * general interface routines - alphabetic
1074 * ---------------------------------------------
1078 SBUDB_AddVolume(struct rx_call *call, struct budb_volumeEntry *vol)
1082 code = AddVolume(call, vol);
1083 osi_auditU(call, BUDB_AddVolEvent, code, AUD_LONG, (vol ? vol->id : 0),
1089 AddVolume(struct rx_call *call, struct budb_volumeEntry *vol)
1091 struct ubik_trans *ut;
1092 dbadr da, ta, via, va;
1096 struct volFragment v;
1098 afs_int32 eval, code = 0;
1100 if (!callPermitted(call))
1101 return BUDB_NOTPERMITTED;
1103 if ((strlen(vol->name) >= sizeof(vi.name))
1104 || (strlen(vol->server) >= sizeof(vi.server))
1105 || (strlen(vol->tape) >= sizeof(t.name)))
1106 return BUDB_BADARGUMENT;
1108 eval = InitRPC(&ut, LOCKWRITE, 1);
1112 /* Find the dump in dumpid hash table */
1113 eval = ht_LookupEntry(ut, &db.dumpIden, &vol->dump, &da, &d);
1117 ABORT(BUDB_NODUMPID);
1119 /* search for the right tape in the dump */
1120 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
1121 /* read the tape entry */
1122 eval = dbread(ut, ta, &t, sizeof(t));
1126 /* Check if the right tape name */
1127 if (strcmp(t.name, vol->tape) == 0)
1131 ABORT(BUDB_NOTAPENAME);
1133 if ((t.dump != htonl(da)) || /* tape must belong to dump */
1134 ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0) || /* tape must be being written */
1135 ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)) /* dump must be in progress */
1136 ABORT(BUDB_BADPROTOCOL);
1138 /* find or create a volume info structure */
1139 eval = GetVolInfo(ut, vol, &via, &vi);
1143 /* Create a volume fragment */
1144 eval = AllocStructure(ut, volFragment_BLOCK, 0, &va, &v);
1148 v.vol = htonl(via); /* vol frag points to vol info */
1149 v.sameNameChain = vi.firstFragment; /* vol frag is chained to vol info */
1150 vi.firstFragment = htonl(va);
1151 vi.nFrags = htonl(ntohl(vi.nFrags) + 1);
1153 eval = dbwrite(ut, via, &vi, sizeof(vi)); /* write the vol info struct */
1157 v.tape = htonl(ta); /* vol frag points to tape */
1158 v.sameTapeChain = t.firstVol; /* vol frag is chained to tape info */
1159 t.firstVol = htonl(va);
1160 t.nVolumes = htonl(ntohl(t.nVolumes) + 1);
1161 bytes = ntohl(t.nBytes) + vol->nBytes; /* update bytes on tape */
1162 t.nMBytes = htonl(ntohl(t.nMBytes) + bytes / (1024 * 1024));
1163 t.nBytes = htonl(bytes % (1024 * 1024));
1165 eval = dbwrite(ut, ta, &t, sizeof(t)); /* write the tape structure */
1169 d.nVolumes = htonl(ntohl(d.nVolumes) + 1); /* one more volume on dump */
1171 eval = dbwrite(ut, da, &d, sizeof(d)); /* write out the dump structure */
1175 v.position = htonl(vol->position); /* vol frag info */
1176 v.clone = htonl(vol->clone);
1177 v.incTime = htonl(vol->incTime);
1178 v.startByte = htonl(vol->startByte);
1179 v.nBytes = htonl(vol->nBytes);
1180 v.flags = htons(vol->flags & VOLFRAGMENTFLAGS);
1181 v.sequence = htons(vol->seq);
1183 eval = dbwrite(ut, va, &v, sizeof(v)); /* write out the vol frag struct */
1187 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1191 LogDebug(4, "added volume %s at %d\n", vol->name, va);
1193 code = ubik_EndTrans(ut);
1197 ubik_AbortTrans(ut);
1203 SBUDB_AddVolumes(struct rx_call *call, struct budb_volumeList *vols)
1207 code = AddVolumes(call, vols);
1208 osi_auditU(call, BUDB_AddVolEvent, code, AUD_LONG, 0, AUD_END);
1213 AddVolumes(struct rx_call *call, struct budb_volumeList *vols)
1215 struct budb_volumeEntry *vol, *vol1;
1216 struct ubik_trans *ut;
1217 dbadr da, ta, via, va;
1221 struct volFragment v;
1223 afs_int32 eval, e, code = 0;
1225 if (!callPermitted(call))
1226 return BUDB_NOTPERMITTED;
1228 if (!vols || (vols->budb_volumeList_len <= 0)
1229 || !vols->budb_volumeList_val)
1230 return BUDB_BADARGUMENT;
1232 /* The first volume in the list of volumes to add */
1233 vol1 = (struct budb_volumeEntry *)vols->budb_volumeList_val;
1235 eval = InitRPC(&ut, LOCKWRITE, 1);
1239 /* Find the dump in dumpid hash table */
1240 eval = ht_LookupEntry(ut, &db.dumpIden, &vol1->dump, &da, &d);
1244 ABORT(BUDB_NODUMPID);
1246 /* search for the right tape in the dump */
1247 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
1248 /* read the tape entry */
1249 eval = dbread(ut, ta, &t, sizeof(t));
1253 /* Check if the right tape name */
1254 if (strcmp(t.name, vol1->tape) == 0)
1258 ABORT(BUDB_NOTAPENAME);
1260 if ((t.dump != htonl(da)) || /* tape must belong to dump */
1261 ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0) || /* tape must be being written */
1262 ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)) /* dump must be in progress */
1263 ABORT(BUDB_BADPROTOCOL);
1265 for (vol = vol1, e = 0; e < vols->budb_volumeList_len; vol++, e++) {
1267 if ((strlen(vol->name) >= sizeof(vi.name)) || (strcmp(vol->name, "") == 0) || /* no null volnames */
1268 (strlen(vol->server) >= sizeof(vi.server))
1269 || (strlen(vol->tape) >= sizeof(t.name))
1270 || (strcmp(vol->tape, vol1->tape) != 0)) {
1271 Log("Volume '%s' %u, tape '%s', dumpID %u is an invalid entry - not added\n", vol->name, vol->id, vol->tape, vol->dump);
1275 /* find or create a volume info structure */
1276 eval = GetVolInfo(ut, vol, &via, &vi);
1279 if (*(afs_int32 *) (&vi) == 0) {
1280 Log("Volume '%s', tape '%s', dumpID %u is an invalid entry - aborted\n", vol->name, vol->tape, vol->dump);
1281 ABORT(BUDB_BADARGUMENT);
1284 /* Create a volume fragment */
1285 eval = AllocStructure(ut, volFragment_BLOCK, 0, &va, &v);
1289 v.vol = htonl(via); /* vol frag points to vol info */
1290 v.sameNameChain = vi.firstFragment; /* vol frag is chained to vol info */
1291 vi.firstFragment = htonl(va);
1292 vi.nFrags = htonl(ntohl(vi.nFrags) + 1);
1293 eval = dbwrite(ut, via, &vi, sizeof(vi)); /* write the vol info struct */
1297 v.tape = htonl(ta); /* vol frag points to tape */
1298 v.sameTapeChain = t.firstVol; /* vol frag is chained to tape info */
1299 t.firstVol = htonl(va);
1300 t.nVolumes = htonl(ntohl(t.nVolumes) + 1);
1301 bytes = ntohl(t.nBytes) + vol->nBytes; /* update bytes on tape */
1302 t.nMBytes = htonl(ntohl(t.nMBytes) + bytes / (1024 * 1024));
1303 t.nBytes = htonl(bytes % (1024 * 1024));
1305 d.nVolumes = htonl(ntohl(d.nVolumes) + 1); /* one more volume on dump */
1307 v.position = htonl(vol->position); /* vol frag info */
1308 v.clone = htonl(vol->clone);
1309 v.incTime = htonl(vol->incTime);
1310 v.startByte = htonl(vol->startByte);
1311 v.nBytes = htonl(vol->nBytes);
1312 v.flags = htons(vol->flags & VOLFRAGMENTFLAGS);
1313 v.sequence = htons(vol->seq);
1315 eval = dbwrite(ut, va, &v, sizeof(v)); /* write out the vol frag struct */
1319 LogDebug(4, "added volume %s at %d\n", vol->name, va);
1322 eval = dbwrite(ut, ta, &t, sizeof(t)); /* write the tape structure */
1326 eval = dbwrite(ut, da, &d, sizeof(d)); /* write out the dump structure */
1330 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1334 code = ubik_EndTrans(ut);
1338 ubik_AbortTrans(ut);
1344 * records the existence of a dump in the database. This creates only
1345 * the dump record, to which one must attach tape and volume records.
1347 * 1) record the volume set
1351 SBUDB_CreateDump(struct rx_call *call, struct budb_dumpEntry *dump)
1355 code = CreateDump(call, dump);
1356 osi_auditU(call, BUDB_CrDmpEvent, code, AUD_DATE, (dump ? dump->id : 0),
1358 if (dump && !code) {
1359 Log("Create dump %s (DumpID %u), path %s\n", dump->name, dump->id,
1366 CreateDump(struct rx_call *call, struct budb_dumpEntry *dump)
1368 struct ubik_trans *ut;
1369 dbadr findDumpAddr, da;
1370 struct dump findDump, d;
1371 afs_int32 eval, code = 0;
1375 Date expiration; /* checked by Security Module */
1376 struct ktc_principal principal;
1378 if (!callPermitted(call))
1379 return BUDB_NOTPERMITTED;
1381 if (strlen(dump->name) >= sizeof(d.dumpName))
1382 return BUDB_BADARGUMENT;
1384 eval = InitRPC(&ut, LOCKWRITE, 1);
1389 rxkad_GetServerInfo(rx_ConnectionOf(call), &level, &expiration,
1390 principal.name, principal.instance,
1391 principal.cell, &kvno);
1394 if (eval != RXKADNOAUTH)
1397 strcpy(principal.name, "");
1398 strcpy(principal.instance, "");
1399 strcpy(principal.cell, "");
1402 /* authenticated. Take user supplied principal information */
1403 if (strcmp(dump->dumper.name, "") != 0)
1404 strncpy(principal.name, dump->dumper.name,
1405 sizeof(principal.name));
1407 if (strcmp(dump->dumper.instance, "") != 0)
1408 strncpy(principal.instance, dump->dumper.instance,
1409 sizeof(principal.instance));
1411 if (strcmp(dump->dumper.cell, "") != 0)
1412 strncpy(principal.cell, dump->dumper.cell,
1413 sizeof(principal.cell));
1416 /* dump id's are time stamps */
1418 while (1) { /* allocate a unique dump id *//*w */
1421 /* ensure it is unique - seach for dumpid in hash table */
1423 ht_LookupEntry(ut, &db.dumpIden, &dump->id, &findDumpAddr,
1428 if (!findDumpAddr) { /* dumpid not in use */
1429 /* update the last dump id allocated */
1430 eval = set_header_word(ut, lastDumpId, htonl(dump->id));
1436 /* dump id is in use - wait a while */
1437 #ifdef AFS_PTHREAD_ENV
1444 /* dump id supplied (e.g. for database restore) */
1446 ht_LookupEntry(ut, &db.dumpIden, &dump->id, &findDumpAddr,
1451 /* Dump id must not already exist */
1453 ABORT(BUDB_DUMPIDEXISTS);
1456 /* Allocate a dump structure */
1457 memset(&d, 0, sizeof(d));
1458 eval = AllocStructure(ut, dump_BLOCK, 0, &da, &d);
1462 strcpy(d.dumpName, dump->name); /* volset.dumpname */
1463 strcpy(d.dumpPath, dump->dumpPath); /* dump node path */
1464 strcpy(d.volumeSet, dump->volumeSetName); /* volume set */
1465 d.id = htonl(dump->id);
1466 d.parent = htonl(dump->parent); /* parent id */
1467 d.level = htonl(dump->level);
1469 LogDebug(4, "dump name %s, parent %d level %d\n", dump->name,
1470 dump->parent, dump->level);
1472 /* if creation time specified, use that. Else use the dumpid time */
1473 if (dump->created == 0)
1474 dump->created = dump->id;
1475 d.created = htonl(dump->created);
1477 principal = d.dumper;
1478 tapeSet_hton(&dump->tapes, &d.tapes);
1480 d.flags = htonl(dump->flags | BUDB_DUMP_INPROGRESS);
1482 eval = ht_HashIn(ut, &db.dumpName, da, &d); /* Into dump name hash table */
1486 eval = ht_HashIn(ut, &db.dumpIden, da, &d); /* Into dumpid hash table */
1490 eval = dbwrite(ut, da, (char *)&d, sizeof(d)); /* Write the dump structure */
1494 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1498 /* If to append this dump, then append it - will write the appended dump */
1499 eval = makeAppended(ut, dump->id, dump->initialDumpID, dump->tapes.b);
1503 code = ubik_EndTrans(ut);
1504 LogDebug(5, "made dump %s, path %s\n", d.dumpName, d.dumpPath);
1508 ubik_AbortTrans(ut);
1513 SBUDB_DeleteDump(struct rx_call *call, dumpId id, Date fromTime, Date toTime,
1514 budb_dumpsList *dumps)
1518 code = DoDeleteDump(call, id, fromTime, toTime, dumps);
1519 osi_auditU(call, BUDB_DelDmpEvent, code, AUD_DATE, id, AUD_END);
1526 DoDeleteDump(struct rx_call *call, dumpId id, Date fromTime, Date toTime,
1527 budb_dumpsList *dumps)
1531 if (!callPermitted(call))
1532 return BUDB_NOTPERMITTED;
1535 code = deleteDump(call, id, dumps);
1540 SBUDB_ListDumps(struct rx_call *call, afs_int32 sflags, char *name,
1541 afs_int32 groupid, Date fromTime, Date toTime,
1542 budb_dumpsList *dumps, budb_dumpsList *flags)
1546 code = ListDumps(call, sflags, groupid, fromTime, toTime, dumps, flags);
1547 osi_auditU(call, BUDB_LstDmpEvent, code, AUD_LONG, flags, AUD_END);
1552 ListDumps(struct rx_call *call, afs_int32 sflags, afs_int32 groupid,
1553 Date fromTime, Date toTime, budb_dumpsList *dumps,
1554 budb_dumpsList *flags)
1556 struct ubik_trans *ut;
1557 struct memoryHashTable *mht;
1558 struct dump diskDump, appDiskDump;
1559 dbadr dbAddr, dbAppAddr;
1561 afs_int32 eval, code = 0;
1562 int old, hash, length, entrySize, count = 0;
1564 if (!callPermitted(call))
1565 return BUDB_NOTPERMITTED;
1567 eval = InitRPC(&ut, LOCKREAD, 1);
1571 /* Search the database */
1572 mht = ht_GetType(HT_dumpIden_FUNCTION, &entrySize);
1574 return (BUDB_BADARGUMENT);
1576 for (old = 0; old <= 1; old++) { /*o *//* old and new hash tables */
1577 length = (old ? mht->oldLength : mht->length);
1581 for (hash = 0; hash < length; hash++) { /*h *//* for each hash bucket */
1582 for (dbAddr = ht_LookupBucket(ut, mht, hash, old); dbAddr; dbAddr = ntohl(diskDump.idHashChain)) { /*d */
1584 /* read the entry */
1585 eval = dbread(ut, dbAddr, &diskDump, sizeof(diskDump));
1589 /* Skip appended dumps */
1590 if (ntohl(diskDump.initialDumpID) != 0) {
1594 /* Skip dumps with different goup id */
1595 if ((sflags & BUDB_OP_GROUPID)
1596 && (ntohl(diskDump.tapes.id) != groupid)) {
1600 /* Look at this dump to see if it meets the criteria for listing */
1601 if (sflags & BUDB_OP_DATES) {
1602 /* This and each appended dump should be in time */
1603 for (dbAppAddr = dbAddr; dbAppAddr;
1604 dbAppAddr = ntohl(appDiskDump.appendedDumpChain)) {
1606 dbread(ut, dbAppAddr, &appDiskDump,
1607 sizeof(appDiskDump));
1611 if ((ntohl(appDiskDump.id) < fromTime)
1612 || (ntohl(appDiskDump.id) > toTime))
1619 /* Add it and each of its appended dump to our list to return */
1620 for (dbAppAddr = dbAddr; dbAppAddr;
1621 dbAppAddr = ntohl(appDiskDump.appendedDumpChain)) {
1623 dbread(ut, dbAppAddr, &appDiskDump,
1624 sizeof(appDiskDump));
1628 /* Make sure we have space to list it */
1629 if (dumps->budb_dumpsList_len >= count) {
1632 dumps->budb_dumpsList_val =
1633 (afs_int32 *) malloc(count *
1635 flags->budb_dumpsList_val =
1636 (afs_int32 *) malloc(count *
1639 dumps->budb_dumpsList_val =
1640 (afs_int32 *) realloc(dumps->
1644 flags->budb_dumpsList_val =
1645 (afs_int32 *) realloc(flags->
1650 if (!dumps->budb_dumpsList_val
1651 || !dumps->budb_dumpsList_val)
1655 /* Add it to our list */
1656 dumps->budb_dumpsList_val[dumps->budb_dumpsList_len] =
1657 ntohl(appDiskDump.id);
1658 flags->budb_dumpsList_val[flags->budb_dumpsList_len] = 0;
1659 if (ntohl(appDiskDump.initialDumpID) != 0) {
1660 flags->budb_dumpsList_val[flags->
1661 budb_dumpsList_len] |=
1664 if (strcmp(appDiskDump.dumpName, DUMP_TAPE_NAME) == 0) {
1665 flags->budb_dumpsList_val[flags->
1666 budb_dumpsList_len] |=
1669 dumps->budb_dumpsList_len++;
1670 flags->budb_dumpsList_len++;
1676 code = ubik_EndTrans(ut);
1680 ubik_AbortTrans(ut);
1685 SBUDB_DeleteTape(struct rx_call *call,
1686 struct budb_tapeEntry *tape) /* tape info */
1690 code = DoDeleteTape(call, tape);
1691 osi_auditU(call, BUDB_DelTpeEvent, code, AUD_DATE,
1692 (tape ? tape->dump : 0), AUD_END);
1697 DoDeleteTape(struct rx_call *call,
1698 struct budb_tapeEntry *tape) /* tape info */
1700 struct ubik_trans *ut;
1703 afs_int32 eval, code;
1705 if (!callPermitted(call))
1706 return BUDB_NOTPERMITTED;
1708 eval = InitRPC(&ut, LOCKWRITE, 1);
1712 eval = ht_LookupEntry(ut, &db.tapeName, tape->name, &a, &t);
1716 eval = DeleteTape(ut, a, &t);
1720 eval = FreeStructure(ut, tape_BLOCK, a);
1724 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1728 code = ubik_EndTrans(ut);
1732 ubik_AbortTrans(ut);
1737 * Deletes old information from the database for a particular dump path
1738 * and volumset. This supercedes the old policy implemented in
1739 * UseTape, which simply matched on the volumeset.dump. Consequently
1740 * it was unable to handle name re-use.
1742 * dsname - dumpset name, i.e. volumeset.dumpname
1743 * dumpPath - full path of dump node
1744 * curDumpID - current dump in progress - so that is may be excluded
1747 * n - some error. May or may not have deleted information.
1751 SBUDB_DeleteVDP(struct rx_call *call, char *dsname, char *dumpPath,
1752 afs_int32 curDumpId)
1756 code = DeleteVDP(call, dsname, dumpPath, curDumpId);
1757 osi_auditU(call, BUDB_DelVDPEvent, code, AUD_STR, dsname, AUD_END);
1762 DeleteVDP(struct rx_call *call, char *dsname, char *dumpPath,
1763 afs_int32 curDumpId)
1768 struct ubik_trans *ut;
1769 afs_int32 eval, code = 0;
1771 if (!callPermitted(call))
1772 return BUDB_NOTPERMITTED;
1775 eval = InitRPC(&ut, LOCKREAD, 1);
1779 eval = ht_LookupEntry(ut, &db.dumpName, dsname, &dumpAddr, &dump);
1783 while (dumpAddr != 0) { /*wd */
1784 if ((strcmp(dump.dumpName, dsname) == 0)
1785 && (strcmp(dump.dumpPath, dumpPath) == 0)
1786 && (ntohl(dump.id) != curDumpId)) {
1787 eval = ubik_EndTrans(ut);
1791 eval = deleteDump(call, ntohl(dump.id), 0);
1795 /* start the traversal over since the various chains may
1801 dumpAddr = ntohl(dump.nameHashChain);
1803 eval = dbread(ut, dumpAddr, &dump, sizeof(dump));
1809 /* check if all the dumps have been examined - can terminate */
1811 eval = ubik_EndTrans(ut);
1817 ubik_AbortTrans(ut);
1823 * Given a volume name, and a dumpID, find the volume in that dump and
1824 * return the clone date of the volume (this is the clone date of the
1825 * volume at the time it was dumped).
1827 * Hashes on the volume name and traverses the fragments. Will need to read
1828 * the volumes tape entry to determine if it belongs to the dump. If the
1829 * volume is not found in the dump, then look for it in its parent dump.
1833 SBUDB_FindClone(struct rx_call *call, afs_int32 dumpID, char *volName,
1834 afs_int32 *clonetime)
1838 code = FindClone(call, dumpID, volName, clonetime);
1839 osi_auditU(call, BUDB_FndClnEvent, code, AUD_STR, volName, AUD_END);
1844 FindClone(struct rx_call *call, afs_int32 dumpID, char *volName,
1845 afs_int32 *clonetime)
1847 struct ubik_trans *ut;
1848 dbadr da, hvia, via, vfa;
1851 struct volFragment vf;
1853 int rvi; /* read the volInfo struct */
1854 afs_int32 eval, code = 0;
1856 if (!callPermitted(call))
1857 return BUDB_NOTPERMITTED;
1859 eval = InitRPC(&ut, LOCKREAD, 1);
1865 /* Search for the volume by name */
1866 eval = ht_LookupEntry(ut, &db.volName, volName, &hvia, &vi);
1870 ABORT(BUDB_NOVOLUMENAME);
1873 /* Follw the dump levels up */
1874 for (; dumpID; dumpID = ntohl(d.parent)) { /*d */
1875 /* Get the dump entry */
1876 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &da, &d);
1880 ABORT(BUDB_NODUMPID);
1882 /* seach all the volInfo entries on the sameNameChain */
1883 for (via = hvia; via; via = ntohl(vi.sameNameChain)) { /*via */
1884 if (rvi) { /* Read the volInfo entry - except first time */
1885 eval = dbread(ut, via, &vi, sizeof(vi));
1891 /* search all the volFrag entries on the volFrag */
1892 for (vfa = ntohl(vi.firstFragment); vfa; vfa = ntohl(vf.sameNameChain)) { /*vfa */
1893 eval = dbread(ut, vfa, &vf, sizeof(vf)); /* Read the volFrag entry */
1897 eval = dbread(ut, ntohl(vf.tape), &t, sizeof(t)); /* Read the tape */
1901 /* Now check to see if this fragment belongs to the dump we have */
1902 if (ntohl(t.dump) == da) {
1903 *clonetime = ntohl(vf.clone); /* return the clone */
1911 code = ubik_EndTrans(ut);
1921 * Searches each tape and each volume in the dump until the volume is found.
1922 * If the volume is not in the dump, then we search it's parent dump.
1924 * Re-write to do lookups by volume name.
1927 FindClone(struct rx_call *call, afs_int32 dumpID, char *volName,
1928 afs_int32 *clonetime)
1930 struct ubik_trans *ut;
1931 dbadr diskAddr, tapeAddr, volFragmentAddr;
1934 struct volFragment volFragment;
1935 struct volInfo volInfo;
1936 afs_int32 eval, code = 0;
1938 if (!callPermitted(call))
1939 return BUDB_NOTPERMITTED;
1941 eval = InitRPC(&ut, LOCKREAD, 1);
1947 for (; dumpID; dumpID = ntohl(dump.parent)) { /*d */
1948 /* Get the dump entry */
1949 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &diskAddr, &dump);
1953 ABORT(BUDB_NODUMPID);
1955 /* just to be sure */
1956 if (ntohl(dump.id) != dumpID) {
1957 LogDebug(4, "BUDB_FindClone: requested %d, found %d\n", dumpID,
1959 ABORT(BUDB_INTERNALERROR);
1962 /* search all the tapes in this dump */
1963 for (tapeAddr = ntohl(dump.firstTape); tapeAddr; tapeAddr = ntohl(tape.nextTape)) { /*t */
1964 /* Get the tape entry */
1965 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
1969 /* search all the volume fragments on this tape */
1970 for (volFragmentAddr = ntohl(tape.firstVol); volFragmentAddr; volFragmentAddr = ntohl(volFragment.sameTapeChain)) { /*vf */
1971 /* Get the volume fragment entry */
1973 dbread(ut, volFragmentAddr, &volFragment,
1974 sizeof(volFragment));
1978 /* Get the volume info entry */
1980 dbread(ut, ntohl(volFragment.vol), &volInfo,
1985 /* check if this volume is the one we want */
1986 if (strcmp(volInfo.name, volName) == 0) {
1987 *clonetime = ntohl(volFragment.clone);
1995 code = ubik_EndTrans(ut);
2005 * Find latest volume dump before adate.
2006 * Used by restore code when restoring a user requested volume(s)
2008 * volumeName - name of volume to match on
2009 * beforeDate - look for dumps older than this date
2011 * deptr - descriptor of most recent dump
2015 SBUDB_FindDump(struct rx_call *call, char *volumeName, afs_int32 beforeDate,
2016 struct budb_dumpEntry *deptr)
2020 code = FindDump(call, volumeName, beforeDate, deptr);
2021 osi_auditU(call, BUDB_FndDmpEvent, code, AUD_STR, volumeName, AUD_END);
2026 FindDump(struct rx_call *call, char *volumeName, afs_int32 beforeDate,
2027 struct budb_dumpEntry *deptr)
2029 struct ubik_trans *ut;
2030 dbadr volInfoAddr, volFragmentAddr;
2032 struct volInfo volInfo;
2033 struct volFragment volFragment;
2035 dbadr selectedDumpAddr = 0;
2036 afs_int32 selectedDate = 0;
2037 afs_int32 volCloned;
2039 afs_int32 eval, code = 0;
2041 if (!callPermitted(call))
2042 return BUDB_NOTPERMITTED;
2044 eval = InitRPC(&ut, LOCKREAD, 1);
2048 /* Find volinfo struct for volume name in hash table */
2050 ht_LookupEntry(ut, &db.volName, volumeName, &volInfoAddr, &volInfo);
2054 ABORT(BUDB_NOVOLUMENAME);
2056 /* Step through all the volinfo structures on the same name chain.
2057 * No need to read the first - we read it above.
2059 for (rvoli = 0; volInfoAddr;
2060 rvoli = 1, volInfoAddr = ntohl(volInfo.sameNameChain)) {
2061 if (rvoli) { /* read the volinfo structure */
2062 eval = dbread(ut, volInfoAddr, &volInfo, sizeof(volInfo));
2067 /* step through the volfrag structures */
2068 for (volFragmentAddr = ntohl(volInfo.firstFragment); volFragmentAddr;
2069 volFragmentAddr = ntohl(volFragment.sameNameChain)) {
2070 /* read the volfrag struct */
2072 dbread(ut, volFragmentAddr, &volFragment,
2073 sizeof(volFragment));
2077 volCloned = ntohl(volFragment.clone);
2079 /* now we can examine the date for most recent dump */
2080 if ((volCloned > selectedDate) && (volCloned < beforeDate)) {
2081 /* from the volfrag struct, read the tape struct */
2083 dbread(ut, ntohl(volFragment.tape), &tape, sizeof(tape));
2087 selectedDate = volCloned;
2088 selectedDumpAddr = ntohl(tape.dump);
2093 if (!selectedDumpAddr)
2096 eval = FillDumpEntry(ut, selectedDumpAddr, deptr);
2100 code = ubik_EndTrans(ut);
2108 /* BUDB_FindLatestDump
2109 * Find the latest dump of volumeset vsname with dump name dname.
2111 * vsname - volumeset name
2116 SBUDB_FindLatestDump(struct rx_call *call, char *vsname, char *dumpPath,
2117 struct budb_dumpEntry *dumpentry)
2121 code = FindLatestDump(call, vsname, dumpPath, dumpentry);
2122 osi_auditU(call, BUDB_FndLaDEvent, code, AUD_STR, vsname, AUD_END);
2127 FindLatestDump(struct rx_call *call, char *vsname, char *dumpPath,
2128 struct budb_dumpEntry *dumpentry)
2130 struct ubik_trans *ut;
2131 dbadr curdbaddr, retdbaddr, firstdbaddr;
2134 char dumpName[BU_MAXNAMELEN + 2];
2135 afs_int32 eval, code = 0;
2137 if (!callPermitted(call))
2138 return BUDB_NOTPERMITTED;
2140 eval = InitRPC(&ut, LOCKREAD, 1);
2144 if ((strcmp(vsname, "") == 0) && (strcmp(dumpPath, "") == 0)) {
2145 /* Construct a database dump name */
2146 strcpy(dumpName, DUMP_TAPE_NAME);
2147 } else if (strchr(dumpPath, '/') == 0) {
2148 int level, old, length, hash;
2149 struct dump hostDump, diskDump;
2150 struct memoryHashTable *mht;
2153 afs_uint32 bestDumpId = 0;
2155 level = atoi(dumpPath);
2157 ABORT(BUDB_BADARGUMENT);
2160 /* Brute force search of all the dumps in the database - yuck! */
2163 mht = ht_GetType(HT_dumpIden_FUNCTION, &entrySize);
2165 ABORT(BUDB_BADARGUMENT);
2167 for (old = 0; old <= 1; old++) { /*fo */
2168 length = (old ? mht->oldLength : mht->length);
2172 for (hash = 0; hash < length; hash++) {
2174 for (dbAddr = ht_LookupBucket(ut, mht, hash, old); dbAddr;
2175 dbAddr = hostDump.idHashChain) {
2177 eval = dbread(ut, dbAddr, &diskDump, sizeof(diskDump));
2180 dump_ntoh(&diskDump, &hostDump);
2182 if ((strcmp(hostDump.volumeSet, vsname) == 0) && /* the volumeset */
2183 (hostDump.level == level) && /* same level */
2184 (hostDump.id > bestDumpId)) { /* more recent */
2185 bestDumpId = hostDump.id;
2192 ABORT(BUDB_NODUMPNAME);
2196 /* construct the name of the dump */
2197 if ((strlen(vsname) + strlen(tailCompPtr(dumpPath))) > BU_MAXNAMELEN)
2198 ABORT(BUDB_NODUMPNAME);
2200 strcpy(dumpName, vsname);
2201 strcat(dumpName, ".");
2202 strcat(dumpName, tailCompPtr(dumpPath));
2205 LogDebug(5, "lookup on :%s:\n", dumpName);
2207 /* Lookup on dumpname in hash table */
2208 eval = ht_LookupEntry(ut, &db.dumpName, dumpName, &firstdbaddr, &d);
2215 /* folow remaining dumps in hash chain, looking for most latest dump */
2216 for (curdbaddr = firstdbaddr; curdbaddr;
2217 curdbaddr = ntohl(d.nameHashChain)) {
2218 if (curdbaddr != firstdbaddr) {
2219 eval = dbread(ut, curdbaddr, &d, sizeof(d));
2224 if ((strcmp(d.dumpPath, dumpPath) == 0) && /* Same dumppath */
2225 (strcmp(d.dumpName, dumpName) == 0) && /* Same dumpname */
2226 (ntohl(d.created) > latest)) { /* most recent */
2227 latest = ntohl(d.created);
2228 retdbaddr = curdbaddr;
2232 ABORT(BUDB_NODUMPNAME);
2235 /* return the dump found */
2236 FillDumpEntry(ut, retdbaddr, dumpentry);
2238 code = ubik_EndTrans(ut);
2242 ubik_AbortTrans(ut);
2248 SBUDB_FinishDump(struct rx_call *call, struct budb_dumpEntry *dump)
2252 code = FinishDump(call, dump);
2253 osi_auditU(call, BUDB_FinDmpEvent, code, AUD_DATE, (dump ? dump->id : 0),
2259 FinishDump(struct rx_call *call, struct budb_dumpEntry *dump)
2261 struct ubik_trans *ut;
2264 afs_int32 eval, code = 0;
2266 if (!callPermitted(call))
2267 return BUDB_NOTPERMITTED;
2269 eval = InitRPC(&ut, LOCKWRITE, 1);
2273 eval = ht_LookupEntry(ut, &db.dumpIden, &dump->id, &a, &d);
2277 ABORT(BUDB_NODUMPID);
2279 if ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)
2280 ABORT(BUDB_DUMPNOTINUSE);
2282 d.flags = htonl(dump->flags & ~BUDB_DUMP_INPROGRESS);
2284 /* if creation time specified set it */
2286 d.created = htonl(dump->created);
2287 dump->created = ntohl(d.created);
2289 /* Write the dump entry out */
2290 eval = dbwrite(ut, a, &d, sizeof(d));
2294 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2298 code = ubik_EndTrans(ut);
2302 ubik_AbortTrans(ut);
2307 SBUDB_FinishTape(struct rx_call *call, struct budb_tapeEntry *tape)
2311 code = FinishTape(call, tape);
2312 osi_auditU(call, BUDB_FinTpeEvent, code, AUD_DATE,
2313 (tape ? tape->dump : 0), AUD_END);
2318 FinishTape(struct rx_call *call, struct budb_tapeEntry *tape)
2320 struct ubik_trans *ut;
2324 afs_int32 eval, code = 0;
2326 if (!callPermitted(call))
2327 return BUDB_NOTPERMITTED;
2329 eval = InitRPC(&ut, LOCKWRITE, 1);
2333 /* find the tape struct in the tapename hash chain */
2334 eval = ht_LookupEntry(ut, &db.tapeName, tape->name, &a, &t);
2338 ABORT(BUDB_NOTAPENAME);
2340 /* Read the dump structure */
2341 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
2345 /* search for the right tape on the rest of the chain */
2346 while (ntohl(d.id) != tape->dump) {
2347 a = ntohl(t.nameHashChain);
2349 ABORT(BUDB_NOTAPENAME);
2351 eval = dbread(ut, a, &t, sizeof(t));
2355 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
2360 if ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0)
2361 ABORT(BUDB_TAPENOTINUSE);
2363 /* t.nBytes = htonl(tape->nBytes); */
2364 t.nFiles = htonl(tape->nFiles);
2365 t.useKBytes = htonl(tape->useKBytes);
2366 t.flags = htonl(tape->flags & ~BUDB_TAPE_BEINGWRITTEN);
2368 eval = dbwrite(ut, a, &t, sizeof(t));
2372 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2376 code = ubik_EndTrans(ut);
2380 ubik_AbortTrans(ut);
2385 * return a set of dumps that match the specified criteria
2388 * majorVersion - version of interface structures. Permits compatibility
2390 * flags - for search and select operations. Broken down into flags
2391 * for name, start point, end point and time.
2392 * name - name to search for. Interpretation based on flags
2399 * dbTimeP - time at which the database was last modified. Up to
2400 * caller (client) to take appropriate action if database
2401 * modified between successive calls
2402 * dumps - list of matching dumps
2404 * currently supported are:
2410 SBUDB_GetDumps(struct rx_call *call,
2411 afs_int32 majorVersion, /* version of interface structures */
2412 afs_int32 flags, /* search & select controls */
2413 char *name, /* s&s parameters */
2416 afs_int32 index, /* start index of returned entries */
2417 afs_int32 *nextIndexP, /* output index for next call */
2419 budb_dumpList *dumps) /* pointer to buffer */
2424 GetDumps(call, majorVersion, flags, name, start, end, index,
2425 nextIndexP, dbTimeP, dumps);
2426 osi_auditU(call, BUDB_GetDmpEvent, code, AUD_END);
2431 GetDumps(struct rx_call *call,
2432 afs_int32 majorVersion, /* version of interface structures */
2433 afs_int32 flags, /* search & select controls */
2434 char *name, /* s&s parameters */
2437 afs_int32 index, /* start index of returned entries */
2438 afs_int32 *nextIndexP, /* output index for next call */
2440 budb_dumpList *dumps) /* pointer to buffer */
2442 struct ubik_trans *ut;
2445 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
2446 afs_int32 eval, code = 0;
2448 struct returnList list;
2450 /* Don't check permissions when we look up a specific dump id */
2451 if (((flags & BUDB_OP_STARTS) != BUDB_OP_DUMPID) && !callPermitted(call))
2452 return BUDB_NOTPERMITTED;
2454 if (majorVersion != BUDB_MAJORVERSION)
2455 return BUDB_OLDINTERFACE;
2457 return BUDB_ENDOFLIST;
2459 eval = InitRPC(&ut, LOCKREAD, 1);
2463 nameFlags = flags & BUDB_OP_NAMES;
2464 startFlags = flags & BUDB_OP_STARTS;
2465 endFlags = flags & BUDB_OP_ENDS;
2466 timeFlags = flags & BUDB_OP_TIMES;
2468 InitReturnList(&list);
2471 if (nameFlags == BUDB_OP_DUMPNAME) {
2472 /* not yet implemented */
2473 if (startFlags || endFlags || timeFlags)
2474 ABORT(BUDB_BADFLAGS);
2476 eval = ht_LookupEntry(ut, &db.dumpName, name, &da, &d);
2480 ABORT(BUDB_NODUMPNAME);
2483 if (strcmp(d.dumpName, name) == 0) {
2484 eval = AddToReturnList(&list, da, &toskip);
2485 if (eval == BUDB_LIST2BIG)
2491 da = ntohl(d.nameHashChain); /* get next dump w/ name */
2495 eval = dbread(ut, da, &d, sizeof(d));
2499 } else if (nameFlags == BUDB_OP_VOLUMENAME) {
2503 LogError(0, "NYI, BUDB_OP_VOLUMENAME\n");
2504 ABORT(BUDB_BADFLAGS);
2507 if (startFlags != BUDB_OP_STARTTIME)
2508 ABORT(BUDB_BADFLAGS);
2510 /* lookup a dump by volumename and time stamp. Find the most recent
2511 * dump of the specified volumename, that occured before the supplied
2515 /* get us a volInfo for name */
2516 eval = ht_LookupEntry(ut, &db.volName, name, &da, &vi);
2521 /* now iterate over all the entries of this name */
2522 for (va = vi.firstFragment; va != 0; va = v.sameNameChain) {
2524 eval = dbread(ut, va, &v, sizeof(v));
2529 on fragment > date ignore it - too recent;
2531 if (date on fragment < date && date on fragment > bestfound)
2532 bestfound = date on fragment;
2536 da = vi.sameNameChain;
2540 eval = dbread(ut, da, &vi, sizeof(vi));
2549 from saved volfragment address, compute dump.
2550 otherwise, return dump found
2555 } else if (startFlags == BUDB_OP_DUMPID) {
2556 if (endFlags || timeFlags)
2557 ABORT(BUDB_BADFLAGS);
2559 ABORT(BUDB_BADFLAGS); /* NYI */
2561 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &da, &d);
2565 ABORT(BUDB_NODUMPID);
2567 eval = AddToReturnList(&list, da, &toskip);
2570 } else if (endFlags == BUDB_OP_NPREVIOUS) {
2571 struct wantDumpRock rock;
2572 struct chosenDump *ptr, *nextPtr;
2574 /* no other flags should be set */
2576 /* end specifies how many dumps */
2578 ABORT(BUDB_BADFLAGS);
2580 memset(&rock, 0, sizeof(rock));
2581 rock.maxDumps = end;
2583 scanHashTable(ut, &db.dumpName, wantDump, rememberDump,
2586 for (ptr = rock.chain; ptr; ptr = nextPtr) {
2587 nextPtr = ptr->next;
2588 AddToReturnList(&list, ptr->addr, &toskip); /* ignore error for free */
2592 ABORT(BUDB_BADFLAGS);
2596 SendReturnList(ut, &list, FillDumpEntry,
2597 sizeof(struct budb_dumpEntry), index, nextIndexP,
2598 dbTimeP, (returnList_t) dumps);
2602 FreeReturnList(&list);
2603 code = ubik_EndTrans(ut);
2607 FreeReturnList(&list);
2608 ubik_AbortTrans(ut);
2613 * Get the expiration of a tape. Since the dump could have appended dumps,
2614 * we should use the most recent expiration date. Put the most recent
2615 * expiration tape into the given tape structure.
2618 getExpiration(struct ubik_trans *ut, struct tape *tapePtr)
2624 afs_int32 eval, code = 0;
2629 /* Get the dump for this tape */
2630 ad = ntohl(tapePtr->dump);
2631 eval = dbread(ut, ad, &d, sizeof(d));
2635 /* If not an initial dump, get the initial dump */
2636 if (d.initialDumpID) {
2637 initDump = ntohl(d.initialDumpID);
2638 eval = ht_LookupEntry(ut, &db.dumpIden, &initDump, &ad, &d);
2643 /* Cycle through the dumps and appended dumps */
2645 /* Get the first tape in this dump. No need to check the rest of the tapes */
2646 /* for this dump since they will all have the same expiration date */
2647 eval = dbread(ut, ntohl(d.firstTape), &t, sizeof(t));
2651 /* Take the greater of the expiration dates */
2652 if (ntohl(tapePtr->expires) < ntohl(t.expires))
2653 tapePtr->expires = t.expires;
2655 /* Step to and read the next appended dump */
2656 if ((ad = ntohl(d.appendedDumpChain))) {
2657 eval = dbread(ut, ad, &d, sizeof(d));
2667 /* Mark the following dump as appended to another, intial dump */
2669 makeAppended(struct ubik_trans *ut, afs_int32 appendedDumpID,
2670 afs_int32 initialDumpID, afs_int32 startTapeSeq)
2672 dbadr ada, da, lastDumpAddr;
2674 afs_int32 eval, code = 0;
2678 if (appendedDumpID == initialDumpID)
2679 ERROR(BUDB_INTERNALERROR);
2681 /* If there is an initial dump, append this dump to it */
2682 /* Find the appended dump via its id */
2683 eval = ht_LookupEntry(ut, &db.dumpIden, &appendedDumpID, &ada, &ad);
2687 /* If the dump is already marked as appended,
2688 * then we have an internal error.
2690 if (ad.initialDumpID) {
2691 if (ntohl(ad.initialDumpID) != initialDumpID)
2692 ERROR(BUDB_INTERNALERROR);
2695 /* Update the appended dump to point to the initial dump */
2696 ad.initialDumpID = htonl(initialDumpID);
2697 ad.tapes.b = htonl(startTapeSeq);
2699 /* find the initial dump via its id */
2700 eval = ht_LookupEntry(ut, &db.dumpIden, &initialDumpID, &da, &d);
2704 /* Update the appended dump's tape format with that of the initial */
2705 strcpy(ad.tapes.format, d.tapes.format);
2707 /* starting with the initial dump step through its appended dumps till
2708 * we reach the last appended dump.
2711 while (d.appendedDumpChain) {
2712 lastDumpAddr = ntohl(d.appendedDumpChain);
2713 if (lastDumpAddr == ada)
2714 ERROR(0); /* Already appended */
2715 eval = dbread(ut, lastDumpAddr, &d, sizeof(d));
2720 /* Update the last dump to point to our new appended dump.
2721 * The appended dump is the last one in the dump chain.
2723 d.appendedDumpChain = htonl(ada);
2724 ad.appendedDumpChain = 0;
2726 /* Write the appended dump and the initial dump */
2727 eval = dbwrite(ut, ada, (char *)&ad, sizeof(ad));
2731 eval = dbwrite(ut, lastDumpAddr, (char *)&d, sizeof(d));
2735 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2744 SBUDB_MakeDumpAppended(struct rx_call *call, afs_int32 appendedDumpID,
2745 afs_int32 initialDumpID, afs_int32 startTapeSeq)
2750 MakeDumpAppended(call, appendedDumpID, initialDumpID, startTapeSeq);
2751 osi_auditU(call, BUDB_AppDmpEvent, code, AUD_LONG, appendedDumpID,
2757 MakeDumpAppended(struct rx_call *call, afs_int32 appendedDumpID,
2758 afs_int32 initialDumpID, afs_int32 startTapeSeq)
2760 struct ubik_trans *ut;
2761 afs_int32 eval, code = 0;
2763 if (!callPermitted(call))
2764 return BUDB_NOTPERMITTED;
2766 eval = InitRPC(&ut, LOCKWRITE, 1);
2770 eval = makeAppended(ut, appendedDumpID, initialDumpID, startTapeSeq);
2774 code = ubik_EndTrans(ut);
2778 ubik_AbortTrans(ut);
2782 /* Find the last tape of a dump-set. This includes any appended dumps */
2784 SBUDB_FindLastTape(struct rx_call *call, afs_int32 dumpID,
2785 struct budb_dumpEntry *dumpEntry,
2786 struct budb_tapeEntry *tapeEntry,
2787 struct budb_volumeEntry *volEntry)
2791 code = FindLastTape(call, dumpID, dumpEntry, tapeEntry, volEntry);
2792 osi_auditU(call, BUDB_FndLTpeEvent, code, AUD_LONG, dumpID, AUD_END);
2797 FindLastTape(struct rx_call *call, afs_int32 dumpID,
2798 struct budb_dumpEntry *dumpEntry,
2799 struct budb_tapeEntry *tapeEntry,
2800 struct budb_volumeEntry *volEntry)
2802 struct ubik_trans *ut;
2806 dbadr lastTape, thisTape;
2807 afs_int32 lastTapeSeq;
2808 struct volFragment vf;
2809 dbadr lastVol, thisVol;
2810 afs_int32 lastVolPos;
2811 afs_int32 eval, code = 0;
2813 if (!callPermitted(call))
2814 return BUDB_NOTPERMITTED;
2817 return (BUDB_BADARGUMENT);
2819 eval = InitRPC(&ut, LOCKREAD, 1);
2823 /* find and read its initial dump via its id */
2824 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &lastDump, &d);
2828 ABORT(BUDB_NODUMPID);
2830 /* Follow the append dumps link chain until we reach the last dump */
2831 while (d.appendedDumpChain) {
2832 lastDump = ntohl(d.appendedDumpChain);
2833 eval = dbread(ut, lastDump, &d, sizeof(d));
2838 /* We now have the last dump of the last appended dump */
2839 /* Copy this into our return structure */
2840 eval = FillDumpEntry(ut, lastDump, dumpEntry);
2844 /* Fail if the last dump has no tapes */
2846 ABORT(BUDB_NOTAPENAME);
2848 /* Follow the tapes in this dump until we reach the last tape */
2849 eval = dbread(ut, ntohl(d.firstTape), &t, sizeof(t));
2853 lastTape = ntohl(d.firstTape);
2854 lastTapeSeq = ntohl(t.seq);
2855 lastVol = ntohl(t.firstVol);
2857 while (t.nextTape) {
2858 thisTape = ntohl(t.nextTape);
2859 eval = dbread(ut, thisTape, &t, sizeof(t));
2863 if (ntohl(t.seq) > lastTapeSeq) {
2864 lastTape = thisTape;
2865 lastTapeSeq = ntohl(t.seq);
2866 lastVol = ntohl(t.firstVol);
2870 /* We now have the last tape of the last appended dump */
2871 /* Copy this into our return structure */
2872 eval = FillTapeEntry(ut, lastTape, tapeEntry);
2876 /* Zero volume entry if the last tape has no volumes */
2878 memset(volEntry, 0, sizeof(*volEntry));
2880 /* Follow the volumes until we reach the last volume */
2881 eval = dbread(ut, lastVol, &vf, sizeof(vf));
2885 lastVolPos = vf.position;
2887 while (vf.sameTapeChain) {
2888 thisVol = ntohl(vf.sameTapeChain);
2889 eval = dbread(ut, thisVol, &vf, sizeof(vf));
2893 if (vf.position > lastVolPos) {
2895 lastVolPos = vf.position;
2899 /* We now have the last volume of this tape */
2900 /* Copy this into our return structure */
2901 eval = FillVolEntry(ut, lastVol, volEntry);
2906 eval = ubik_EndTrans(ut);
2912 ubik_AbortTrans(ut);
2918 SBUDB_GetTapes(struct rx_call *call,
2919 afs_int32 majorVersion, /* version of interface structures */
2920 afs_int32 flags, /* search & select controls */
2921 char *name, /* s&s parameters */
2923 afs_int32 end, /* reserved: MBZ */
2924 afs_int32 index, /* start index of returned entries */
2925 afs_int32 *nextIndexP, /* output index for next call */
2927 budb_tapeList *tapes) /* pointer to buffer */
2932 GetTapes(call, majorVersion, flags, name, start, end, index,
2933 nextIndexP, dbTimeP, tapes);
2934 osi_auditU(call, BUDB_GetTpeEvent, code, AUD_END);
2939 GetTapes(struct rx_call *call,
2940 afs_int32 majorVersion, /* version of interface structures */
2941 afs_int32 flags, /* search & select controls */
2942 char *name, /* s&s parameters */
2944 afs_int32 end, /* reserved: MBZ */
2945 afs_int32 index, /* start index of returned entries */
2946 afs_int32 *nextIndexP, /* output index for next call */
2948 budb_tapeList *tapes) /* pointer to buffer */
2950 struct ubik_trans *ut;
2954 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
2955 struct returnList list;
2956 afs_int32 eval, code = 0;
2959 if (!callPermitted(call))
2960 return BUDB_NOTPERMITTED;
2962 if (majorVersion != BUDB_MAJORVERSION)
2963 return BUDB_OLDINTERFACE;
2966 return BUDB_ENDOFLIST;
2968 eval = InitRPC(&ut, LOCKREAD, 1);
2972 nameFlags = flags & BUDB_OP_NAMES;
2973 startFlags = flags & BUDB_OP_STARTS;
2974 endFlags = flags & BUDB_OP_ENDS;
2975 timeFlags = flags & BUDB_OP_TIMES;
2977 InitReturnList(&list);
2980 if (nameFlags == BUDB_OP_TAPENAME) { /*it */
2981 eval = ht_LookupEntry(ut, &db.tapeName, name, &ta, &t);
2985 ABORT(BUDB_NOTAPENAME);
2988 if ((startFlags & ~BUDB_OP_DUMPID) || endFlags || timeFlags)
2989 ABORT(BUDB_BADFLAGS);
2991 /* follow the hash chain to the end */
2993 if (startFlags & BUDB_OP_DUMPID) {
2994 /* read in the dump */
2995 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
2999 /* check if both name and dump id match */
3000 if ((strcmp(name, t.name) == 0) && (ntohl(d.id) == start)) {
3001 eval = AddToReturnList(&list, ta, &toskip);
3002 if (eval && (eval != BUDB_LIST2BIG))
3007 /* Add to return list and continue search */
3008 if (strcmp(name, t.name) == 0) {
3009 eval = AddToReturnList(&list, ta, &toskip);
3010 if (eval == BUDB_LIST2BIG)
3017 ta = ntohl(t.nameHashChain);
3019 dbread(ut, ta, &t, sizeof(t));
3022 else if (nameFlags == BUDB_OP_TAPESEQ) {
3023 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &da, &d);
3027 ABORT(BUDB_NODUMPNAME);
3029 /* search for the right tape */
3030 ta = ntohl(d.firstTape);
3031 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
3032 eval = dbread(ut, ta, &t, sizeof(t));
3036 if (ntohl(t.seq) == end) {
3037 eval = AddToReturnList(&list, ta, &toskip);
3038 if (eval && (eval != BUDB_LIST2BIG))
3044 ABORT(BUDB_BADFLAGS);
3048 SendReturnList(ut, &list, FillTapeEntry,
3049 sizeof(struct budb_tapeEntry), index, nextIndexP,
3050 dbTimeP, (returnList_t) tapes);
3054 FreeReturnList(&list);
3055 code = ubik_EndTrans(ut);
3059 FreeReturnList(&list);
3060 ubik_AbortTrans(ut);
3065 * get a set of volumes according to the specified criteria.
3066 * See BUDB_GetDumps for general information on parameters
3067 * Currently supports:
3068 * 1) volume match - returns volumes based on volume name only.
3069 * 2) flags = BUDB_OP_DUMPID in which case name is a volume name
3070 * and start is a dumpid. Returns all volumes of the specified
3071 * name on the selected dumpid.
3075 SBUDB_GetVolumes(struct rx_call *call,
3076 afs_int32 majorVersion, /* version of interface structures */
3077 afs_int32 flags, /* search & select controls */
3078 char *name, /* - parameters for search */
3079 afs_int32 start, /* - usage depends which BUDP_OP */
3080 afs_int32 end, /* - bits are set */
3081 afs_int32 index, /* start index of returned entries */
3082 afs_int32 *nextIndexP, /* output index for next call */
3084 budb_volumeList *volumes) /* pointer to buffer */
3089 GetVolumes(call, majorVersion, flags, name, start, end, index,
3090 nextIndexP, dbTimeP, volumes);
3091 osi_auditU(call, BUDB_GetVolEvent, code, AUD_END);
3096 GetVolumes(struct rx_call *call,
3097 afs_int32 majorVersion, /* version of interface structures */
3098 afs_int32 flags, /* search & select controls */
3099 char *name, /* - parameters for search */
3100 afs_int32 start, /* - usage depends which BUDP_OP_* */
3101 afs_int32 end, /* - bits are set */
3102 afs_int32 index, /* start index of returned entries */
3103 afs_int32 *nextIndexP, /* output index for next call */
3105 budb_volumeList *volumes) /* pointer to buffer */
3107 struct ubik_trans *ut;
3110 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
3111 afs_int32 eval, code = 0;
3112 struct returnList vollist;
3115 /* Don't check permissions when we look up a specific volume name */
3116 if (((flags & BUDB_OP_NAMES) != BUDB_OP_VOLUMENAME)
3117 && !callPermitted(call))
3118 return BUDB_NOTPERMITTED;
3120 if (majorVersion != BUDB_MAJORVERSION)
3121 return BUDB_OLDINTERFACE;
3123 return BUDB_ENDOFLIST;
3125 eval = InitRPC(&ut, LOCKREAD, 1);
3129 nameFlags = flags & BUDB_OP_NAMES;
3130 startFlags = flags & BUDB_OP_STARTS;
3131 endFlags = flags & BUDB_OP_ENDS;
3132 timeFlags = flags & BUDB_OP_TIMES;
3134 InitReturnList(&vollist);
3137 /* lookup a the volume (specified by name) in the dump (specified by id) */
3138 if (nameFlags == BUDB_OP_VOLUMENAME) {
3139 /* dumpid permissible, all others off */
3140 if (((startFlags & ~BUDB_OP_DUMPID) != 0) || endFlags || timeFlags)
3141 ABORT(BUDB_BADFLAGS);
3143 /* returns ptr to volinfo of requested name */
3144 eval = ht_LookupEntry(ut, &db.volName, name, &via, &vi);
3148 ABORT(BUDB_NOVOLUMENAME);
3150 /* Iterate over all volume fragments with this name */
3152 struct volFragment v;
3155 /* traverse all the volume fragments for this volume info structure */
3156 for (va = vi.firstFragment; va; va = v.sameNameChain) {
3158 eval = dbread(ut, va, &v, sizeof(v));
3162 if (startFlags & BUDB_OP_DUMPID) {
3166 /* get the dump id for this fragment */
3167 eval = dbread(ut, ntohl(v.tape), &atape, sizeof(atape));
3172 dbread(ut, ntohl(atape.dump), &adump, sizeof(adump));
3176 /* dump id does not match */
3177 if (ntohl(adump.id) != start)
3181 eval = AddToReturnList(&vollist, va, &toskip);
3182 if (eval == BUDB_LIST2BIG)
3187 if (eval == BUDB_LIST2BIG)
3190 via = vi.sameNameChain;
3195 eval = dbread(ut, via, &vi, sizeof(vi));
3199 } else if (((nameFlags == 0) || (nameFlags == BUDB_OP_TAPENAME))
3200 && (startFlags == BUDB_OP_DUMPID)) {
3205 struct volFragment volFrag;
3208 /* lookup all volumes for a specified dump id */
3210 /* no other flags should be set */
3211 if (endFlags || timeFlags)
3212 ABORT(BUDB_BADFLAGS);
3215 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &dumpAddr, &dump);
3219 /* traverse all the tapes */
3220 for (tapeAddr = ntohl(dump.firstTape); tapeAddr; tapeAddr = ntohl(tape.nextTape)) { /*w */
3221 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
3225 if ((nameFlags != BUDB_OP_TAPENAME)
3226 || ((nameFlags == BUDB_OP_TAPENAME)
3227 && (strcmp(tape.name, name) == 0))) {
3228 /* now return all the volumes */
3229 for (volFragAddr = ntohl(tape.firstVol); volFragAddr;
3230 volFragAddr = ntohl(volFrag.sameTapeChain)) {
3231 eval = dbread(ut, volFragAddr, &volFrag, sizeof(volFrag));
3235 eval = AddToReturnList(&vollist, volFragAddr, &toskip);
3236 if (eval == BUDB_LIST2BIG)
3242 if (eval == BUDB_LIST2BIG)
3246 ABORT(BUDB_BADFLAGS);
3250 SendReturnList(ut, &vollist, FillVolEntry,
3251 sizeof(struct budb_volumeEntry), index, nextIndexP,
3252 dbTimeP, (returnList_t) volumes);
3257 FreeReturnList(&vollist);
3258 code = ubik_EndTrans(ut);
3262 FreeReturnList(&vollist);
3263 ubik_AbortTrans(ut);
3268 SBUDB_UseTape(struct rx_call *call,
3269 struct budb_tapeEntry *tape, /* tape info */
3270 afs_int32 *new) /* set if tape is new */
3274 code = UseTape(call, tape, new);
3275 osi_auditU(call, BUDB_UseTpeEvent, code, AUD_DATE,
3276 (tape ? tape->dump : 0), AUD_END);
3281 UseTape(struct rx_call *call,
3282 struct budb_tapeEntry *tape, /* tape info */
3283 int *new) /* set if tape is new */
3285 struct ubik_trans *ut;
3289 afs_int32 eval, code;
3291 if (!callPermitted(call))
3292 return BUDB_NOTPERMITTED;
3294 if (strlen(tape->name) >= sizeof(t.name))
3295 return BUDB_BADARGUMENT;
3297 eval = InitRPC(&ut, LOCKWRITE, 1);
3303 memset(&t, 0, sizeof(t));
3304 eval = AllocStructure(ut, tape_BLOCK, 0, &a, &t);
3308 strcpy(t.name, tape->name);
3310 eval = ht_HashIn(ut, &db.tapeName, a, &t);
3316 /* Since deleting a tape may change the dump (if its the same one), read in
3317 * the dump after the call to DeleteTape. */
3319 eval = ht_LookupEntry(ut, &db.dumpIden, &tape->dump, &da, &d);
3323 ABORT(BUDB_NODUMPID);
3326 tape->written = time(0); /* fill in tape struct */
3327 t.written = htonl(tape->written);
3328 t.expires = htonl(tape->expires);
3330 t.seq = htonl(tape->seq);
3331 t.useCount = htonl(tape->useCount);
3332 t.labelpos = htonl(tape->labelpos);
3334 t.flags = htonl(tape->flags | BUDB_TAPE_BEINGWRITTEN);
3336 t.nextTape = d.firstTape; /* Chain the tape to the dump */
3337 d.firstTape = htonl(a);
3339 if (tape->seq >= ntohl(d.tapes.maxTapes)) /* inc # tapes in the dump */
3340 d.tapes.maxTapes = htonl(tape->seq);
3342 eval = dbwrite(ut, a, &t, sizeof(t)); /* write tape struct */
3346 eval = dbwrite(ut, da, &d, sizeof(d)); /* write the dump struct */
3350 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
3354 LogDebug(5, "added tape %s\n", tape->name);
3356 code = ubik_EndTrans(ut);
3360 ubik_AbortTrans(ut);
3366 /* ---------------------------------------------
3367 * debug interface routines
3368 * ---------------------------------------------
3372 SBUDB_T_DumpHashTable(struct rx_call *call, afs_int32 type, char *filename)
3376 code = T_DumpHashTable(call, type, filename);
3377 osi_auditU(call, BUDB_TDmpHaEvent, code, AUD_STR, filename, AUD_END);
3382 T_DumpHashTable(struct rx_call *call, int type, char *filename)
3384 struct ubik_trans *ut;
3385 struct memoryHashTable *mht;
3387 afs_int32 eval, code = 0;
3394 char e[sizeof(struct block)]; /* unnecessarily conservative */
3397 struct volInfo e_volinfo;
3401 if (!callPermitted(call))
3402 return BUDB_NOTPERMITTED;
3404 if (strlen(filename) >= sizeof(path) - 5)
3405 return BUDB_BADARGUMENT;
3407 eval = InitRPC(&ut, LOCKWRITE, 1);
3411 if ((mht = ht_GetType(type, &e_size)) == 0)
3412 return BUDB_BADARGUMENT;
3414 sprintf(path, "%s/%s", gettmpdir(), filename);
3416 DUMP = fopen(path, "w");
3418 ABORT(BUDB_BADARGUMENT);
3421 for (old = 0;; old++) {
3422 length = (old ? mht->oldLength : mht->length);
3424 fprintf(DUMP, "Dumping %sHash Table:\n", (old ? "Old " : ""));
3426 for (hash = 0; hash < length; hash++) {
3427 a = ht_LookupBucket(ut, mht, hash, old);
3430 eval = dbread(ut, a, e, e_size);
3436 fprintf(DUMP, " in bucket %d at %d is ", hash, a);
3438 fprintf(DUMP, " at %d is ", a);
3440 case HT_dumpIden_FUNCTION:
3441 memcpy(&e_dump, e, sizeof(e_dump));
3442 fprintf(DUMP, "%d\n", ntohl(e_dump.id));
3444 case HT_dumpName_FUNCTION:
3445 memcpy(&e_dump, e, sizeof(e_dump));
3446 fprintf(DUMP, "%s\n", e_dump.dumpName);
3448 case HT_tapeName_FUNCTION:
3449 memcpy(&e_tape, e, sizeof(e_tape));
3450 fprintf(DUMP, "%s\n", e_tape.name);
3452 case HT_volName_FUNCTION:
3453 memcpy(&e_volinfo, e, sizeof(e_volinfo));
3454 fprintf(DUMP, "%s\n", e_volinfo.name);
3457 if ((ht_HashEntry(mht, e) % length) != hash)
3458 ABORT(BUDB_DATABASEINCONSISTENT);
3459 a = ntohl(*(dbadr *) (e + mht->threadOffset));
3466 fprintf(DUMP, "%d entries found\n", ent);
3467 if (ntohl(mht->ht->entries) != ent)
3468 ABORT(BUDB_DATABASEINCONSISTENT);
3470 code = ubik_EndTrans(ut);
3476 ubik_AbortTrans(ut);
3483 SBUDB_T_GetVersion(struct rx_call *call, afs_int32 *majorVersion)
3487 code = T_GetVersion(call, majorVersion);
3488 osi_auditU(call, BUDB_TGetVrEvent, code, AUD_END);
3493 T_GetVersion(struct rx_call *call, int *majorVersion)
3495 struct ubik_trans *ut;
3498 code = InitRPC(&ut, LOCKREAD, 0);
3502 *majorVersion = BUDB_MAJORVERSION;
3504 code = ubik_EndTrans(ut);
3508 /* BUDB_T_DumpDatabase
3509 * dump as much of the database as possible int /tmp/<filename>
3513 SBUDB_T_DumpDatabase(struct rx_call *call, char *filename)
3517 code = T_DumpDatabase(call, filename);
3518 osi_auditU(call, BUDB_TDmpDBEvent, code, AUD_STR, filename, AUD_END);
3523 T_DumpDatabase(struct rx_call *call, char *filename)
3527 struct ubik_trans *ut;
3530 int type, old, length, hash;
3531 struct memoryHashTable *mht;
3532 afs_int32 eval, code = 0;
3534 if (!callPermitted(call))
3535 return BUDB_NOTPERMITTED;
3537 asprintf(&path, "%s/%s", gettmpdir(), filename);
3539 return (BUDB_INTERNALERROR);
3541 dumpfid = fopen(path, "w");
3543 return (BUDB_BADARGUMENT);
3545 eval = InitRPC(&ut, LOCKWRITE, 1);
3549 /* dump all items in the database */
3550 for (type = 1; type <= HT_MAX_FUNCTION; type++) { /*ft */
3551 mht = ht_GetType(type, &entrySize);
3553 ERROR(BUDB_BADARGUMENT);
3555 for (old = 0; old <= 1; old++) { /*fo */
3556 length = (old ? mht->oldLength : mht->length);
3560 fprintf(dumpfid, "Dumping %s Hash Table:\n", (old ? "Old " : ""));
3562 for (hash = 0; hash < length; hash++) { /*f */
3563 dbAddr = ht_LookupBucket(ut, mht, hash, old);
3565 while (dbAddr) { /*w */
3566 switch (type) { /*s */
3567 case HT_dumpIden_FUNCTION:
3569 struct dump hostDump, diskDump;
3572 cdbread(ut, dump_BLOCK, dbAddr, &diskDump,
3578 "\ndumpId hash %d, entry at %u\n",
3581 "----------------------------\n");
3582 dump_ntoh(&diskDump, &hostDump);
3583 printDump(dumpfid, &hostDump);
3584 dbAddr = hostDump.idHashChain;
3588 case HT_dumpName_FUNCTION:
3590 struct dump hostDump, diskDump;
3593 cdbread(ut, dump_BLOCK, dbAddr, &diskDump,
3599 "\ndumpname hash %d, entry at %u\n",
3602 "----------------------------\n");
3603 dump_ntoh(&diskDump, &hostDump);
3604 printDump(dumpfid, &hostDump);
3605 dbAddr = hostDump.nameHashChain;
3609 case HT_tapeName_FUNCTION:
3611 struct tape hostTape, diskTape;
3614 cdbread(ut, tape_BLOCK, dbAddr, &diskTape,
3620 "\ntapename hash %d, entry at %u\n",
3623 "----------------------------\n");
3624 tape_ntoh(&diskTape, &hostTape);
3625 printTape(dumpfid, &hostTape);
3626 dbAddr = hostTape.nameHashChain;
3630 case HT_volName_FUNCTION:
3632 struct volInfo hostVolInfo, diskVolInfo;
3635 cdbread(ut, volInfo_BLOCK, dbAddr,
3636 &diskVolInfo, sizeof(diskVolInfo));
3641 "\nvolname hash %d, entry at %u\n",
3644 "----------------------------\n");
3645 volInfo_ntoh(&diskVolInfo, &hostVolInfo);
3646 printVolInfo(dumpfid, &hostVolInfo);
3647 dbAddr = hostVolInfo.nameHashChain;
3649 volFragsDump(ut, dumpfid,
3650 hostVolInfo.firstFragment);
3655 fprintf(dumpfid, "unknown type %d\n", type);
3665 code = ubik_EndTrans(ut); /* is this safe if no ut started ? */
3674 volFragsDump(struct ubik_trans *ut, FILE *dumpfid, dbadr dbAddr)
3676 struct volFragment hostVolFragment, diskVolFragment;
3681 cdbread(ut, volFragment_BLOCK, dbAddr, &diskVolFragment,
3682 sizeof(diskVolFragment));
3683 if (code) { /* don't be fussy about errors */
3684 fprintf(dumpfid, "volFragsDump: Error reading database\n");
3688 fprintf(dumpfid, "\nvolfragment entry at %u\n", dbAddr);
3689 fprintf(dumpfid, "----------------------------\n");
3690 volFragment_ntoh(&diskVolFragment, &hostVolFragment);
3691 printVolFragment(dumpfid, &hostVolFragment);
3692 dbAddr = hostVolFragment.sameNameChain;
3698 /* utilities - network to host conversion
3699 * currently used for debug only
3703 volFragmentDiskToHost(struct volFragment *diskVfPtr,
3704 struct volFragment *hostVfPtr)
3706 hostVfPtr->vol = ntohl(diskVfPtr->vol);
3707 hostVfPtr->sameNameChain = ntohl(diskVfPtr->sameNameChain);
3708 hostVfPtr->tape = ntohl(diskVfPtr->tape);
3709 hostVfPtr->sameTapeChain = ntohl(diskVfPtr->sameTapeChain);
3710 hostVfPtr->position = ntohl(diskVfPtr->position);
3711 hostVfPtr->clone = ntohl(diskVfPtr->clone);
3712 hostVfPtr->incTime = ntohl(diskVfPtr->incTime);
3713 hostVfPtr->startByte = ntohl(diskVfPtr->startByte);
3714 hostVfPtr->nBytes = ntohl(diskVfPtr->nBytes);
3715 hostVfPtr->flags = ntohs(diskVfPtr->flags);
3716 hostVfPtr->sequence = ntohs(diskVfPtr->sequence);
3720 volInfoDiskToHost(struct volInfo *diskViPtr, struct volInfo *hostViPtr)
3722 strcpy(hostViPtr->name, diskViPtr->name);
3723 hostViPtr->nameHashChain = ntohl(diskViPtr->nameHashChain);
3724 hostViPtr->id = ntohl(diskViPtr->id);
3725 strcpy(hostViPtr->server, diskViPtr->server);
3726 hostViPtr->partition = ntohl(diskViPtr->partition);
3727 hostViPtr->flags = ntohl(diskViPtr->flags);
3728 hostViPtr->sameNameHead = ntohl(diskViPtr->sameNameHead);
3729 hostViPtr->sameNameChain = ntohl(diskViPtr->sameNameChain);
3730 hostViPtr->firstFragment = ntohl(diskViPtr->firstFragment);
3731 hostViPtr->nFrags = ntohl(diskViPtr->nFrags);
3735 tapeDiskToHost(struct tape *diskTapePtr, struct tape *hostTapePtr)
3737 strcpy(hostTapePtr->name, diskTapePtr->name);
3738 hostTapePtr->nameHashChain = ntohl(diskTapePtr->nameHashChain);
3739 hostTapePtr->flags = ntohl(diskTapePtr->flags);
3741 /* tape id conversion here */
3742 hostTapePtr->written = ntohl(diskTapePtr->written);
3743 hostTapePtr->nBytes = ntohl(diskTapePtr->nBytes);
3744 hostTapePtr->nFiles = ntohl(diskTapePtr->nFiles);
3745 hostTapePtr->nVolumes = ntohl(diskTapePtr->nVolumes);
3746 hostTapePtr->seq = ntohl(diskTapePtr->seq);
3747 hostTapePtr->dump = ntohl(diskTapePtr->dump);
3748 hostTapePtr->nextTape = ntohl(diskTapePtr->nextTape);
3749 hostTapePtr->firstVol = ntohl(diskTapePtr->firstVol);
3750 hostTapePtr->useCount = ntohl(diskTapePtr->useCount);
3754 dumpDiskToHost(struct dump *diskDumpPtr, struct dump *hostDumpPtr)
3756 hostDumpPtr->id = ntohl(diskDumpPtr->id);
3757 hostDumpPtr->idHashChain = ntohl(diskDumpPtr->idHashChain);
3758 strcpy(hostDumpPtr->dumpName, diskDumpPtr->dumpName);
3759 strcpy(hostDumpPtr->dumpPath, diskDumpPtr->dumpPath);
3760 strcpy(hostDumpPtr->volumeSet, diskDumpPtr->volumeSet);
3761 hostDumpPtr->nameHashChain = ntohl(diskDumpPtr->nameHashChain);
3762 hostDumpPtr->flags = ntohl(diskDumpPtr->flags);
3763 hostDumpPtr->parent = ntohl(diskDumpPtr->parent);
3764 hostDumpPtr->created = ntohl(diskDumpPtr->created);
3765 /* hostDumpPtr->incTime = ntohl(diskDumpPtr->incTime); */
3766 hostDumpPtr->nVolumes = ntohl(diskDumpPtr->nVolumes);
3768 /* tapeset conversion here */
3770 hostDumpPtr->firstTape = ntohl(diskDumpPtr->firstTape);
3772 /* principal conversion here */
3778 checkHash(struct ubik_trans *ut, int hashType)
3780 struct memoryHashTable *mhtPtr;
3781 int entrySize, hashTableLength;
3786 mhtPtr = ht_GetType(hashType, &entrySize);
3790 for (old = 0; old < 1; old++) {
3791 LogDebug(5, "\nold = %d\n", old);
3792 printMemoryHashTable(stdout, mhtPtr);
3794 hashTableLength = (old ? mhtPtr->oldLength : mhtPtr->length);
3796 for (bucket = 0; bucket < hashTableLength; bucket++) {
3799 entryAddr = ht_LookupBucket(ut, mhtPtr, bucket, old);
3800 while (entryAddr != 0) {
3801 LogDebug(6, "bucket %d has disk addr %d\n", bucket,
3804 case HT_dumpIden_FUNCTION:
3806 struct dump diskDump, hostDump;
3808 code = dbread(ut, entryAddr, &diskDump, entrySize);
3812 dump_ntoh(&diskDump, &hostDump);
3813 printDump(stdout, &hostDump);
3814 entryAddr = hostDump.idHashChain;
3818 case HT_dumpName_FUNCTION:
3821 case HT_tapeName_FUNCTION:
3824 case HT_volName_FUNCTION:
3826 struct volInfo diskVolInfo, hostVolInfo;
3828 code = dbread(ut, entryAddr, &diskVolInfo, entrySize);
3832 volInfo_ntoh(&diskVolInfo, &hostVolInfo);
3833 printVolInfo(stdout, &hostVolInfo);
3834 entryAddr = hostVolInfo.nameHashChain;