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>
25 #include <netinet/in.h>
27 #include <sys/param.h>
29 #include <sys/resource.h>
33 #include <sys/types.h>
35 #include <afs/bubasics.h>
44 #include <afs/cellconfig.h>
48 #include "budb_errs.h"
50 #include "error_macros.h"
52 #include "afs/audit.h"
53 #include <afs/afsutil.h>
59 extern struct ubik_dbase *BU_dbase;
60 extern struct afsconf_dir *BU_conf; /* for getting cell info */
62 afs_int32 AddVolume(), AddVolumes(), CreateDump(), DoDeleteDump(),
63 DoDeleteTape(), ListDumps();
64 afs_int32 DeleteVDP(), FindClone(), FindDump(), FindLatestDump();
65 afs_int32 FinishDump(), FinishTape(), GetDumps(), getExpiration(),
67 afs_int32 makeAppended(), MakeDumpAppended(), FindLastTape(), GetTapes();
68 afs_int32 GetVolumes(), UseTape(), T_DumpHashTable(), T_GetVersion();
70 /* Text block management */
73 struct memTextBlock *mtb_next; /* next in chain */
74 afs_int32 mtb_nbytes; /* # of bytes in this block */
75 struct blockHeader mtb_blkHeader; /* in memory header */
76 dbadr mtb_addr; /* disk address of block */
79 typedef struct memTextBlock memTextBlockT;
80 typedef memTextBlockT *memTextBlockP;
82 /* These variable are for returning debugging info about the state of the
83 server. If they get trashed during multi-threaded operation it doesn't
86 /* This is global so COUNT_REQ in krb_udp.c can refer to it. */
87 char *lastOperation; /* name of last operation */
88 static Date lastTrans; /* time of last transaction */
90 /* procsInited is sort of a lock: during a transaction only one process runs
91 while procsInited is false. */
93 static int procsInited = 0;
95 /* This variable is protected by the procsInited flag. */
97 static int (*rebuildDatabase) ();
99 /* AwaitInitialization
100 * Wait unitl budb has initialized (InitProcs). If it hasn't
101 * within 5 seconds, then return no quorum.
104 AwaitInitialization()
108 while (!procsInited) {
111 else if (time(0) - start > 5)
113 #ifdef AFS_PTHREAD_ENV
123 * name is a pathname style name, determine trailing name and return
128 tailCompPtr(pathNamePtr)
132 ptr = strrchr(pathNamePtr, '/');
134 /* this should never happen */
135 LogError(0, "tailCompPtr: could not find / in name(%s)\n",
137 return (pathNamePtr);
139 ptr++; /* skip the / */
144 * Check to see if the caller is a SuperUser.
152 struct rx_call *call;
155 struct afsconf_dir *acdir;
157 acdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
161 if (afsconf_SuperUser(acdir, call, NULL))
165 afsconf_Close(acdir);
170 * This is called by every RPC interface to create a Ubik transaction
171 * and read the database header into core
177 * sets a lock on byte 1 of the database. Looks like it enforces
178 * single threading by use of the lock.
182 InitRPC(ut, lock, this_op)
183 struct ubik_trans **ut;
184 int lock; /* indicate read/write transaction */
185 int this_op; /* opcode of RCP, for COUNT_ABO */
188 float wait = 0.91; /* start waiting for 1 second */
191 /* wait for server initialization to finish if this is not InitProcs calling */
193 if (code = AwaitInitialization())
196 for (code = UNOQUORUM; code == UNOQUORUM;) {
198 ubik_BeginTrans(BU_dbase,
200 LOCKREAD) ? UBIK_READTRANS : UBIK_WRITETRANS),
202 if (code == UNOQUORUM) { /* no quorum elected */
204 Log("Waiting for quorum election\n");
207 #ifdef AFS_PTHREAD_ENV
210 IOMGR_Sleep((int)wait);
217 Log("Have established quorum\n");
219 /* set lock at posiion 1, for 1 byte of type lock */
220 if (code = ubik_SetLock(*ut, 1, 1, lock)) {
221 ubik_AbortTrans(*ut);
225 /* check that dbase is initialized and setup cheader */
226 if (lock == LOCKREAD) {
227 /* init but don't fix because this is read only */
228 if (code = CheckInit(*ut, 0)) {
229 ubik_AbortTrans(*ut);
230 if (code = InitRPC(ut, LOCKWRITE, 0)) { /* Now fix the database */
231 LogError(code, "InitRPC: InitRPC failed\n");
234 if (code = ubik_EndTrans(*ut)) {
235 LogError(code, "InitRPC: ubik_EndTrans failed\n");
238 goto start; /* now redo the read transaction */
241 if (code = CheckInit(*ut, rebuildDatabase)) {
242 ubik_AbortTrans(*ut);
250 /* This is called to initialize a newly created database */
252 initialize_database(ut)
253 struct ubik_trans *ut;
258 static int noAuthenticationRequired; /* global state */
259 static int recheckNoAuth; /* global state */
264 struct ubik_trans *ut;
269 if ((globalConfPtr->myHost == 0) || (BU_conf == 0))
270 ERROR(BUDB_INTERNALERROR);
274 if (globalConfPtr->debugFlags & DF_NOAUTH)
275 noAuthenticationRequired = 1;
277 if (globalConfPtr->debugFlags & DF_RECHECKNOAUTH)
281 noAuthenticationRequired = afsconf_GetNoAuthFlag(BU_conf);
283 if (noAuthenticationRequired)
284 LogError(0, "Running server with security disabled\n");
288 rebuildDatabase = initialize_database;
290 if (code = InitRPC(&ut, LOCKREAD, 0)) {
291 LogError(code, "InitProcs: InitRPC failed\n");
294 code = ubik_EndTrans(ut);
296 LogError(code, "InitProcs: ubik_EndTrans failed\n");
300 rebuildDatabase = 0; /* only do this during init */
308 int nElements; /* number in list */
309 int allocSize; /* number of elements allocated */
310 dbadr *elements; /* array of addresses */
315 struct returnList *list;
319 list->elements = (dbadr *) 0;
324 struct returnList *list;
327 free(list->elements);
328 list->elements = (dbadr *) 0;
332 /* As entries are collected, they are added to a return list. Once all
333 * entries have been collected, it is then placed in the return buffer
334 * with SendReturnList(). The first *to_skipP are not recorded.
337 AddToReturnList(list, a, to_skipP)
338 struct returnList *list;
352 /* Up to 5 plus a maximum so SendReturnList() knows if we
353 * need to come back for more.
355 if (list->nElements >= BUDB_MAX_RETURN_LIST + 5)
356 return BUDB_LIST2BIG;
358 if (list->nElements >= list->allocSize) {
359 if (list->elements == 0) {
361 tmp = (char *)malloc(sizeof(dbadr) * size);
363 size = list->allocSize + 10;
364 tmp = (char *)realloc(list->elements, sizeof(dbadr) * size);
368 list->elements = (dbadr *) tmp;
369 list->allocSize = size;
372 list->elements[list->nElements] = a;
378 FillVolEntry(ut, va, vol)
379 struct ubik_trans *ut;
381 struct budb_volumeEntry *vol;
386 struct volFragment vf;
388 if (dbread(ut, va, &vf, sizeof(vf)))
389 return BUDB_IO; /* The volFrag */
390 if (dbread(ut, ntohl(vf.vol), &vi, sizeof(vi)))
391 return BUDB_IO; /* The volInfo */
392 if (dbread(ut, ntohl(vf.tape), &t, sizeof(t)))
393 return BUDB_IO; /* The tape */
394 if (dbread(ut, ntohl(t.dump), &d, sizeof(d)))
395 return BUDB_IO; /* The dump */
397 strcpy(vol->name, vi.name);
398 strcpy(vol->server, vi.server);
399 strcpy(vol->tape, t.name);
400 vol->tapeSeq = ntohl(t.seq);
401 vol->dump = ntohl(d.id);
402 vol->position = ntohl(vf.position);
403 vol->clone = ntohl(vf.clone);
404 vol->incTime = ntohl(vf.incTime);
405 vol->nBytes = ntohl(vf.nBytes);
406 vol->startByte = ntohl(vf.startByte);
407 vol->flags = (ntohs(vf.flags) & VOLFRAGMENTFLAGS); /* low 16 bits here */
408 vol->flags |= (ntohl(vi.flags) & VOLINFOFLAGS); /* high 16 bits here */
409 vol->seq = ntohs(vf.sequence);
410 vol->id = ntohl(vi.id);
411 vol->partition = ntohl(vi.partition);
417 FillDumpEntry(ut, da, dump)
418 struct ubik_trans *ut;
420 struct budb_dumpEntry *dump;
424 if (dbread(ut, da, &d, sizeof(d)))
426 dump->id = ntohl(d.id);
427 dump->flags = ntohl(d.flags);
428 dump->created = ntohl(d.created);
429 strncpy(dump->name, d.dumpName, sizeof(dump->name));
430 strncpy(dump->dumpPath, d.dumpPath, sizeof(dump->dumpPath));
431 strncpy(dump->volumeSetName, d.volumeSet, sizeof(dump->volumeSetName));
433 dump->parent = ntohl(d.parent);
434 dump->level = ntohl(d.level);
435 dump->nVolumes = ntohl(d.nVolumes);
437 tapeSet_ntoh(&d.tapes, &dump->tapes);
439 if (strlen(d.dumper.name) < sizeof(dump->dumper.name))
440 strcpy(dump->dumper.name, d.dumper.name);
441 if (strlen(d.dumper.instance) < sizeof(dump->dumper.instance))
442 strcpy(dump->dumper.instance, d.dumper.instance);
443 if (strlen(d.dumper.cell) < sizeof(dump->dumper.cell))
444 strcpy(dump->dumper.cell, d.dumper.cell);
446 /* Get the initial dumpid and the appended dump id */
447 dump->initialDumpID = ntohl(d.initialDumpID);
448 if (d.appendedDumpChain) {
449 if (dbread(ut, ntohl(d.appendedDumpChain), &ad, sizeof(ad)))
451 dump->appendedDumpID = ntohl(ad.id);
453 dump->appendedDumpID = 0;
455 /* printf("dump name %s, parent %d, level %d\n",
456 * d.dumpName, ntohl(d.parent), ntohl(d.level)); */
462 FillTapeEntry(ut, ta, tape)
463 struct ubik_trans *ut;
465 struct budb_tapeEntry *tape;
471 if (dbread(ut, ta, &t, sizeof(t)))
474 /* Get the tape's expiration date */
475 if (code = getExpiration(ut, &t))
478 strcpy(tape->name, t.name);
479 tape->flags = ntohl(t.flags);
480 tape->written = ntohl(t.written);
481 tape->expires = ntohl(t.expires);
482 tape->nMBytes = ntohl(t.nMBytes);
483 tape->nBytes = ntohl(t.nBytes);
484 tape->nFiles = ntohl(t.nFiles);
485 tape->nVolumes = ntohl(t.nVolumes);
486 tape->seq = ntohl(t.seq);
487 tape->labelpos = ntohl(t.labelpos);
488 tape->useCount = ntohl(t.useCount);
489 tape->useKBytes = ntohl(t.useKBytes);
491 if (dbread(ut, ntohl(t.dump), &d, sizeof(d)))
493 tape->dump = ntohl(d.id);
497 #define returnList_t budb_dumpList *
500 * A list of elements of size e_size is in list, collected
501 * with AddToReturnList(). We will move this to a correspoding
502 * return list, eList, via FillProc(). nextInodeP tells us
503 * if there are more and how many to skip on the next request.
506 SendReturnList(ut, list, FillProc, e_size, index, nextIndexP, dbTimeP, eList)
507 struct ubik_trans *ut;
508 struct returnList *list; /* list of elements to return */
509 afs_int32(*FillProc) (); /* proc to fill entry */
510 int e_size; /* size of each element */
511 afs_int32 index; /* index from previous call */
512 afs_int32 *nextIndexP; /* if more elements are available */
513 afs_int32 *dbTimeP; /* time of last db update */
514 budb_dumpList *eList; /* rxgen list structure (e.g.) */
522 *dbTimeP = ntohl(db.h.lastUpdate);
524 /* Calculate how many to return. Don't let if go over
525 * BUDB_MAX_RETURN_LIST nor the size of our return list.
527 to_return = list->nElements;
528 if (to_return > BUDB_MAX_RETURN_LIST)
529 to_return = BUDB_MAX_RETURN_LIST;
530 if (eList->budb_dumpList_len && (to_return > eList->budb_dumpList_len))
531 to_return = eList->budb_dumpList_len;
533 /* Allocate space for the return values if needed and zero it */
534 if (eList->budb_dumpList_val == 0) {
535 eList->budb_dumpList_val =
536 (struct budb_dumpEntry *)malloc(e_size * to_return);
537 if (!eList->budb_dumpList_val)
540 memset(eList->budb_dumpList_val, 0, e_size * to_return);
541 eList->budb_dumpList_len = to_return;
543 e = (char *)(eList->budb_dumpList_val);
544 for (i = 0; i < to_return; i++, e += e_size) {
545 code = (*FillProc) (ut, list->elements[i], e);
550 if (list->nElements > i)
551 *nextIndexP = index + i;
555 /* Come here to delete a volInfo structure. */
558 DeleteVolInfo(ut, via, vi)
559 struct ubik_trans *ut;
567 if (vi->firstFragment)
568 return 0; /* still some frags, don't free yet */
569 if (vi->sameNameHead == 0) { /* this is the head */
570 if (vi->sameNameChain)
571 return 0; /* empty head, some non-heads left */
573 code = ht_HashOut(ut, &db.volName, via, vi);
576 code = FreeStructure(ut, volInfo_BLOCK, via);
579 hvia = ntohl(vi->sameNameHead);
580 if (dbread(ut, hvia, &hvi, sizeof(hvi)))
583 RemoveFromList(ut, hvia, &hvi, &hvi.sameNameChain, via, vi,
586 return BUDB_DATABASEINCONSISTENT;
588 code = FreeStructure(ut, volInfo_BLOCK, via);
592 /* Detach a volume fragment from its volInfo structure. Its tape chain is
593 already freed. This routine frees the structure and the caller must not
597 DeleteVolFragment(ut, va, v)
598 struct ubik_trans *ut;
600 struct volFragment *v;
607 if (dbread(ut, via, &vi, sizeof(vi)))
610 RemoveFromList(ut, via, &vi, &vi.firstFragment, va, v,
613 return BUDB_DATABASEINCONSISTENT;
616 if (vi.firstFragment == 0)
617 if (code = DeleteVolInfo(ut, via, &vi))
619 if (code = FreeStructure(ut, volFragment_BLOCK, va))
622 /* decrement frag counter */
624 set_word_addr(ut, via, &vi, &vi.nFrags, htonl(ntohl(vi.nFrags) - 1));
630 /* DeleteTape - by freeing all its volumes and removing it from its dump chain.
631 * The caller will remove it from the hash table if necessary. The caller is
632 * also responsible for writing the tape out if necessary. */
635 DeleteTape(ut, ta, t)
636 struct ubik_trans *ut;
646 return BUDB_DATABASEINCONSISTENT;
647 if (dbread(ut, da, &d, sizeof(d)))
649 if (d.firstTape == 0)
650 return BUDB_DATABASEINCONSISTENT;
652 code = RemoveFromList(ut, da, &d, &d.firstTape, ta, t, &t->nextTape);
654 return BUDB_DATABASEINCONSISTENT;
658 /* Since the tape should have been truncated there should never be any
659 * volumes in the tape. */
660 if (t->firstVol || t->nVolumes)
661 return BUDB_DATABASEINCONSISTENT;
667 DeleteDump(ut, da, d)
668 struct ubik_trans *ut;
674 code = ht_HashOut(ut, &db.dumpIden, da, d);
678 code = ht_HashOut(ut, &db.dumpName, da, d);
682 /* Since the tape should have been truncated this should never happen. */
683 if (d->firstTape || d->nVolumes)
684 ERROR(BUDB_DATABASEINCONSISTENT);
686 code = FreeStructure(ut, dump_BLOCK, da);
697 * This is called with a volumeEntry and a volInfo structure and compares
698 * them. It returns non-zero if they are equal. It is used by GetVolInfo to
699 * search volInfo structures once it has the head volInfo structure from the
700 * volName hash table.
702 * When called from GetVolInfo the name compare is redundant.
703 * Always AND the flags with VOLINFOFLAGS for backwards compatability (3.3).
707 VolInfoMatch(vol, vi)
708 struct budb_volumeEntry *vol;
711 return ((strcmp(vol->name, vi->name) == 0) && /* same volume name */
712 (vol->id == ntohl(vi->id)) && /* same volume id */
713 ((vol->flags & VOLINFOFLAGS) == (ntohl(vi->flags) & VOLINFOFLAGS)) && /* same flags */
714 (vol->partition == ntohl(vi->partition)) && /* same partition (N/A) */
715 (strcmp(vol->server, vi->server) == 0)); /* same server (N/A) */
720 * This routine takes a volumeEntry structure from an RPC interface and
721 * returns the corresponding volInfo structure, creating it if necessary.
723 * The caller must write the entry out.
727 GetVolInfo(ut, volP, viaP, viP)
728 struct ubik_trans *ut;
729 struct budb_volumeEntry *volP;
735 afs_int32 eval, code = 0;
737 eval = ht_LookupEntry(ut, &db.volName, volP->name, &via, viP);
742 /* allocate a new volinfo structure */
743 eval = AllocStructure(ut, volInfo_BLOCK, 0, &via, viP);
747 strcpy(viP->name, volP->name);
748 strcpy(viP->server, volP->server);
749 viP->sameNameHead = 0; /* The head of same name chain */
750 viP->sameNameChain = 0; /* Same name chain is empty */
751 viP->firstFragment = 0;
753 viP->id = htonl(volP->id);
754 viP->partition = htonl(volP->partition);
755 viP->flags = htonl(volP->flags & VOLINFOFLAGS);
757 /* Chain onto volname hash table */
758 eval = ht_HashIn(ut, &db.volName, via, viP);
762 LogDebug(4, "volume Info for %s placed at %d\n", db.volName, via);
765 else if (!VolInfoMatch(volP, viP)) { /* Not the head volinfo struct */
766 hvia = via; /* remember the head volinfo struct */
767 memcpy(&hvi, viP, sizeof(hvi));
769 /* Search the same name chain for the correct volinfo structure */
770 for (via = ntohl(viP->sameNameChain); via;
771 via = ntohl(viP->sameNameChain)) {
772 eval = dbread(ut, via, viP, sizeof(*viP));
776 if (VolInfoMatch(volP, viP))
777 break; /* found the one */
780 /* if the correct volinfo struct isn't found, create one */
782 eval = AllocStructure(ut, volInfo_BLOCK, 0, &via, viP);
786 strcpy(viP->name, volP->name);
787 strcpy(viP->server, volP->server);
788 viP->nameHashChain = 0; /* not in hash table */
789 viP->sameNameHead = htonl(hvia); /* chain to head of sameNameChain */
790 viP->sameNameChain = hvi.sameNameChain;
791 viP->firstFragment = 0;
793 viP->id = htonl(volP->id);
794 viP->partition = htonl(volP->partition);
795 viP->flags = htonl(volP->flags & VOLINFOFLAGS);
797 /* write the head entry's sameNameChain link */
799 set_word_addr(ut, hvia, &hvi, &hvi.sameNameChain, htonl(via));
811 /* deletesomevolumesfromtape
812 * Deletes a specified number of volumes from a tape. The tape
813 * and dump are modified to reflect the smaller number of volumes.
814 * The transaction is not terminated, it is up to the caller to
815 * finish the transaction and start a new one (if desired).
817 * maxvolumestodelete - don't delete more than this many volumes
821 deleteSomeVolumesFromTape(ut, tapeAddr, tapePtr, maxVolumesToDelete)
822 struct ubik_trans *ut;
824 struct tape *tapePtr;
825 int maxVolumesToDelete;
827 dbadr volFragAddr, nextVolFragAddr, dumpAddr;
828 struct volFragment volFrag;
830 int volumesDeleted = 0;
831 afs_int32 eval, code = 0;
836 for (volFragAddr = ntohl(tapePtr->firstVol);
837 (volFragAddr && (maxVolumesToDelete > 0));
838 volFragAddr = nextVolFragAddr) {
839 eval = dbread(ut, volFragAddr, &volFrag, sizeof(volFrag));
843 nextVolFragAddr = ntohl(volFrag.sameTapeChain);
845 eval = DeleteVolFragment(ut, volFragAddr, &volFrag);
849 maxVolumesToDelete--;
853 /* reset the volume fragment pointer in the tape */
854 tapePtr->firstVol = htonl(volFragAddr);
856 /* diminish the tape's volume count */
857 tapePtr->nVolumes = htonl(ntohl(tapePtr->nVolumes) - volumesDeleted);
859 eval = dbwrite(ut, tapeAddr, tapePtr, sizeof(*tapePtr));
863 /* diminish the dump's volume count */
864 dumpAddr = ntohl(tapePtr->dump);
865 eval = dbread(ut, dumpAddr, &dump, sizeof(dump));
869 dump.nVolumes = htonl(ntohl(dump.nVolumes) - volumesDeleted);
870 eval = dbwrite(ut, dumpAddr, &dump, sizeof(dump));
879 * deletes a dump in stages, by repeatedly deleting a small number of
880 * volumes from the dump until none are left. The dump is then deleted.
882 * In the case where multiple calls are made to delete the same
883 * dump, the operation will succeed but contention for structures
884 * will result in someone getting back an error.
887 * id - id of dump to delete
891 deleteDump(call, id, dumps)
892 struct rx_call *call;
894 budb_dumpsList *dumps;
896 struct ubik_trans *ut;
897 dbadr dumpAddr, tapeAddr, appendedDump;
901 afs_int32 eval, code = 0;
904 /* iterate until the dump is truly deleted */
910 eval = InitRPC(&ut, LOCKWRITE, 1);
912 ERROR(eval); /* can't start transaction */
915 ht_LookupEntry(ut, &db.dumpIden, &dumpid, &dumpAddr, &dump);
919 ABORT(BUDB_NOENT); /* can't find dump */
921 if ((dumpid == id) && (dump.initialDumpID)) /* can't be an appended dump */
922 ABORT(BUDB_NOTINITIALDUMP);
924 tapeAddr = ntohl(dump.firstTape);
928 /* there is a tape to delete */
929 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
933 if (ntohl(tape.nVolumes)) {
934 /* tape is not empty */
935 eval = deleteSomeVolumesFromTape(ut, tapeAddr, &tape, 10);
940 if (ntohl(tape.nVolumes) == 0) {
941 /* tape is now empty, delete it */
942 eval = DeleteTape(ut, tapeAddr, &tape);
945 eval = ht_HashOut(ut, &db.tapeName, tapeAddr, &tape);
948 eval = FreeStructure(ut, tape_BLOCK, tapeAddr);
953 eval = ubik_EndTrans(ut);
957 } /* next deletion portion */
959 /* Record the dump just deleted */
960 if (dumps && (dumps->budb_dumpsList_len < BUDB_MAX_RETURN_LIST)) {
961 if (dumps->budb_dumpsList_len == 0)
962 dumps->budb_dumpsList_val =
963 (afs_int32 *) malloc(sizeof(afs_int32));
965 dumps->budb_dumpsList_val =
966 (afs_int32 *) realloc(dumps->budb_dumpsList_val,
967 (dumps->budb_dumpsList_len +
968 1) * sizeof(afs_int32));
970 if (!dumps->budb_dumpsList_val)
973 dumps->budb_dumpsList_val[dumps->budb_dumpsList_len] = dumpid;
974 dumps->budb_dumpsList_len++;
977 appendedDump = ntohl(dump.appendedDumpChain);
979 /* finally done. No more tapes left in the dump. Delete the dump itself */
980 eval = DeleteDump(ut, dumpAddr, &dump);
984 /* Now delete the appended dump too */
986 eval = dbread(ut, appendedDump, &dump, sizeof(dump));
990 dumpid = ntohl(dump.id);
994 eval = ubik_EndTrans(ut);
998 Log("Delete dump %s (DumpID %u), path %s\n", dump.dumpName,
999 ntohl(dump.id), dump.dumpPath);
1003 if (code && partialDel) {
1004 Log("Delete dump %s (DumpID %u), path %s - INCOMPLETE (code = %u)\n",
1005 dump.dumpName, ntohl(dump.id), dump.dumpPath, code);
1010 ubik_AbortTrans(ut);
1015 * dump selection routines - used by BUDB_GetDumps
1019 /* most recent dump selection */
1022 struct chosenDump *next;
1027 struct wantDumpRock {
1028 int maxDumps; /* max wanted */
1029 int ndumps; /* actual in chain */
1030 struct chosenDump *chain;
1035 wantDump(dumpAddrParam, dumpParam, dumpListPtrParam)
1036 char *dumpAddrParam;
1038 char *dumpListPtrParam;
1041 struct dump *dumpPtr;
1042 struct wantDumpRock *rockPtr;
1044 dumpAddr = (dbadr) dumpAddrParam;
1045 dumpPtr = (struct dump *)dumpParam;
1046 rockPtr = (struct wantDumpRock *)dumpListPtrParam;
1048 /* if we don't have our full complement, just add another */
1049 if (rockPtr->ndumps < rockPtr->maxDumps)
1052 /* got the number we need, select based on date */
1053 if ((afs_uint32) ntohl(dumpPtr->created) > rockPtr->chain->date)
1060 rememberDump(dumpAddrParam, dumpParam, dumpListPtrParam)
1061 char *dumpAddrParam;
1063 char *dumpListPtrParam;
1066 struct dump *dumpPtr;
1067 struct wantDumpRock *rockPtr;
1068 struct chosenDump *ptr, *deletedPtr, **nextPtr;
1070 dumpAddr = (dbadr) dumpAddrParam;
1071 dumpPtr = (struct dump *)dumpParam;
1072 rockPtr = (struct wantDumpRock *)dumpListPtrParam;
1074 ptr = (struct chosenDump *)malloc(sizeof(*ptr));
1077 memset(ptr, 0, sizeof(*ptr));
1078 ptr->addr = dumpAddr;
1079 ptr->date = (afs_uint32) ntohl(dumpPtr->created);
1081 /* Don't overflow the max */
1082 while (rockPtr->ndumps >= rockPtr->maxDumps) {
1083 /* have to drop one */
1084 deletedPtr = rockPtr->chain;
1085 rockPtr->chain = deletedPtr->next;
1090 /* now insert in the right place */
1091 for (nextPtr = &rockPtr->chain; *nextPtr; nextPtr = &((*nextPtr)->next)) {
1092 if (ptr->date < (*nextPtr)->date)
1095 ptr->next = *nextPtr;
1103 /* ---------------------------------------------
1104 * general interface routines - alphabetic
1105 * ---------------------------------------------
1109 SBUDB_AddVolume(call, vol)
1110 struct rx_call *call;
1111 struct budb_volumeEntry *vol;
1115 code = AddVolume(call, vol);
1116 osi_auditU(call, BUDB_AddVolEvent, code, AUD_LONG, (vol ? vol->id : 0),
1122 AddVolume(call, vol)
1123 struct rx_call *call;
1124 struct budb_volumeEntry *vol;
1126 struct ubik_trans *ut;
1127 dbadr da, ta, via, va;
1131 struct volFragment v;
1133 afs_int32 eval, code = 0;
1135 if (!callPermitted(call))
1136 return BUDB_NOTPERMITTED;
1138 if ((strlen(vol->name) >= sizeof(vi.name))
1139 || (strlen(vol->server) >= sizeof(vi.server))
1140 || (strlen(vol->tape) >= sizeof(t.name)))
1141 return BUDB_BADARGUMENT;
1143 eval = InitRPC(&ut, LOCKWRITE, 1);
1147 /* Find the dump in dumpid hash table */
1148 eval = ht_LookupEntry(ut, &db.dumpIden, &vol->dump, &da, &d);
1152 ABORT(BUDB_NODUMPID);
1154 /* search for the right tape in the dump */
1155 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
1156 /* read the tape entry */
1157 eval = dbread(ut, ta, &t, sizeof(t));
1161 /* Check if the right tape name */
1162 if (strcmp(t.name, vol->tape) == 0)
1166 ABORT(BUDB_NOTAPENAME);
1168 if ((t.dump != htonl(da)) || /* tape must belong to dump */
1169 ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0) || /* tape must be being written */
1170 ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)) /* dump must be in progress */
1171 ABORT(BUDB_BADPROTOCOL);
1173 /* find or create a volume info structure */
1174 eval = GetVolInfo(ut, vol, &via, &vi);
1178 /* Create a volume fragment */
1179 eval = AllocStructure(ut, volFragment_BLOCK, 0, &va, &v);
1183 v.vol = htonl(via); /* vol frag points to vol info */
1184 v.sameNameChain = vi.firstFragment; /* vol frag is chained to vol info */
1185 vi.firstFragment = htonl(va);
1186 vi.nFrags = htonl(ntohl(vi.nFrags) + 1);
1188 eval = dbwrite(ut, via, &vi, sizeof(vi)); /* write the vol info struct */
1192 v.tape = htonl(ta); /* vol frag points to tape */
1193 v.sameTapeChain = t.firstVol; /* vol frag is chained to tape info */
1194 t.firstVol = htonl(va);
1195 t.nVolumes = htonl(ntohl(t.nVolumes) + 1);
1196 bytes = ntohl(t.nBytes) + vol->nBytes; /* update bytes on tape */
1197 t.nMBytes = htonl(ntohl(t.nMBytes) + bytes / (1024 * 1024));
1198 t.nBytes = htonl(bytes % (1024 * 1024));
1200 eval = dbwrite(ut, ta, &t, sizeof(t)); /* write the tape structure */
1204 d.nVolumes = htonl(ntohl(d.nVolumes) + 1); /* one more volume on dump */
1206 eval = dbwrite(ut, da, &d, sizeof(d)); /* write out the dump structure */
1210 v.position = htonl(vol->position); /* vol frag info */
1211 v.clone = htonl(vol->clone);
1212 v.incTime = htonl(vol->incTime);
1213 v.startByte = htonl(vol->startByte);
1214 v.nBytes = htonl(vol->nBytes);
1215 v.flags = htons(vol->flags & VOLFRAGMENTFLAGS);
1216 v.sequence = htons(vol->seq);
1218 eval = dbwrite(ut, va, &v, sizeof(v)); /* write out the vol frag struct */
1222 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1226 LogDebug(4, "added volume %s at %d\n", vol->name, va);
1228 code = ubik_EndTrans(ut);
1232 ubik_AbortTrans(ut);
1238 SBUDB_AddVolumes(call, vols)
1239 struct rx_call *call;
1240 struct budb_volumeList *vols;
1244 code = AddVolumes(call, vols);
1245 osi_auditU(call, BUDB_AddVolEvent, code, AUD_LONG, 0, AUD_END);
1250 AddVolumes(call, vols)
1251 struct rx_call *call;
1252 struct budb_volumeList *vols;
1254 struct budb_volumeEntry *vol, *vol1;
1255 struct ubik_trans *ut;
1256 dbadr da, ta, via, va;
1260 struct volFragment v;
1262 afs_int32 eval, e, code = 0;
1264 if (!callPermitted(call))
1265 return BUDB_NOTPERMITTED;
1267 if (!vols || (vols->budb_volumeList_len <= 0)
1268 || !vols->budb_volumeList_val)
1269 return BUDB_BADARGUMENT;
1271 /* The first volume in the list of volumes to add */
1272 vol1 = (struct budb_volumeEntry *)vols->budb_volumeList_val;
1274 eval = InitRPC(&ut, LOCKWRITE, 1);
1278 /* Find the dump in dumpid hash table */
1279 eval = ht_LookupEntry(ut, &db.dumpIden, &vol1->dump, &da, &d);
1283 ABORT(BUDB_NODUMPID);
1285 /* search for the right tape in the dump */
1286 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
1287 /* read the tape entry */
1288 eval = dbread(ut, ta, &t, sizeof(t));
1292 /* Check if the right tape name */
1293 if (strcmp(t.name, vol1->tape) == 0)
1297 ABORT(BUDB_NOTAPENAME);
1299 if ((t.dump != htonl(da)) || /* tape must belong to dump */
1300 ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0) || /* tape must be being written */
1301 ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)) /* dump must be in progress */
1302 ABORT(BUDB_BADPROTOCOL);
1304 for (vol = vol1, e = 0; e < vols->budb_volumeList_len; vol++, e++) {
1306 if ((strlen(vol->name) >= sizeof(vi.name)) || (strcmp(vol->name, "") == 0) || /* no null volnames */
1307 (strlen(vol->server) >= sizeof(vi.server))
1308 || (strlen(vol->tape) >= sizeof(t.name))
1309 || (strcmp(vol->tape, vol1->tape) != 0)) {
1310 Log("Volume '%s' %u, tape '%s', dumpID %u is an invalid entry - not added\n", vol->name, vol->id, vol->tape, vol->dump);
1314 /* find or create a volume info structure */
1315 eval = GetVolInfo(ut, vol, &via, &vi);
1318 if (*(afs_int32 *) (&vi) == 0) {
1319 Log("Volume '%s', tape '%s', dumpID %u is an invalid entry - aborted\n", vol->name, vol->tape, vol->dump);
1320 ABORT(BUDB_BADARGUMENT);
1323 /* Create a volume fragment */
1324 eval = AllocStructure(ut, volFragment_BLOCK, 0, &va, &v);
1328 v.vol = htonl(via); /* vol frag points to vol info */
1329 v.sameNameChain = vi.firstFragment; /* vol frag is chained to vol info */
1330 vi.firstFragment = htonl(va);
1331 vi.nFrags = htonl(ntohl(vi.nFrags) + 1);
1332 eval = dbwrite(ut, via, &vi, sizeof(vi)); /* write the vol info struct */
1336 v.tape = htonl(ta); /* vol frag points to tape */
1337 v.sameTapeChain = t.firstVol; /* vol frag is chained to tape info */
1338 t.firstVol = htonl(va);
1339 t.nVolumes = htonl(ntohl(t.nVolumes) + 1);
1340 bytes = ntohl(t.nBytes) + vol->nBytes; /* update bytes on tape */
1341 t.nMBytes = htonl(ntohl(t.nMBytes) + bytes / (1024 * 1024));
1342 t.nBytes = htonl(bytes % (1024 * 1024));
1344 d.nVolumes = htonl(ntohl(d.nVolumes) + 1); /* one more volume on dump */
1346 v.position = htonl(vol->position); /* vol frag info */
1347 v.clone = htonl(vol->clone);
1348 v.incTime = htonl(vol->incTime);
1349 v.startByte = htonl(vol->startByte);
1350 v.nBytes = htonl(vol->nBytes);
1351 v.flags = htons(vol->flags & VOLFRAGMENTFLAGS);
1352 v.sequence = htons(vol->seq);
1354 eval = dbwrite(ut, va, &v, sizeof(v)); /* write out the vol frag struct */
1358 LogDebug(4, "added volume %s at %d\n", vol->name, va);
1361 eval = dbwrite(ut, ta, &t, sizeof(t)); /* write the tape structure */
1365 eval = dbwrite(ut, da, &d, sizeof(d)); /* write out the dump structure */
1369 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1373 code = ubik_EndTrans(ut);
1377 ubik_AbortTrans(ut);
1383 * records the existence of a dump in the database. This creates only
1384 * the dump record, to which one must attach tape and volume records.
1386 * 1) record the volume set
1390 SBUDB_CreateDump(call, dump)
1391 struct rx_call *call;
1392 struct budb_dumpEntry *dump;
1396 code = CreateDump(call, dump);
1397 osi_auditU(call, BUDB_CrDmpEvent, code, AUD_DATE, (dump ? dump->id : 0),
1399 if (dump && !code) {
1400 Log("Create dump %s (DumpID %u), path %s\n", dump->name, dump->id,
1407 CreateDump(call, dump)
1408 struct rx_call *call;
1409 struct budb_dumpEntry *dump;
1411 struct ubik_trans *ut;
1412 dbadr findDumpAddr, da;
1413 struct dump findDump, d;
1414 afs_int32 eval, code = 0;
1418 Date expiration; /* checked by Security Module */
1419 struct ktc_principal principal;
1421 if (!callPermitted(call))
1422 return BUDB_NOTPERMITTED;
1424 if (strlen(dump->name) >= sizeof(d.dumpName))
1425 return BUDB_BADARGUMENT;
1427 eval = InitRPC(&ut, LOCKWRITE, 1);
1432 rxkad_GetServerInfo(rx_ConnectionOf(call), &level, &expiration,
1433 principal.name, principal.instance,
1434 principal.cell, &kvno);
1437 if (eval != RXKADNOAUTH)
1440 strcpy(principal.name, "");
1441 strcpy(principal.instance, "");
1442 strcpy(principal.cell, "");
1445 /* authenticated. Take user supplied principal information */
1446 if (strcmp(dump->dumper.name, "") != 0)
1447 strncpy(principal.name, dump->dumper.name,
1448 sizeof(principal.name));
1450 if (strcmp(dump->dumper.instance, "") != 0)
1451 strncpy(principal.instance, dump->dumper.instance,
1452 sizeof(principal.instance));
1454 if (strcmp(dump->dumper.cell, "") != 0)
1455 strncpy(principal.cell, dump->dumper.cell,
1456 sizeof(principal.cell));
1459 /* dump id's are time stamps */
1461 while (1) { /* allocate a unique dump id *//*w */
1464 /* ensure it is unique - seach for dumpid in hash table */
1466 ht_LookupEntry(ut, &db.dumpIden, &dump->id, &findDumpAddr,
1471 if (!findDumpAddr) { /* dumpid not in use */
1472 /* update the last dump id allocated */
1473 eval = set_header_word(ut, lastDumpId, htonl(dump->id));
1479 /* dump id is in use - wait a while */
1480 #ifdef AFS_PTHREAD_ENV
1487 /* dump id supplied (e.g. for database restore) */
1489 ht_LookupEntry(ut, &db.dumpIden, &dump->id, &findDumpAddr,
1494 /* Dump id must not already exist */
1496 ABORT(BUDB_DUMPIDEXISTS);
1499 /* Allocate a dump structure */
1500 memset(&d, 0, sizeof(d));
1501 eval = AllocStructure(ut, dump_BLOCK, 0, &da, &d);
1505 strcpy(d.dumpName, dump->name); /* volset.dumpname */
1506 strcpy(d.dumpPath, dump->dumpPath); /* dump node path */
1507 strcpy(d.volumeSet, dump->volumeSetName); /* volume set */
1508 d.id = htonl(dump->id);
1509 d.parent = htonl(dump->parent); /* parent id */
1510 d.level = htonl(dump->level);
1512 LogDebug(4, "dump name %s, parent %d level %d\n", dump->name,
1513 dump->parent, dump->level);
1515 /* if creation time specified, use that. Else use the dumpid time */
1516 if (dump->created == 0)
1517 dump->created = dump->id;
1518 d.created = htonl(dump->created);
1520 principal_hton(&principal, &d.dumper);
1521 tapeSet_hton(&dump->tapes, &d.tapes);
1523 d.flags = htonl(dump->flags | BUDB_DUMP_INPROGRESS);
1525 eval = ht_HashIn(ut, &db.dumpName, da, &d); /* Into dump name hash table */
1529 eval = ht_HashIn(ut, &db.dumpIden, da, &d); /* Into dumpid hash table */
1533 eval = dbwrite(ut, da, (char *)&d, sizeof(d)); /* Write the dump structure */
1537 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1541 /* If to append this dump, then append it - will write the appended dump */
1542 eval = makeAppended(ut, dump->id, dump->initialDumpID, dump->tapes.b);
1546 code = ubik_EndTrans(ut);
1547 LogDebug(5, "made dump %s, path %s\n", d.dumpName, d.dumpPath);
1551 ubik_AbortTrans(ut);
1556 SBUDB_DeleteDump(call, id, fromTime, toTime, dumps)
1557 struct rx_call *call;
1561 budb_dumpsList *dumps;
1565 code = DoDeleteDump(call, id, fromTime, toTime, dumps);
1566 osi_auditU(call, BUDB_DelDmpEvent, code, AUD_DATE, id, AUD_END);
1573 DoDeleteDump(call, id, fromTime, toTime, dumps)
1574 struct rx_call *call;
1578 budb_dumpsList *dumps;
1582 if (!callPermitted(call))
1583 return BUDB_NOTPERMITTED;
1586 code = deleteDump(call, id, dumps);
1591 SBUDB_ListDumps(call, sflags, name, groupid, fromTime, toTime, dumps, flags)
1592 struct rx_call *call;
1593 afs_int32 sflags, groupid;
1595 Date fromTime, toTime;
1596 budb_dumpsList *dumps, *flags;
1600 code = ListDumps(call, sflags, groupid, fromTime, toTime, dumps, flags);
1601 osi_auditU(call, BUDB_LstDmpEvent, code, AUD_LONG, flags, AUD_END);
1606 ListDumps(call, sflags, groupid, fromTime, toTime, dumps, flags)
1607 struct rx_call *call;
1608 afs_int32 sflags, groupid;
1609 Date fromTime, toTime;
1610 budb_dumpsList *dumps, *flags;
1612 struct ubik_trans *ut;
1613 struct memoryHashTable *mht;
1614 struct dump diskDump, appDiskDump;
1615 dbadr dbAddr, dbAppAddr;
1617 afs_int32 eval, code = 0;
1618 int old, hash, length, entrySize, count = 0;
1620 if (!callPermitted(call))
1621 return BUDB_NOTPERMITTED;
1623 eval = InitRPC(&ut, LOCKREAD, 1);
1627 /* Search the database */
1628 mht = ht_GetType(HT_dumpIden_FUNCTION, &entrySize);
1630 return (BUDB_BADARGUMENT);
1632 for (old = 0; old <= 1; old++) { /*o *//* old and new hash tables */
1633 length = (old ? mht->oldLength : mht->length);
1637 for (hash = 0; hash < length; hash++) { /*h *//* for each hash bucket */
1638 for (dbAddr = ht_LookupBucket(ut, mht, hash, old); dbAddr; dbAddr = ntohl(diskDump.idHashChain)) { /*d */
1640 /* read the entry */
1641 eval = dbread(ut, dbAddr, &diskDump, sizeof(diskDump));
1645 /* Skip appended dumps */
1646 if (ntohl(diskDump.initialDumpID) != 0) {
1650 /* Skip dumps with different goup id */
1651 if ((sflags & BUDB_OP_GROUPID)
1652 && (ntohl(diskDump.tapes.id) != groupid)) {
1656 /* Look at this dump to see if it meets the criteria for listing */
1657 if (sflags & BUDB_OP_DATES) {
1658 /* This and each appended dump should be in time */
1659 for (dbAppAddr = dbAddr; dbAppAddr;
1660 dbAppAddr = ntohl(appDiskDump.appendedDumpChain)) {
1662 dbread(ut, dbAppAddr, &appDiskDump,
1663 sizeof(appDiskDump));
1667 if ((ntohl(appDiskDump.id) < fromTime)
1668 || (ntohl(appDiskDump.id) > toTime))
1675 /* Add it and each of its appended dump to our list to return */
1676 for (dbAppAddr = dbAddr; dbAppAddr;
1677 dbAppAddr = ntohl(appDiskDump.appendedDumpChain)) {
1679 dbread(ut, dbAppAddr, &appDiskDump,
1680 sizeof(appDiskDump));
1684 /* Make sure we have space to list it */
1685 if (dumps->budb_dumpsList_len >= count) {
1688 dumps->budb_dumpsList_val =
1689 (afs_int32 *) malloc(count *
1691 flags->budb_dumpsList_val =
1692 (afs_int32 *) malloc(count *
1695 dumps->budb_dumpsList_val =
1696 (afs_int32 *) realloc(dumps->
1700 flags->budb_dumpsList_val =
1701 (afs_int32 *) realloc(flags->
1706 if (!dumps->budb_dumpsList_val
1707 || !dumps->budb_dumpsList_val)
1711 /* Add it to our list */
1712 dumps->budb_dumpsList_val[dumps->budb_dumpsList_len] =
1713 ntohl(appDiskDump.id);
1714 flags->budb_dumpsList_val[flags->budb_dumpsList_len] = 0;
1715 if (ntohl(appDiskDump.initialDumpID) != 0) {
1716 flags->budb_dumpsList_val[flags->
1717 budb_dumpsList_len] |=
1720 if (strcmp(appDiskDump.dumpName, DUMP_TAPE_NAME) == 0) {
1721 flags->budb_dumpsList_val[flags->
1722 budb_dumpsList_len] |=
1725 dumps->budb_dumpsList_len++;
1726 flags->budb_dumpsList_len++;
1732 code = ubik_EndTrans(ut);
1736 ubik_AbortTrans(ut);
1741 SBUDB_DeleteTape(call, tape)
1742 struct rx_call *call;
1743 struct budb_tapeEntry *tape; /* tape info */
1747 code = DoDeleteTape(call, tape);
1748 osi_auditU(call, BUDB_DelTpeEvent, code, AUD_DATE,
1749 (tape ? tape->dump : 0), AUD_END);
1754 DoDeleteTape(call, tape)
1755 struct rx_call *call;
1756 struct budb_tapeEntry *tape; /* tape info */
1758 struct ubik_trans *ut;
1761 afs_int32 eval, code;
1763 if (!callPermitted(call))
1764 return BUDB_NOTPERMITTED;
1766 eval = InitRPC(&ut, LOCKWRITE, 1);
1770 eval = ht_LookupEntry(ut, &db.tapeName, tape->name, &a, &t);
1774 eval = DeleteTape(ut, a, &t);
1778 eval = FreeStructure(ut, tape_BLOCK, a);
1782 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
1786 code = ubik_EndTrans(ut);
1790 ubik_AbortTrans(ut);
1795 * Deletes old information from the database for a particular dump path
1796 * and volumset. This supercedes the old policy implemented in
1797 * UseTape, which simply matched on the volumeset.dump. Consequently
1798 * it was unable to handle name re-use.
1800 * dsname - dumpset name, i.e. volumeset.dumpname
1801 * dumpPath - full path of dump node
1802 * curDumpID - current dump in progress - so that is may be excluded
1805 * n - some error. May or may not have deleted information.
1809 SBUDB_DeleteVDP(call, dsname, dumpPath, curDumpId)
1810 struct rx_call *call;
1813 afs_int32 curDumpId;
1817 code = DeleteVDP(call, dsname, dumpPath, curDumpId);
1818 osi_auditU(call, BUDB_DelVDPEvent, code, AUD_STR, dsname, AUD_END);
1823 DeleteVDP(call, dsname, dumpPath, curDumpId)
1824 struct rx_call *call;
1827 afs_int32 curDumpId;
1832 struct ubik_trans *ut;
1833 afs_int32 eval, code = 0;
1835 if (!callPermitted(call))
1836 return BUDB_NOTPERMITTED;
1839 eval = InitRPC(&ut, LOCKREAD, 1);
1843 eval = ht_LookupEntry(ut, &db.dumpName, dsname, &dumpAddr, &dump);
1847 while (dumpAddr != 0) { /*wd */
1848 if ((strcmp(dump.dumpName, dsname) == 0)
1849 && (strcmp(dump.dumpPath, dumpPath) == 0)
1850 && (ntohl(dump.id) != curDumpId)) {
1851 eval = ubik_EndTrans(ut);
1855 eval = deleteDump(call, ntohl(dump.id), 0);
1859 /* start the traversal over since the various chains may
1865 dumpAddr = ntohl(dump.nameHashChain);
1867 eval = dbread(ut, dumpAddr, &dump, sizeof(dump));
1873 /* check if all the dumps have been examined - can terminate */
1875 eval = ubik_EndTrans(ut);
1881 ubik_AbortTrans(ut);
1887 * Given a volume name, and a dumpID, find the volume in that dump and
1888 * return the clone date of the volume (this is the clone date of the
1889 * volume at the time it was dumped).
1891 * Hashes on the volume name and traverses the fragments. Will need to read
1892 * the volumes tape entry to determine if it belongs to the dump. If the
1893 * volume is not found in the dump, then look for it in its parent dump.
1897 SBUDB_FindClone(call, dumpID, volName, clonetime)
1898 struct rx_call *call;
1901 afs_int32 *clonetime;
1905 code = FindClone(call, dumpID, volName, clonetime);
1906 osi_auditU(call, BUDB_FndClnEvent, code, AUD_STR, volName, AUD_END);
1911 FindClone(call, dumpID, volName, clonetime)
1912 struct rx_call *call;
1915 afs_int32 *clonetime;
1917 struct ubik_trans *ut;
1918 dbadr da, hvia, via, vfa;
1921 struct volFragment vf;
1923 int rvi; /* read the volInfo struct */
1924 afs_int32 eval, code = 0;
1926 if (!callPermitted(call))
1927 return BUDB_NOTPERMITTED;
1929 eval = InitRPC(&ut, LOCKREAD, 1);
1935 /* Search for the volume by name */
1936 eval = ht_LookupEntry(ut, &db.volName, volName, &hvia, &vi);
1940 ABORT(BUDB_NOVOLUMENAME);
1943 /* Follw the dump levels up */
1944 for (; dumpID; dumpID = ntohl(d.parent)) { /*d */
1945 /* Get the dump entry */
1946 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &da, &d);
1950 ABORT(BUDB_NODUMPID);
1952 /* seach all the volInfo entries on the sameNameChain */
1953 for (via = hvia; via; via = ntohl(vi.sameNameChain)) { /*via */
1954 if (rvi) { /* Read the volInfo entry - except first time */
1955 eval = dbread(ut, via, &vi, sizeof(vi));
1961 /* search all the volFrag entries on the volFrag */
1962 for (vfa = ntohl(vi.firstFragment); vfa; vfa = ntohl(vf.sameNameChain)) { /*vfa */
1963 eval = dbread(ut, vfa, &vf, sizeof(vf)); /* Read the volFrag entry */
1967 eval = dbread(ut, ntohl(vf.tape), &t, sizeof(t)); /* Read the tape */
1971 /* Now check to see if this fragment belongs to the dump we have */
1972 if (ntohl(t.dump) == da) {
1973 *clonetime = ntohl(vf.clone); /* return the clone */
1981 code = ubik_EndTrans(ut);
1991 * Searches each tape and each volume in the dump until the volume is found.
1992 * If the volume is not in the dump, then we search it's parent dump.
1994 * Re-write to do lookups by volume name.
1997 FindClone(call, dumpID, volName, clonetime)
1998 struct rx_call *call;
2001 afs_int32 *clonetime;
2003 struct ubik_trans *ut;
2004 dbadr diskAddr, tapeAddr, volFragmentAddr;
2007 struct volFragment volFragment;
2008 struct volInfo volInfo;
2009 afs_int32 eval, code = 0;
2011 if (!callPermitted(call))
2012 return BUDB_NOTPERMITTED;
2014 eval = InitRPC(&ut, LOCKREAD, 1);
2020 for (; dumpID; dumpID = ntohl(dump.parent)) { /*d */
2021 /* Get the dump entry */
2022 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &diskAddr, &dump);
2026 ABORT(BUDB_NODUMPID);
2028 /* just to be sure */
2029 if (ntohl(dump.id) != dumpID) {
2030 LogDebug(4, "BUDB_FindClone: requested %d, found %d\n", dumpID,
2032 ABORT(BUDB_INTERNALERROR);
2035 /* search all the tapes in this dump */
2036 for (tapeAddr = ntohl(dump.firstTape); tapeAddr; tapeAddr = ntohl(tape.nextTape)) { /*t */
2037 /* Get the tape entry */
2038 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
2042 /* search all the volume fragments on this tape */
2043 for (volFragmentAddr = ntohl(tape.firstVol); volFragmentAddr; volFragmentAddr = ntohl(volFragment.sameTapeChain)) { /*vf */
2044 /* Get the volume fragment entry */
2046 dbread(ut, volFragmentAddr, &volFragment,
2047 sizeof(volFragment));
2051 /* Get the volume info entry */
2053 dbread(ut, ntohl(volFragment.vol), &volInfo,
2058 /* check if this volume is the one we want */
2059 if (strcmp(volInfo.name, volName) == 0) {
2060 *clonetime = ntohl(volFragment.clone);
2068 code = ubik_EndTrans(ut);
2078 * Find latest volume dump before adate.
2079 * Used by restore code when restoring a user requested volume(s)
2081 * volumeName - name of volume to match on
2082 * beforeDate - look for dumps older than this date
2084 * deptr - descriptor of most recent dump
2088 SBUDB_FindDump(call, volumeName, beforeDate, deptr)
2089 struct rx_call *call;
2091 afs_int32 beforeDate;
2092 struct budb_dumpEntry *deptr;
2096 code = FindDump(call, volumeName, beforeDate, deptr);
2097 osi_auditU(call, BUDB_FndDmpEvent, code, AUD_STR, volumeName, AUD_END);
2102 FindDump(call, volumeName, beforeDate, deptr)
2103 struct rx_call *call;
2105 afs_int32 beforeDate;
2106 struct budb_dumpEntry *deptr;
2108 struct ubik_trans *ut;
2109 dbadr volInfoAddr, volFragmentAddr;
2111 struct volInfo volInfo;
2112 struct volFragment volFragment;
2114 dbadr selectedDumpAddr = 0;
2115 afs_int32 selectedDate = 0;
2116 afs_int32 volCloned;
2118 afs_int32 eval, code = 0;
2120 if (!callPermitted(call))
2121 return BUDB_NOTPERMITTED;
2123 eval = InitRPC(&ut, LOCKREAD, 1);
2127 /* Find volinfo struct for volume name in hash table */
2129 ht_LookupEntry(ut, &db.volName, volumeName, &volInfoAddr, &volInfo);
2133 ABORT(BUDB_NOVOLUMENAME);
2135 /* Step through all the volinfo structures on the same name chain.
2136 * No need to read the first - we read it above.
2138 for (rvoli = 0; volInfoAddr;
2139 rvoli = 1, volInfoAddr = ntohl(volInfo.sameNameChain)) {
2140 if (rvoli) { /* read the volinfo structure */
2141 eval = dbread(ut, volInfoAddr, &volInfo, sizeof(volInfo));
2146 /* step through the volfrag structures */
2147 for (volFragmentAddr = ntohl(volInfo.firstFragment); volFragmentAddr;
2148 volFragmentAddr = ntohl(volFragment.sameNameChain)) {
2149 /* read the volfrag struct */
2151 dbread(ut, volFragmentAddr, &volFragment,
2152 sizeof(volFragment));
2156 volCloned = ntohl(volFragment.clone);
2158 /* now we can examine the date for most recent dump */
2159 if ((volCloned > selectedDate) && (volCloned < beforeDate)) {
2160 /* from the volfrag struct, read the tape struct */
2162 dbread(ut, ntohl(volFragment.tape), &tape, sizeof(tape));
2166 selectedDate = volCloned;
2167 selectedDumpAddr = ntohl(tape.dump);
2172 if (!selectedDumpAddr)
2175 eval = FillDumpEntry(ut, selectedDumpAddr, deptr);
2179 code = ubik_EndTrans(ut);
2187 /* BUDB_FindLatestDump
2188 * Find the latest dump of volumeset vsname with dump name dname.
2190 * vsname - volumeset name
2195 SBUDB_FindLatestDump(call, vsname, dumpPath, dumpentry)
2196 struct rx_call *call;
2197 char *vsname, *dumpPath;
2198 struct budb_dumpEntry *dumpentry;
2202 code = FindLatestDump(call, vsname, dumpPath, dumpentry);
2203 osi_auditU(call, BUDB_FndLaDEvent, code, AUD_STR, vsname, AUD_END);
2208 FindLatestDump(call, vsname, dumpPath, dumpentry)
2209 struct rx_call *call;
2210 char *vsname, *dumpPath;
2211 struct budb_dumpEntry *dumpentry;
2213 struct ubik_trans *ut;
2214 dbadr curdbaddr, retdbaddr, firstdbaddr;
2217 char dumpName[BU_MAXNAMELEN + 2];
2218 afs_int32 eval, code = 0;
2220 if (!callPermitted(call))
2221 return BUDB_NOTPERMITTED;
2223 eval = InitRPC(&ut, LOCKREAD, 1);
2227 if ((strcmp(vsname, "") == 0) && (strcmp(dumpPath, "") == 0)) {
2228 /* Construct a database dump name */
2229 strcpy(dumpName, DUMP_TAPE_NAME);
2230 } else if (strchr(dumpPath, '/') == 0) {
2231 int level, old, length, hash;
2232 struct dump hostDump, diskDump;
2233 struct memoryHashTable *mht;
2236 afs_uint32 bestDumpId = 0;
2238 level = atoi(dumpPath);
2240 ABORT(BUDB_BADARGUMENT);
2243 /* Brute force search of all the dumps in the database - yuck! */
2246 mht = ht_GetType(HT_dumpIden_FUNCTION, &entrySize);
2248 ABORT(BUDB_BADARGUMENT);
2250 for (old = 0; old <= 1; old++) { /*fo */
2251 length = (old ? mht->oldLength : mht->length);
2255 for (hash = 0; hash < length; hash++) {
2257 for (dbAddr = ht_LookupBucket(ut, mht, hash, old); dbAddr;
2258 dbAddr = hostDump.idHashChain) {
2260 eval = dbread(ut, dbAddr, &diskDump, sizeof(diskDump));
2263 dump_ntoh(&diskDump, &hostDump);
2265 if ((strcmp(hostDump.volumeSet, vsname) == 0) && /* the volumeset */
2266 (hostDump.level == level) && /* same level */
2267 (hostDump.id > bestDumpId)) { /* more recent */
2268 bestDumpId = hostDump.id;
2275 ABORT(BUDB_NODUMPNAME);
2279 /* construct the name of the dump */
2280 if ((strlen(vsname) + strlen(tailCompPtr(dumpPath))) > BU_MAXNAMELEN)
2281 ABORT(BUDB_NODUMPNAME);
2283 strcpy(dumpName, vsname);
2284 strcat(dumpName, ".");
2285 strcat(dumpName, tailCompPtr(dumpPath));
2288 LogDebug(5, "lookup on :%s:\n", dumpName);
2290 /* Lookup on dumpname in hash table */
2291 eval = ht_LookupEntry(ut, &db.dumpName, dumpName, &firstdbaddr, &d);
2298 /* folow remaining dumps in hash chain, looking for most latest dump */
2299 for (curdbaddr = firstdbaddr; curdbaddr;
2300 curdbaddr = ntohl(d.nameHashChain)) {
2301 if (curdbaddr != firstdbaddr) {
2302 eval = dbread(ut, curdbaddr, &d, sizeof(d));
2307 if ((strcmp(d.dumpPath, dumpPath) == 0) && /* Same dumppath */
2308 (strcmp(d.dumpName, dumpName) == 0) && /* Same dumpname */
2309 (ntohl(d.created) > latest)) { /* most recent */
2310 latest = ntohl(d.created);
2311 retdbaddr = curdbaddr;
2315 ABORT(BUDB_NODUMPNAME);
2318 /* return the dump found */
2319 FillDumpEntry(ut, retdbaddr, dumpentry);
2321 code = ubik_EndTrans(ut);
2325 ubik_AbortTrans(ut);
2331 SBUDB_FinishDump(call, dump)
2332 struct rx_call *call;
2333 struct budb_dumpEntry *dump;
2337 code = FinishDump(call, dump);
2338 osi_auditU(call, BUDB_FinDmpEvent, code, AUD_DATE, (dump ? dump->id : 0),
2344 FinishDump(call, dump)
2345 struct rx_call *call;
2346 struct budb_dumpEntry *dump;
2348 struct ubik_trans *ut;
2351 afs_int32 eval, code = 0;
2353 if (!callPermitted(call))
2354 return BUDB_NOTPERMITTED;
2356 eval = InitRPC(&ut, LOCKWRITE, 1);
2360 eval = ht_LookupEntry(ut, &db.dumpIden, &dump->id, &a, &d);
2364 ABORT(BUDB_NODUMPID);
2366 if ((ntohl(d.flags) & BUDB_DUMP_INPROGRESS) == 0)
2367 ABORT(BUDB_DUMPNOTINUSE);
2369 d.flags = htonl(dump->flags & ~BUDB_DUMP_INPROGRESS);
2371 /* if creation time specified set it */
2373 d.created = htonl(dump->created);
2374 dump->created = ntohl(d.created);
2376 /* Write the dump entry out */
2377 eval = dbwrite(ut, a, &d, sizeof(d));
2381 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2385 code = ubik_EndTrans(ut);
2389 ubik_AbortTrans(ut);
2394 SBUDB_FinishTape(call, tape)
2395 struct rx_call *call;
2396 struct budb_tapeEntry *tape;
2400 code = FinishTape(call, tape);
2401 osi_auditU(call, BUDB_FinTpeEvent, code, AUD_DATE,
2402 (tape ? tape->dump : 0), AUD_END);
2407 FinishTape(call, tape)
2408 struct rx_call *call;
2409 struct budb_tapeEntry *tape;
2411 struct ubik_trans *ut;
2415 afs_int32 eval, code = 0;
2417 if (!callPermitted(call))
2418 return BUDB_NOTPERMITTED;
2420 eval = InitRPC(&ut, LOCKWRITE, 1);
2424 /* find the tape struct in the tapename hash chain */
2425 eval = ht_LookupEntry(ut, &db.tapeName, tape->name, &a, &t);
2429 ABORT(BUDB_NOTAPENAME);
2431 /* Read the dump structure */
2432 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
2436 /* search for the right tape on the rest of the chain */
2437 while (ntohl(d.id) != tape->dump) {
2438 a = ntohl(t.nameHashChain);
2440 ABORT(BUDB_NOTAPENAME);
2442 eval = dbread(ut, a, &t, sizeof(t));
2446 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
2451 if ((ntohl(t.flags) & BUDB_TAPE_BEINGWRITTEN) == 0)
2452 ABORT(BUDB_TAPENOTINUSE);
2454 /* t.nBytes = htonl(tape->nBytes); */
2455 t.nFiles = htonl(tape->nFiles);
2456 t.useKBytes = htonl(tape->useKBytes);
2457 t.flags = htonl(tape->flags & ~BUDB_TAPE_BEINGWRITTEN);
2459 eval = dbwrite(ut, a, &t, sizeof(t));
2463 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2467 code = ubik_EndTrans(ut);
2471 ubik_AbortTrans(ut);
2476 * return a set of dumps that match the specified criteria
2479 * majorVersion - version of interface structures. Permits compatibility
2481 * flags - for search and select operations. Broken down into flags
2482 * for name, start point, end point and time.
2483 * name - name to search for. Interpretation based on flags
2490 * dbTimeP - time at which the database was last modified. Up to
2491 * caller (client) to take appropriate action if database
2492 * modified between successive calls
2493 * dumps - list of matching dumps
2495 * currently supported are:
2501 SBUDB_GetDumps(call, majorVersion, flags, name, start, end, index, nextIndexP,
2503 struct rx_call *call;
2504 afs_int32 majorVersion; /* version of interface structures */
2505 afs_int32 flags; /* search & select controls */
2506 char *name; /* s&s parameters */
2509 afs_int32 index; /* start index of returned entries */
2510 afs_int32 *nextIndexP; /* output index for next call */
2512 budb_dumpList *dumps; /* pointer to buffer */
2517 GetDumps(call, majorVersion, flags, name, start, end, index,
2518 nextIndexP, dbTimeP, dumps);
2519 osi_auditU(call, BUDB_GetDmpEvent, code, AUD_END);
2524 GetDumps(call, majorVersion, flags, name, start, end, index, nextIndexP,
2526 struct rx_call *call;
2527 afs_int32 majorVersion; /* version of interface structures */
2528 afs_int32 flags; /* search & select controls */
2529 char *name; /* s&s parameters */
2532 afs_int32 index; /* start index of returned entries */
2533 afs_int32 *nextIndexP; /* output index for next call */
2535 budb_dumpList *dumps; /* pointer to buffer */
2537 struct ubik_trans *ut;
2540 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
2541 afs_int32 eval, code = 0;
2543 struct returnList list;
2545 /* Don't check permissions when we look up a specific dump id */
2546 if (((flags & BUDB_OP_STARTS) != BUDB_OP_DUMPID) && !callPermitted(call))
2547 return BUDB_NOTPERMITTED;
2549 if (majorVersion != BUDB_MAJORVERSION)
2550 return BUDB_OLDINTERFACE;
2552 return BUDB_ENDOFLIST;
2554 eval = InitRPC(&ut, LOCKREAD, 1);
2558 nameFlags = flags & BUDB_OP_NAMES;
2559 startFlags = flags & BUDB_OP_STARTS;
2560 endFlags = flags & BUDB_OP_ENDS;
2561 timeFlags = flags & BUDB_OP_TIMES;
2563 InitReturnList(&list);
2566 if (nameFlags == BUDB_OP_DUMPNAME) {
2567 /* not yet implemented */
2568 if (startFlags || endFlags || timeFlags)
2569 ABORT(BUDB_BADFLAGS);
2571 eval = ht_LookupEntry(ut, &db.dumpName, name, &da, &d);
2575 ABORT(BUDB_NODUMPNAME);
2578 if (strcmp(d.dumpName, name) == 0) {
2579 eval = AddToReturnList(&list, da, &toskip);
2580 if (eval == BUDB_LIST2BIG)
2586 da = ntohl(d.nameHashChain); /* get next dump w/ name */
2590 eval = dbread(ut, da, &d, sizeof(d));
2594 } else if (nameFlags == BUDB_OP_VOLUMENAME) {
2598 LogError(0, "NYI, BUDB_OP_VOLUMENAME\n");
2599 ABORT(BUDB_BADFLAGS);
2602 if (startFlags != BUDB_OP_STARTTIME)
2603 ABORT(BUDB_BADFLAGS);
2605 /* lookup a dump by volumename and time stamp. Find the most recent
2606 * dump of the specified volumename, that occured before the supplied
2610 /* get us a volInfo for name */
2611 eval = ht_LookupEntry(ut, &db.volName, name, &da, &vi);
2616 /* now iterate over all the entries of this name */
2617 for (va = vi.firstFragment; va != 0; va = v.sameNameChain) {
2619 eval = dbread(ut, va, &v, sizeof(v));
2624 on fragment > date ignore it - too recent;
2626 if (date on fragment < date && date on fragment > bestfound)
2627 bestfound = date on fragment;
2631 da = vi.sameNameChain;
2635 eval = dbread(ut, da, &vi, sizeof(vi));
2644 from saved volfragment address, compute dump.
2645 otherwise, return dump found
2650 } else if (startFlags == BUDB_OP_DUMPID) {
2651 if (endFlags || timeFlags)
2652 ABORT(BUDB_BADFLAGS);
2654 ABORT(BUDB_BADFLAGS); /* NYI */
2656 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &da, &d);
2660 ABORT(BUDB_NODUMPID);
2662 eval = AddToReturnList(&list, da, &toskip);
2665 } else if (endFlags == BUDB_OP_NPREVIOUS) {
2666 struct wantDumpRock rock;
2667 struct chosenDump *ptr, *nextPtr;
2669 extern wantDump(), rememberDump();
2671 /* no other flags should be set */
2673 /* end specifies how many dumps */
2675 ABORT(BUDB_BADFLAGS);
2677 memset(&rock, 0, sizeof(rock));
2678 rock.maxDumps = end;
2680 scanHashTable(ut, &db.dumpName, wantDump, rememberDump,
2683 for (ptr = rock.chain; ptr; ptr = nextPtr) {
2684 nextPtr = ptr->next;
2685 AddToReturnList(&list, ptr->addr, &toskip); /* ignore error for free */
2689 ABORT(BUDB_BADFLAGS);
2693 SendReturnList(ut, &list, FillDumpEntry,
2694 sizeof(struct budb_dumpEntry), index, nextIndexP,
2695 dbTimeP, (returnList_t) dumps);
2699 FreeReturnList(&list);
2700 code = ubik_EndTrans(ut);
2704 FreeReturnList(&list);
2705 ubik_AbortTrans(ut);
2710 * Get the expiration of a tape. Since the dump could have appended dumps,
2711 * we should use the most recent expiration date. Put the most recent
2712 * expiration tape into the given tape structure.
2715 getExpiration(ut, tapePtr)
2716 struct ubik_trans *ut;
2717 struct tape *tapePtr;
2723 afs_int32 eval, code = 0;
2728 /* Get the dump for this tape */
2729 ad = ntohl(tapePtr->dump);
2730 eval = dbread(ut, ad, &d, sizeof(d));
2734 /* If not an initial dump, get the initial dump */
2735 if (d.initialDumpID) {
2736 initDump = ntohl(d.initialDumpID);
2737 eval = ht_LookupEntry(ut, &db.dumpIden, &initDump, &ad, &d);
2742 /* Cycle through the dumps and appended dumps */
2744 /* Get the first tape in this dump. No need to check the rest of the tapes */
2745 /* for this dump since they will all have the same expiration date */
2746 eval = dbread(ut, ntohl(d.firstTape), &t, sizeof(t));
2750 /* Take the greater of the expiration dates */
2751 if (ntohl(tapePtr->expires) < ntohl(t.expires))
2752 tapePtr->expires = t.expires;
2754 /* Step to and read the next appended dump */
2755 if (ad = ntohl(d.appendedDumpChain)) {
2756 eval = dbread(ut, ad, &d, sizeof(d));
2766 /* Mark the following dump as appended to another, intial dump */
2768 makeAppended(ut, appendedDumpID, initialDumpID, startTapeSeq)
2769 struct ubik_trans *ut;
2770 afs_int32 appendedDumpID;
2771 afs_int32 initialDumpID;
2772 afs_int32 startTapeSeq;
2774 dbadr ada, da, lastDumpAddr;
2776 afs_int32 eval, code = 0;
2780 if (appendedDumpID == initialDumpID)
2781 ERROR(BUDB_INTERNALERROR);
2783 /* If there is an initial dump, append this dump to it */
2784 /* Find the appended dump via its id */
2785 eval = ht_LookupEntry(ut, &db.dumpIden, &appendedDumpID, &ada, &ad);
2789 /* If the dump is already marked as appended,
2790 * then we have an internal error.
2792 if (ad.initialDumpID) {
2793 if (ntohl(ad.initialDumpID) != initialDumpID)
2794 ERROR(BUDB_INTERNALERROR);
2797 /* Update the appended dump to point to the initial dump */
2798 ad.initialDumpID = htonl(initialDumpID);
2799 ad.tapes.b = htonl(startTapeSeq);
2801 /* find the initial dump via its id */
2802 eval = ht_LookupEntry(ut, &db.dumpIden, &initialDumpID, &da, &d);
2806 /* Update the appended dump's tape format with that of the initial */
2807 strcpy(ad.tapes.format, d.tapes.format);
2809 /* starting with the initial dump step through its appended dumps till
2810 * we reach the last appended dump.
2813 while (d.appendedDumpChain) {
2814 lastDumpAddr = ntohl(d.appendedDumpChain);
2815 if (lastDumpAddr == ada)
2816 ERROR(0); /* Already appended */
2817 eval = dbread(ut, lastDumpAddr, &d, sizeof(d));
2822 /* Update the last dump to point to our new appended dump.
2823 * The appended dump is the last one in the dump chain.
2825 d.appendedDumpChain = htonl(ada);
2826 ad.appendedDumpChain = 0;
2828 /* Write the appended dump and the initial dump */
2829 eval = dbwrite(ut, ada, (char *)&ad, sizeof(ad));
2833 eval = dbwrite(ut, lastDumpAddr, (char *)&d, sizeof(d));
2837 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
2846 SBUDB_MakeDumpAppended(call, appendedDumpID, initialDumpID, startTapeSeq)
2847 struct rx_call *call;
2848 afs_int32 appendedDumpID;
2849 afs_int32 initialDumpID;
2850 afs_int32 startTapeSeq;
2855 MakeDumpAppended(call, appendedDumpID, initialDumpID, startTapeSeq);
2856 osi_auditU(call, BUDB_AppDmpEvent, code, AUD_LONG, appendedDumpID,
2862 MakeDumpAppended(call, appendedDumpID, initialDumpID, startTapeSeq)
2863 struct rx_call *call;
2864 afs_int32 appendedDumpID;
2865 afs_int32 initialDumpID;
2866 afs_int32 startTapeSeq;
2868 struct ubik_trans *ut;
2869 afs_int32 eval, code = 0;
2871 if (!callPermitted(call))
2872 return BUDB_NOTPERMITTED;
2874 eval = InitRPC(&ut, LOCKWRITE, 1);
2878 eval = makeAppended(ut, appendedDumpID, initialDumpID, startTapeSeq);
2882 code = ubik_EndTrans(ut);
2886 ubik_AbortTrans(ut);
2890 /* Find the last tape of a dump-set. This includes any appended dumps */
2892 SBUDB_FindLastTape(call, dumpID, dumpEntry, tapeEntry, volEntry)
2893 struct rx_call *call;
2895 struct budb_dumpEntry *dumpEntry;
2896 struct budb_tapeEntry *tapeEntry;
2897 struct budb_volumeEntry *volEntry;
2901 code = FindLastTape(call, dumpID, dumpEntry, tapeEntry, volEntry);
2902 osi_auditU(call, BUDB_FndLTpeEvent, code, AUD_LONG, dumpID, AUD_END);
2907 FindLastTape(call, dumpID, dumpEntry, tapeEntry, volEntry)
2908 struct rx_call *call;
2910 struct budb_dumpEntry *dumpEntry;
2911 struct budb_tapeEntry *tapeEntry;
2912 struct budb_volumeEntry *volEntry;
2914 struct ubik_trans *ut;
2918 dbadr lastTape, thisTape;
2919 afs_int32 lastTapeSeq;
2920 struct volFragment vf;
2921 dbadr lastVol, thisVol;
2922 afs_int32 lastVolPos;
2923 afs_int32 eval, code = 0;
2925 if (!callPermitted(call))
2926 return BUDB_NOTPERMITTED;
2929 return (BUDB_BADARGUMENT);
2931 eval = InitRPC(&ut, LOCKREAD, 1);
2935 /* find and read its initial dump via its id */
2936 eval = ht_LookupEntry(ut, &db.dumpIden, &dumpID, &lastDump, &d);
2940 ABORT(BUDB_NODUMPID);
2942 /* Follow the append dumps link chain until we reach the last dump */
2943 while (d.appendedDumpChain) {
2944 lastDump = ntohl(d.appendedDumpChain);
2945 eval = dbread(ut, lastDump, &d, sizeof(d));
2950 /* We now have the last dump of the last appended dump */
2951 /* Copy this into our return structure */
2952 eval = FillDumpEntry(ut, lastDump, dumpEntry);
2956 /* Fail if the last dump has no tapes */
2958 ABORT(BUDB_NOTAPENAME);
2960 /* Follow the tapes in this dump until we reach the last tape */
2961 eval = dbread(ut, ntohl(d.firstTape), &t, sizeof(t));
2965 lastTape = ntohl(d.firstTape);
2966 lastTapeSeq = ntohl(t.seq);
2967 lastVol = ntohl(t.firstVol);
2969 while (t.nextTape) {
2970 thisTape = ntohl(t.nextTape);
2971 eval = dbread(ut, thisTape, &t, sizeof(t));
2975 if (ntohl(t.seq) > lastTapeSeq) {
2976 lastTape = thisTape;
2977 lastTapeSeq = ntohl(t.seq);
2978 lastVol = ntohl(t.firstVol);
2982 /* We now have the last tape of the last appended dump */
2983 /* Copy this into our return structure */
2984 eval = FillTapeEntry(ut, lastTape, tapeEntry);
2988 /* Zero volume entry if the last tape has no volumes */
2990 memset(volEntry, 0, sizeof(*volEntry));
2992 /* Follow the volumes until we reach the last volume */
2993 eval = dbread(ut, lastVol, &vf, sizeof(vf));
2997 lastVolPos = vf.position;
2999 while (vf.sameTapeChain) {
3000 thisVol = ntohl(vf.sameTapeChain);
3001 eval = dbread(ut, thisVol, &vf, sizeof(vf));
3005 if (vf.position > lastVolPos) {
3007 lastVolPos = vf.position;
3011 /* We now have the last volume of this tape */
3012 /* Copy this into our return structure */
3013 eval = FillVolEntry(ut, lastVol, volEntry);
3018 eval = ubik_EndTrans(ut);
3024 ubik_AbortTrans(ut);
3030 SBUDB_GetTapes(call, majorVersion, flags, name, start, end, index, nextIndexP,
3032 struct rx_call *call;
3033 afs_int32 majorVersion; /* version of interface structures */
3034 afs_int32 flags; /* search & select controls */
3035 char *name; /* s&s parameters */
3037 afs_int32 end; /* reserved: MBZ */
3038 afs_int32 index; /* start index of returned entries */
3039 afs_int32 *nextIndexP; /* output index for next call */
3041 budb_tapeList *tapes; /* pointer to buffer */
3046 GetTapes(call, majorVersion, flags, name, start, end, index,
3047 nextIndexP, dbTimeP, tapes);
3048 osi_auditU(call, BUDB_GetTpeEvent, code, AUD_END);
3053 GetTapes(call, majorVersion, flags, name, start, end, index, nextIndexP,
3055 struct rx_call *call;
3056 afs_int32 majorVersion; /* version of interface structures */
3057 afs_int32 flags; /* search & select controls */
3058 char *name; /* s&s parameters */
3060 afs_int32 end; /* reserved: MBZ */
3061 afs_int32 index; /* start index of returned entries */
3062 afs_int32 *nextIndexP; /* output index for next call */
3064 budb_tapeList *tapes; /* pointer to buffer */
3066 struct ubik_trans *ut;
3070 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
3071 struct returnList list;
3072 afs_int32 eval, code = 0;
3075 if (!callPermitted(call))
3076 return BUDB_NOTPERMITTED;
3078 if (majorVersion != BUDB_MAJORVERSION)
3079 return BUDB_OLDINTERFACE;
3082 return BUDB_ENDOFLIST;
3084 eval = InitRPC(&ut, LOCKREAD, 1);
3088 nameFlags = flags & BUDB_OP_NAMES;
3089 startFlags = flags & BUDB_OP_STARTS;
3090 endFlags = flags & BUDB_OP_ENDS;
3091 timeFlags = flags & BUDB_OP_TIMES;
3093 InitReturnList(&list);
3096 if (nameFlags == BUDB_OP_TAPENAME) { /*it */
3097 eval = ht_LookupEntry(ut, &db.tapeName, name, &ta, &t);
3101 ABORT(BUDB_NOTAPENAME);
3104 if ((startFlags & ~BUDB_OP_DUMPID) || endFlags || timeFlags)
3105 ABORT(BUDB_BADFLAGS);
3107 /* follow the hash chain to the end */
3109 if (startFlags & BUDB_OP_DUMPID) {
3110 /* read in the dump */
3111 eval = dbread(ut, ntohl(t.dump), &d, sizeof(d));
3115 /* check if both name and dump id match */
3116 if ((strcmp(name, t.name) == 0) && (ntohl(d.id) == start)) {
3117 eval = AddToReturnList(&list, ta, &toskip);
3118 if (eval && (eval != BUDB_LIST2BIG))
3123 /* Add to return list and continue search */
3124 if (strcmp(name, t.name) == 0) {
3125 eval = AddToReturnList(&list, ta, &toskip);
3126 if (eval == BUDB_LIST2BIG)
3133 ta = ntohl(t.nameHashChain);
3135 dbread(ut, ta, &t, sizeof(t));
3138 else if (nameFlags == BUDB_OP_TAPESEQ) {
3139 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &da, &d);
3143 ABORT(BUDB_NODUMPNAME);
3145 /* search for the right tape */
3146 ta = ntohl(d.firstTape);
3147 for (ta = ntohl(d.firstTape); ta; ta = ntohl(t.nextTape)) {
3148 eval = dbread(ut, ta, &t, sizeof(t));
3152 if (ntohl(t.seq) == end) {
3153 eval = AddToReturnList(&list, ta, &toskip);
3154 if (eval && (eval != BUDB_LIST2BIG))
3160 ABORT(BUDB_BADFLAGS);
3164 SendReturnList(ut, &list, FillTapeEntry,
3165 sizeof(struct budb_tapeEntry), index, nextIndexP,
3166 dbTimeP, (returnList_t) tapes);
3170 FreeReturnList(&list);
3171 code = ubik_EndTrans(ut);
3175 FreeReturnList(&list);
3176 ubik_AbortTrans(ut);
3181 * get a set of volumes according to the specified criteria.
3182 * See BUDB_GetDumps for general information on parameters
3183 * Currently supports:
3184 * 1) volume match - returns volumes based on volume name only.
3185 * 2) flags = BUDB_OP_DUMPID in which case name is a volume name
3186 * and start is a dumpid. Returns all volumes of the specified
3187 * name on the selected dumpid.
3191 SBUDB_GetVolumes(call, majorVersion, flags, name, start, end, index,
3192 nextIndexP, dbTimeP, volumes)
3193 struct rx_call *call;
3194 afs_int32 majorVersion; /* version of interface structures */
3195 afs_int32 flags; /* search & select controls */
3196 char *name; /* - parameters for search */
3197 afs_int32 start; /* - usage depends which BUDP_OP_* */
3198 afs_int32 end; /* - bits are set */
3199 afs_int32 index; /* start index of returned entries */
3200 afs_int32 *nextIndexP; /* output index for next call */
3202 budb_volumeList *volumes; /* pointer to buffer */
3207 GetVolumes(call, majorVersion, flags, name, start, end, index,
3208 nextIndexP, dbTimeP, volumes);
3209 osi_auditU(call, BUDB_GetVolEvent, code, AUD_END);
3214 GetVolumes(call, majorVersion, flags, name, start, end, index, nextIndexP,
3216 struct rx_call *call;
3217 afs_int32 majorVersion; /* version of interface structures */
3218 afs_int32 flags; /* search & select controls */
3219 char *name; /* - parameters for search */
3220 afs_int32 start; /* - usage depends which BUDP_OP_* */
3221 afs_int32 end; /* - bits are set */
3222 afs_int32 index; /* start index of returned entries */
3223 afs_int32 *nextIndexP; /* output index for next call */
3225 budb_volumeList *volumes; /* pointer to buffer */
3227 struct ubik_trans *ut;
3230 afs_int32 nameFlags, startFlags, endFlags, timeFlags;
3231 afs_int32 eval, code = 0;
3232 struct returnList vollist;
3235 /* Don't check permissions when we look up a specific volume name */
3236 if (((flags & BUDB_OP_NAMES) != BUDB_OP_VOLUMENAME)
3237 && !callPermitted(call))
3238 return BUDB_NOTPERMITTED;
3240 if (majorVersion != BUDB_MAJORVERSION)
3241 return BUDB_OLDINTERFACE;
3243 return BUDB_ENDOFLIST;
3245 eval = InitRPC(&ut, LOCKREAD, 1);
3249 nameFlags = flags & BUDB_OP_NAMES;
3250 startFlags = flags & BUDB_OP_STARTS;
3251 endFlags = flags & BUDB_OP_ENDS;
3252 timeFlags = flags & BUDB_OP_TIMES;
3254 InitReturnList(&vollist);
3257 /* lookup a the volume (specified by name) in the dump (specified by id) */
3258 if (nameFlags == BUDB_OP_VOLUMENAME) {
3259 /* dumpid permissible, all others off */
3260 if (((startFlags & ~BUDB_OP_DUMPID) != 0) || endFlags || timeFlags)
3261 ABORT(BUDB_BADFLAGS);
3263 /* returns ptr to volinfo of requested name */
3264 eval = ht_LookupEntry(ut, &db.volName, name, &via, &vi);
3268 ABORT(BUDB_NOVOLUMENAME);
3270 /* Iterate over all volume fragments with this name */
3272 struct volFragment v;
3275 /* traverse all the volume fragments for this volume info structure */
3276 for (va = vi.firstFragment; va; va = v.sameNameChain) {
3278 eval = dbread(ut, va, &v, sizeof(v));
3282 if (startFlags & BUDB_OP_DUMPID) {
3286 /* get the dump id for this fragment */
3287 eval = dbread(ut, ntohl(v.tape), &atape, sizeof(atape));
3292 dbread(ut, ntohl(atape.dump), &adump, sizeof(adump));
3296 /* dump id does not match */
3297 if (ntohl(adump.id) != start)
3301 eval = AddToReturnList(&vollist, va, &toskip);
3302 if (eval == BUDB_LIST2BIG)
3307 if (eval == BUDB_LIST2BIG)
3310 via = vi.sameNameChain;
3315 eval = dbread(ut, via, &vi, sizeof(vi));
3319 } else if (((nameFlags == 0) || (nameFlags == BUDB_OP_TAPENAME))
3320 && (startFlags == BUDB_OP_DUMPID)) {
3325 struct volFragment volFrag;
3328 /* lookup all volumes for a specified dump id */
3330 /* no other flags should be set */
3331 if (endFlags || timeFlags)
3332 ABORT(BUDB_BADFLAGS);
3335 eval = ht_LookupEntry(ut, &db.dumpIden, &start, &dumpAddr, &dump);
3339 /* traverse all the tapes */
3340 for (tapeAddr = ntohl(dump.firstTape); tapeAddr; tapeAddr = ntohl(tape.nextTape)) { /*w */
3341 eval = dbread(ut, tapeAddr, &tape, sizeof(tape));
3345 if ((nameFlags != BUDB_OP_TAPENAME)
3346 || ((nameFlags == BUDB_OP_TAPENAME)
3347 && (strcmp(tape.name, name) == 0))) {
3348 /* now return all the volumes */
3349 for (volFragAddr = ntohl(tape.firstVol); volFragAddr;
3350 volFragAddr = ntohl(volFrag.sameTapeChain)) {
3351 eval = dbread(ut, volFragAddr, &volFrag, sizeof(volFrag));
3355 eval = AddToReturnList(&vollist, volFragAddr, &toskip);
3356 if (eval == BUDB_LIST2BIG)
3362 if (eval == BUDB_LIST2BIG)
3366 ABORT(BUDB_BADFLAGS);
3370 SendReturnList(ut, &vollist, FillVolEntry,
3371 sizeof(struct budb_volumeEntry), index, nextIndexP,
3372 dbTimeP, (returnList_t) volumes);
3377 FreeReturnList(&vollist);
3378 code = ubik_EndTrans(ut);
3382 FreeReturnList(&vollist);
3383 ubik_AbortTrans(ut);
3388 SBUDB_UseTape(call, tape, new)
3389 struct rx_call *call;
3390 struct budb_tapeEntry *tape; /* tape info */
3391 afs_int32 *new; /* set if tape is new */
3395 code = UseTape(call, tape, new);
3396 osi_auditU(call, BUDB_UseTpeEvent, code, AUD_DATE,
3397 (tape ? tape->dump : 0), AUD_END);
3402 UseTape(call, tape, new)
3403 struct rx_call *call;
3404 struct budb_tapeEntry *tape; /* tape info */
3405 int *new; /* set if tape is new */
3407 struct ubik_trans *ut;
3411 afs_int32 eval, code;
3413 if (!callPermitted(call))
3414 return BUDB_NOTPERMITTED;
3416 if (strlen(tape->name) >= sizeof(t.name))
3417 return BUDB_BADARGUMENT;
3419 eval = InitRPC(&ut, LOCKWRITE, 1);
3425 memset(&t, 0, sizeof(t));
3426 eval = AllocStructure(ut, tape_BLOCK, 0, &a, &t);
3430 strcpy(t.name, tape->name);
3432 eval = ht_HashIn(ut, &db.tapeName, a, &t);
3438 /* Since deleting a tape may change the dump (if its the same one), read in
3439 * the dump after the call to DeleteTape. */
3441 eval = ht_LookupEntry(ut, &db.dumpIden, &tape->dump, &da, &d);
3445 ABORT(BUDB_NODUMPID);
3448 tape->written = time(0); /* fill in tape struct */
3449 t.written = htonl(tape->written);
3450 t.expires = htonl(tape->expires);
3452 t.seq = htonl(tape->seq);
3453 t.useCount = htonl(tape->useCount);
3454 t.labelpos = htonl(tape->labelpos);
3456 t.flags = htonl(tape->flags | BUDB_TAPE_BEINGWRITTEN);
3458 t.nextTape = d.firstTape; /* Chain the tape to the dump */
3459 d.firstTape = htonl(a);
3461 if (tape->seq >= ntohl(d.tapes.maxTapes)) /* inc # tapes in the dump */
3462 d.tapes.maxTapes = htonl(tape->seq);
3464 eval = dbwrite(ut, a, &t, sizeof(t)); /* write tape struct */
3468 eval = dbwrite(ut, da, &d, sizeof(d)); /* write the dump struct */
3472 eval = set_header_word(ut, lastUpdate, htonl(time(0)));
3476 LogDebug(5, "added tape %s\n", tape->name);
3478 code = ubik_EndTrans(ut);
3482 ubik_AbortTrans(ut);
3488 /* ---------------------------------------------
3489 * debug interface routines
3490 * ---------------------------------------------
3494 SBUDB_T_DumpHashTable(call, type, filename)
3495 struct rx_call *call;
3501 code = T_DumpHashTable(call, type, filename);
3502 osi_auditU(call, BUDB_TDmpHaEvent, code, AUD_STR, filename, AUD_END);
3507 T_DumpHashTable(call, type, filename)
3508 struct rx_call *call;
3512 struct ubik_trans *ut;
3513 struct memoryHashTable *mht;
3515 afs_int32 eval, code = 0;
3522 char e[sizeof(struct block)]; /* unnecessarily conservative */
3526 if (!callPermitted(call))
3527 return BUDB_NOTPERMITTED;
3529 if (strlen(filename) >= sizeof(path) - 5)
3530 return BUDB_BADARGUMENT;
3532 eval = InitRPC(&ut, LOCKWRITE, 1);
3536 if ((mht = ht_GetType(type, &e_size)) == 0)
3537 return BUDB_BADARGUMENT;
3539 sprintf(path, "%s/%s", gettmpdir(), filename);
3541 DUMP = fopen(path, "w");
3543 ABORT(BUDB_BADARGUMENT);
3546 for (old = 0;; old++) {
3547 length = (old ? mht->oldLength : mht->length);
3549 fprintf(DUMP, "Dumping %sHash Table:\n", (old ? "Old " : ""));
3551 for (hash = 0; hash < length; hash++) {
3552 a = ht_LookupBucket(ut, mht, hash, old);
3555 eval = dbread(ut, a, e, e_size);
3561 fprintf(DUMP, " in bucket %d at %d is ", hash, a);
3563 fprintf(DUMP, " at %d is ", a);
3565 case HT_dumpIden_FUNCTION:
3566 fprintf(DUMP, "%d\n", ntohl(((struct dump *)e)->id));
3568 case HT_dumpName_FUNCTION:
3569 fprintf(DUMP, "%s\n", ((struct dump *)e)->dumpName);
3571 case HT_tapeName_FUNCTION:
3572 fprintf(DUMP, "%s\n", ((struct tape *)e)->name);
3574 case HT_volName_FUNCTION:
3575 fprintf(DUMP, "%s\n", ((struct volInfo *)e)->name);
3578 if ((ht_HashEntry(mht, e) % length) != hash)
3579 ABORT(BUDB_DATABASEINCONSISTENT);
3580 a = ntohl(*(dbadr *) (e + mht->threadOffset));
3587 fprintf(DUMP, "%d entries found\n", ent);
3588 if (ntohl(mht->ht->entries) != ent)
3589 ABORT(BUDB_DATABASEINCONSISTENT);
3591 code = ubik_EndTrans(ut);
3597 ubik_AbortTrans(ut);
3604 SBUDB_T_GetVersion(call, majorVersion)
3605 struct rx_call *call;
3606 afs_int32 *majorVersion;
3610 code = T_GetVersion(call, majorVersion);
3611 osi_auditU(call, BUDB_TGetVrEvent, code, AUD_END);
3616 T_GetVersion(call, majorVersion)
3617 struct rx_call *call;
3620 struct ubik_trans *ut;
3623 code = InitRPC(&ut, LOCKREAD, 0);
3627 *majorVersion = BUDB_MAJORVERSION;
3629 code = ubik_EndTrans(ut);
3633 /* BUDB_T_DumpDatabase
3634 * dump as much of the database as possible int /tmp/<filename>
3638 SBUDB_T_DumpDatabase(call, filename)
3639 struct rx_call *call;
3644 code = T_DumpDatabase(call, filename);
3645 osi_auditU(call, BUDB_TDmpDBEvent, code, AUD_STR, filename, AUD_END);
3650 T_DumpDatabase(call, filename)
3651 struct rx_call *call;
3656 struct ubik_trans *ut;
3659 int type, old, length, hash;
3660 struct memoryHashTable *mht;
3661 afs_int32 eval, code = 0;
3663 if (!callPermitted(call))
3664 return BUDB_NOTPERMITTED;
3666 path = (char *)malloc(strlen(gettmpdir()) + 1 + strlen(filename) + 1);
3668 return (BUDB_INTERNALERROR);
3670 sprintf(path, "%s/%s", gettmpdir(), filename);
3672 dumpfid = fopen(path, "w");
3674 return (BUDB_BADARGUMENT);
3676 eval = InitRPC(&ut, LOCKWRITE, 1);
3680 /* dump all items in the database */
3681 for (type = 1; type <= HT_MAX_FUNCTION; type++) { /*ft */
3682 mht = ht_GetType(type, &entrySize);
3684 ERROR(BUDB_BADARGUMENT);
3686 for (old = 0; old <= 1; old++) { /*fo */
3687 length = (old ? mht->oldLength : mht->length);
3691 fprintf(dumpfid, "Dumping %s Hash Table:\n", (old ? "Old " : ""));
3693 for (hash = 0; hash < length; hash++) { /*f */
3694 dbAddr = ht_LookupBucket(ut, mht, hash, old);
3696 while (dbAddr) { /*w */
3697 switch (type) { /*s */
3698 case HT_dumpIden_FUNCTION:
3700 struct dump hostDump, diskDump;
3703 cdbread(ut, dump_BLOCK, dbAddr, &diskDump,
3709 "\ndumpId hash %d, entry at %u\n",
3712 "----------------------------\n");
3713 dump_ntoh(&diskDump, &hostDump);
3714 printDump(dumpfid, &hostDump);
3715 dbAddr = hostDump.idHashChain;
3719 case HT_dumpName_FUNCTION:
3721 struct dump hostDump, diskDump;
3724 cdbread(ut, dump_BLOCK, dbAddr, &diskDump,
3730 "\ndumpname hash %d, entry at %u\n",
3733 "----------------------------\n");
3734 dump_ntoh(&diskDump, &hostDump);
3735 printDump(dumpfid, &hostDump);
3736 dbAddr = hostDump.nameHashChain;
3740 case HT_tapeName_FUNCTION:
3742 struct tape hostTape, diskTape;
3745 cdbread(ut, tape_BLOCK, dbAddr, &diskTape,
3751 "\ntapename hash %d, entry at %u\n",
3754 "----------------------------\n");
3755 tape_ntoh(&diskTape, &hostTape);
3756 printTape(dumpfid, &hostTape);
3757 dbAddr = hostTape.nameHashChain;
3761 case HT_volName_FUNCTION:
3763 struct volInfo hostVolInfo, diskVolInfo;
3766 cdbread(ut, volInfo_BLOCK, dbAddr,
3767 &diskVolInfo, sizeof(diskVolInfo));
3772 "\nvolname hash %d, entry at %u\n",
3775 "----------------------------\n");
3776 volInfo_ntoh(&diskVolInfo, &hostVolInfo);
3777 printVolInfo(dumpfid, &hostVolInfo);
3778 dbAddr = hostVolInfo.nameHashChain;
3780 volFragsDump(ut, dumpfid,
3781 hostVolInfo.firstFragment);
3786 fprintf(dumpfid, "unknown type %d\n", type);
3796 code = ubik_EndTrans(ut); /* is this safe if no ut started ? */
3805 volFragsDump(ut, dumpfid, dbAddr)
3806 struct ubik_trans *ut;
3810 struct volFragment hostVolFragment, diskVolFragment;
3815 cdbread(ut, volFragment_BLOCK, dbAddr, &diskVolFragment,
3816 sizeof(diskVolFragment));
3817 if (code) { /* don't be fussy about errors */
3818 fprintf(dumpfid, "volFragsDump: Error reading database\n");
3822 fprintf(dumpfid, "\nvolfragment entry at %u\n", dbAddr);
3823 fprintf(dumpfid, "----------------------------\n");
3824 volFragment_ntoh(&diskVolFragment, &hostVolFragment);
3825 printVolFragment(dumpfid, &hostVolFragment);
3826 dbAddr = hostVolFragment.sameNameChain;
3832 /* utilities - network to host conversion
3833 * currently used for debug only
3836 volFragmentDiskToHost(diskVfPtr, hostVfPtr)
3837 struct volFragment *diskVfPtr, *hostVfPtr;
3839 hostVfPtr->vol = ntohl(diskVfPtr->vol);
3840 hostVfPtr->sameNameChain = ntohl(diskVfPtr->sameNameChain);
3841 hostVfPtr->tape = ntohl(diskVfPtr->tape);
3842 hostVfPtr->sameTapeChain = ntohl(diskVfPtr->sameTapeChain);
3843 hostVfPtr->position = ntohl(diskVfPtr->position);
3844 hostVfPtr->clone = ntohl(diskVfPtr->clone);
3845 hostVfPtr->incTime = ntohl(diskVfPtr->incTime);
3846 hostVfPtr->startByte = ntohl(diskVfPtr->startByte);
3847 hostVfPtr->nBytes = ntohl(diskVfPtr->nBytes);
3848 hostVfPtr->flags = ntohs(diskVfPtr->flags);
3849 hostVfPtr->sequence = ntohs(diskVfPtr->sequence);
3852 volInfoDiskToHost(diskViPtr, hostViPtr)
3853 struct volInfo *diskViPtr, *hostViPtr;
3855 strcpy(hostViPtr->name, diskViPtr->name);
3856 hostViPtr->nameHashChain = ntohl(diskViPtr->nameHashChain);
3857 hostViPtr->id = ntohl(diskViPtr->id);
3858 strcpy(hostViPtr->server, diskViPtr->server);
3859 hostViPtr->partition = ntohl(diskViPtr->partition);
3860 hostViPtr->flags = ntohl(diskViPtr->flags);
3861 hostViPtr->sameNameHead = ntohl(diskViPtr->sameNameHead);
3862 hostViPtr->sameNameChain = ntohl(diskViPtr->sameNameChain);
3863 hostViPtr->firstFragment = ntohl(diskViPtr->firstFragment);
3864 hostViPtr->nFrags = ntohl(diskViPtr->nFrags);
3867 tapeDiskToHost(diskTapePtr, hostTapePtr)
3868 struct tape *diskTapePtr, *hostTapePtr;
3870 strcpy(hostTapePtr->name, diskTapePtr->name);
3871 hostTapePtr->nameHashChain = ntohl(diskTapePtr->nameHashChain);
3872 hostTapePtr->flags = ntohl(diskTapePtr->flags);
3874 /* tape id conversion here */
3875 hostTapePtr->written = ntohl(diskTapePtr->written);
3876 hostTapePtr->nBytes = ntohl(diskTapePtr->nBytes);
3877 hostTapePtr->nFiles = ntohl(diskTapePtr->nFiles);
3878 hostTapePtr->nVolumes = ntohl(diskTapePtr->nVolumes);
3879 hostTapePtr->seq = ntohl(diskTapePtr->seq);
3880 hostTapePtr->dump = ntohl(diskTapePtr->dump);
3881 hostTapePtr->nextTape = ntohl(diskTapePtr->nextTape);
3882 hostTapePtr->firstVol = ntohl(diskTapePtr->firstVol);
3883 hostTapePtr->useCount = ntohl(diskTapePtr->useCount);
3886 dumpDiskToHost(diskDumpPtr, hostDumpPtr)
3887 struct dump *diskDumpPtr, *hostDumpPtr;
3889 hostDumpPtr->id = ntohl(diskDumpPtr->id);
3890 hostDumpPtr->idHashChain = ntohl(diskDumpPtr->idHashChain);
3891 strcpy(hostDumpPtr->dumpName, diskDumpPtr->dumpName);
3892 strcpy(hostDumpPtr->dumpPath, diskDumpPtr->dumpPath);
3893 strcpy(hostDumpPtr->volumeSet, diskDumpPtr->volumeSet);
3894 hostDumpPtr->nameHashChain = ntohl(diskDumpPtr->nameHashChain);
3895 hostDumpPtr->flags = ntohl(diskDumpPtr->flags);
3896 hostDumpPtr->parent = ntohl(diskDumpPtr->parent);
3897 hostDumpPtr->created = ntohl(diskDumpPtr->created);
3898 /* hostDumpPtr->incTime = ntohl(diskDumpPtr->incTime); */
3899 hostDumpPtr->nVolumes = ntohl(diskDumpPtr->nVolumes);
3901 /* tapeset conversion here */
3903 hostDumpPtr->firstTape = ntohl(diskDumpPtr->firstTape);
3905 /* principal conversion here */
3911 checkHash(ut, hashType)
3912 struct ubik_trans *ut;
3915 struct memoryHashTable *mhtPtr;
3916 int entrySize, hashTableLength;
3921 mhtPtr = ht_GetType(hashType, &entrySize);
3925 for (old = 0; old < 1; old++) {
3926 LogDebug(5, "\nold = %d\n", old);
3927 printMemoryHashTable(stdout, mhtPtr);
3929 hashTableLength = (old ? mhtPtr->oldLength : mhtPtr->length);
3931 for (bucket = 0; bucket < hashTableLength; bucket++) {
3934 entryAddr = ht_LookupBucket(ut, mhtPtr, bucket, old);
3935 while (entryAddr != 0) {
3936 LogDebug(6, "bucket %d has disk addr %d\n", bucket,
3939 case HT_dumpIden_FUNCTION:
3941 struct dump diskDump, hostDump;
3943 code = dbread(ut, entryAddr, &diskDump, entrySize);
3947 dump_ntoh(&diskDump, &hostDump);
3948 printDump(stdout, &hostDump);
3949 entryAddr = hostDump.idHashChain;
3953 case HT_dumpName_FUNCTION:
3956 case HT_tapeName_FUNCTION:
3959 case HT_volName_FUNCTION:
3961 struct volInfo diskVolInfo, hostVolInfo;
3963 code = dbread(ut, entryAddr, &diskVolInfo, entrySize);
3967 volInfo_ntoh(&diskVolInfo, &hostVolInfo);
3968 printVolInfo(stdout, &hostVolInfo);
3969 entryAddr = hostVolInfo.nameHashChain;