#include <rx/rx.h>
#include <afs/afsint.h>
#include <stdio.h>
+#include <string.h>
#include <afs/procmgmt.h>
#include <afs/assert.h>
#include <afs/prs_fs.h>
#include <afs/nfs.h>
#include <lwp.h>
#include <lock.h>
-#include <afs/auth.h>
#include <afs/cellconfig.h>
#include <afs/keys.h>
#include <ubik.h>
#include "error_macros.h"
/* GLOBAL CONFIGURATION PARAMETERS */
+#define BIGCHUNK 102400
+
extern int dump_namecheck;
extern int autoQuery;
+static void initTapeBuffering();
+static writeDbDump();
+static restoreDbEntries();
+
+void * KeepAlive(void *);
/* CreateDBDump
* create a dump entry for a saved database
*/
int interactiveFlag;
char tapeName[BU_MAXTAPELEN];
char strlevel[5];
- afs_int32 i;
struct timeval tp;
struct timezone tzp;
afs_int32 curTime;
return (code);
}
+/* writeDbDump
+ * notes:
+ * this code assumes that the blocksize on reads is smaller than
+ * the blocksize on writes
+ */
+
+static
+writeDbDump(tapeInfoPtr, taskId, expires, dumpid)
+ struct butm_tapeInfo *tapeInfoPtr;
+ afs_uint32 taskId;
+ Date expires;
+ afs_uint32 dumpid;
+{
+ afs_int32 blockSize;
+ afs_int32 writeBufNbytes = 0;
+ char *writeBlock = 0;
+ char *writeBuffer = 0;
+ char *writeBufPtr;
+ afs_int32 transferSize;
+
+ char *readBufPtr;
+ afs_int32 maxReadSize;
+
+ charListT charList;
+ afs_int32 done;
+ afs_int32 code;
+ afs_int32 chunksize = 0;
+ afs_int32 tc_EndMargin, tc_KEndMargin, kRemaining;
+ int sequence;
+ int wroteLabel;
+ int firstcall;
+#ifdef AFS_PTHREAD_ENV
+ pthread_t alivePid;
+ pthread_attr_t tattr;
+ AFS_SIGSET_DECL;
+#else
+ PROCESS alivePid;
+#endif
+
+ extern struct tapeConfig globalTapeConfig;
+ extern struct udbHandleS udbHandle;
+
+ blockSize = BUTM_BLKSIZE;
+ writeBlock = (char *)malloc(BUTM_BLOCKSIZE);
+ if (!writeBlock)
+ ERROR_EXIT(TC_NOMEMORY);
+
+ writeBuffer = writeBlock + sizeof(struct blockMark);
+ memset(writeBuffer, 0, BUTM_BLKSIZE);
+ maxReadSize = 1024;
+
+ /*
+ * The margin of space to check for end of tape is set to the
+ * amount of space used to write an end-of-tape multiplied by 2.
+ * The amount of space is size of a 16K EODump marker, its EOF
+ * marker, and up to two EOF markers done on close (1 16K blocks +
+ * 3 EOF * markers).
+ */
+ tc_EndMargin = (16384 + 3 * globalTapeConfig.fileMarkSize) * 2;
+ tc_KEndMargin = tc_EndMargin / 1024;
+
+ /* have to write enclose the dump in file marks */
+ code = butm_WriteFileBegin(tapeInfoPtr);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write FileBegin on tape\n");
+ ERROR_EXIT(code);
+ }
+
+ writeBufPtr = &writeBuffer[0];
+ firstcall = 1;
+ sequence = 1;
+ charList.charListT_val = 0;
+ charList.charListT_len = 0;
+
+ while (1) { /*w */
+ /* When no data in buffer, read data from the budb_server */
+ if (charList.charListT_len == 0) {
+ /* get more data. let rx allocate space */
+ if (charList.charListT_val) {
+ free(charList.charListT_val);
+ charList.charListT_val = 0;
+ }
+
+ /* get the data */
+ code =
+ ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
+ UF_SINGLESERVER, firstcall,
+ maxReadSize, &charList, &done);
+ if (code) {
+ ErrorLog(0, taskId, code, 0, "Can't read database\n");
+ ERROR_EXIT(code);
+ }
+
+ /* If this if the first call to the budb server, create a thread
+ * that will keep the connection alive (during tape changes).
+ */
+ if (firstcall) {
+#ifdef AFS_PTHREAD_ENV
+ code = pthread_attr_init(&tattr);
+ if (code) {
+ ErrorLog(0, taskId, code, 0,
+ "Can't pthread_attr_init Keep-alive process\n");
+ ERROR_EXIT(code);
+ }
+
+ code =
+ pthread_attr_setdetachstate(&tattr,
+ PTHREAD_CREATE_DETACHED);
+ if (code) {
+ ErrorLog(0, taskId, code, 0,
+ "Can't pthread_attr_setdetachstate Keep-alive process\n");
+ ERROR_EXIT(code);
+ }
+
+ AFS_SIGSET_CLEAR();
+ code = pthread_create(&alivePid, &tattr, KeepAlive, 0);
+ AFS_SIGSET_RESTORE();
+#else
+ code =
+ LWP_CreateProcess(KeepAlive, 16384, 1, (void *)NULL,
+ "Keep-alive process", &alivePid);
+#endif
+ /* XXX should we check code here ??? XXX */
+ }
+ firstcall = 0;
+
+ readBufPtr = charList.charListT_val;
+ }
+
+ if ((charList.charListT_len == 0) && done)
+ break;
+
+ /* compute how many bytes and transfer to the write Buffer */
+ transferSize =
+ (charList.charListT_len <
+ (blockSize -
+ writeBufNbytes)) ? charList.charListT_len : (blockSize -
+ writeBufNbytes);
+
+ memcpy(writeBufPtr, readBufPtr, transferSize);
+ charList.charListT_len -= transferSize;
+ writeBufPtr += transferSize;
+ readBufPtr += transferSize;
+ writeBufNbytes += transferSize;
+
+ /* If filled the write buffer, then write it to tape */
+ if (writeBufNbytes == blockSize) {
+ code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write data on tape\n");
+ ERROR_EXIT(code);
+ }
+
+ memset(writeBuffer, 0, blockSize);
+ writeBufPtr = &writeBuffer[0];
+ writeBufNbytes = 0;
+
+ /* Every BIGCHUNK bytes check if aborted */
+ chunksize += blockSize;
+ if (chunksize > BIGCHUNK) {
+ chunksize = 0;
+ if (checkAbortByTaskId(taskId))
+ ERROR_EXIT(TC_ABORTEDBYREQUEST);
+ }
+
+ /*
+ * check if tape is full - since we filled a blockSize worth of data
+ * assume that there is more data.
+ */
+ kRemaining = butm_remainingKSpace(tapeInfoPtr);
+ if (kRemaining < tc_KEndMargin) {
+ code = butm_WriteFileEnd(tapeInfoPtr);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write FileEnd on tape\n");
+ ERROR_EXIT(code);
+ }
+
+ code = butm_WriteEOT(tapeInfoPtr);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write end-of-dump on tape\n");
+ ERROR_EXIT(code);
+ }
+
+ /* Mark tape as having been written */
+ tapeEntryPtr->useKBytes =
+ tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
+ tapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
+
+ unmountTape(taskId, tapeInfoPtr);
+
+ /* Get next tape and writes its label */
+ sequence++;
+ code =
+ GetDBTape(taskId, expires, tapeInfoPtr, dumpid, sequence,
+ 1, &wroteLabel);
+ if (code)
+ ERROR_EXIT(code);
+
+ code = butm_WriteFileBegin(tapeInfoPtr);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write FileBegin on tape\n");
+ ERROR_EXIT(code);
+ }
+ }
+ }
+ } /*w */
+
+ /* no more data to be read - if necessary, flush out the last buffer */
+ if (writeBufNbytes > 0) {
+ code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize);
+ if (code) {
+ ErrorLog(1, taskId, code, tapeInfoPtr->error,
+ "Can't write data on tape\n");
+ ERROR_EXIT(code);
+ }
+ }
+
+ code = butm_WriteFileEnd(tapeInfoPtr);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't write FileEnd on tape\n");
+ ERROR_EXIT(code);
+ }
+
+ /* Mark tape as having been written */
+ tapeEntryPtr->useKBytes =
+ tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
+ tapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
+
+ error_exit:
+ /* Let the KeepAlive process stop on its own */
+ code =
+ ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
+ UF_END_SINGLESERVER, 0);
+
+ if (writeBlock)
+ free(writeBlock);
+ if (charList.charListT_val)
+ free(charList.charListT_val);
+ return (code);
+}
+
/* saveDbToTape
* dump backup database to tape
*/
-afs_int32
-saveDbToTape(saveDbIfPtr)
- struct saveDbIf *saveDbIfPtr;
+void *
+saveDbToTape(void *param)
{
+ struct saveDbIf *saveDbIfPtr = (struct saveDbIf *)param;
afs_int32 code = 0;
afs_int32 i;
int wroteLabel;
- afs_int32 new;
afs_uint32 taskId;
Date expires;
struct butm_tapeInfo tapeInfo;
struct budb_dumpEntry dumpEntry;
- struct tapeEntryList *next;
- struct budb_dumpEntry de;
extern struct deviceSyncNode *deviceLatch;
extern struct tapeConfig globalTapeConfig;
free(saveDbIfPtr);
LeaveDeviceQueue(deviceLatch);
- return (code);
+ return (void *)(code);
}
struct rstTapeInfo {
struct budb_tapeEntry *tapeEntPtr;
struct budb_dumpEntry *dumpEntryPtr;
{
- afs_int32 code;
-
memset(dumpEntryPtr, 0, sizeof(struct budb_dumpEntry));
dumpEntryPtr->id = tapeEntPtr->dump;
strcat(dumpEntryPtr->tapes.format, ".%d");
dumpEntryPtr->tapes.b = tapeEntPtr->seq;
dumpEntryPtr->tapes.maxTapes = 0;
+ return 0;
}
/* readDbTape
{
afs_int32 code = 0;
int interactiveFlag;
- afs_int32 taskId, i;
+ afs_int32 taskId;
struct butm_tapeLabel oldTapeLabel;
char AFStapeName[BU_MAXTAPELEN], tapeName[BU_MAXTAPELEN];
struct tapeEntryList *endList;
while (1) { /*w */
if (interactiveFlag) { /* need a tape to read */
- code =
- PromptForTape(RESTOREDBOPCODE, tapeName,
- rstTapeInfoPtr->dumpid, taskId, tapecount);
- if (code)
- ERROR_EXIT(code);
- }
- interactiveFlag = 1;
- tapecount++;
-
- code = butm_Mount(tapeInfoPtr, tapeName);
- if (code) {
- TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
- goto getNewTape;
- }
-
- code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1); /* will rewind the tape */
- if (code) {
- TapeLog(0, taskId, code, tapeInfoPtr->error,
- "Can't read tape label\n");
- goto getNewTape;
- }
-
- /* Check for name of tape and matching dump id (if applicable). */
- if ((strcmp(oldTapeLabel.AFSName, AFStapeName) != 0)
- || ((rstTapeInfoPtr->tapeSeq != 1)
- && (oldTapeLabel.dumpid != rstTapeInfoPtr->dumpid))) {
- char expTape[BU_MAXTAPELEN + 32];
- char gotTape[BU_MAXTAPELEN + 32];
-
- TAPENAME(expTape, tapeName, rstTapeInfoPtr->dumpid);
- TAPENAME(gotTape, oldTapeLabel.AFSName, oldTapeLabel.dumpid);
-
- TLog(taskId, "Tape label expected %s, label seen %s\n", expTape,
- gotTape);
- goto getNewTape;
- }
-
- if (rstTapeInfoPtr->tapeSeq == 1) /* Remember this dumpId */
- rstTapeInfoPtr->dumpid = oldTapeLabel.dumpid;
-
- break;
-
- getNewTape:
- unmountTape(taskId, tapeInfoPtr);
- } /*w */
-
-
- /* Initialize a tapeEntry for later inclusion into the database */
- listEntryPtr =
- (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList));
- if (!listEntryPtr)
- ERROR_EXIT(TC_NOMEMORY);
- memset(listEntryPtr, 0, sizeof(struct tapeEntryList));
-
- /* Fill in tape entry so we can save it later */
- strcpy(tapeEntryPtr->name, TNAME(&oldTapeLabel));
- tapeEntryPtr->dump = oldTapeLabel.dumpid;
- tapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
- tapeEntryPtr->written = oldTapeLabel.creationTime;
- tapeEntryPtr->expires = oldTapeLabel.expirationDate;
- tapeEntryPtr->seq = extractTapeSeq(oldTapeLabel.AFSName);
- tapeEntryPtr->useCount = oldTapeLabel.useCount;
- tapeEntryPtr->useKBytes = 0;
- tapeEntryPtr->labelpos = 0;
-
- /* Thread onto end of single-linked list */
- if (listEntryHead) {
- endList = listEntryHead;
- while (endList->next)
- endList = endList->next;
- endList->next = listEntryPtr;
- } else
- listEntryHead = listEntryPtr;
-
- error_exit:
- return (code);
-}
-
-/* restoreDbFromTape
- * restore the backup database from tape.
- */
-
-afs_int32
-restoreDbFromTape(taskId)
- afs_uint32 taskId;
-{
- afs_int32 code = 0;
- afs_int32 new, i;
- struct dumpNode *node;
- struct butm_tapeInfo tapeInfo;
- struct rstTapeInfo rstTapeInfo;
- struct budb_dumpEntry dumpEntry;
-
- extern struct tapeConfig globalTapeConfig;
- extern struct deviceSyncNode *deviceLatch;
-
- setStatus(taskId, DRIVE_WAIT);
- EnterDeviceQueue(deviceLatch); /* lock tape device */
- clearStatus(taskId, DRIVE_WAIT);
-
- printf("\n\n");
- TLog(taskId, "RestoreDb\n");
-
- tapeInfo.structVersion = BUTM_MAJORVERSION;
- code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfo.error,
- "Can't initialize tape module\n");
- ERROR_EXIT(code);
- }
-
- listEntryHead = NULL;
-
- rstTapeInfo.taskId = taskId;
- rstTapeInfo.tapeSeq = 1;
- rstTapeInfo.dumpid = 0;
-
- code = readDbTape(&tapeInfo, &rstTapeInfo, autoQuery);
- if (code)
- ERROR_EXIT(code);
-
- code = restoreDbEntries(&tapeInfo, &rstTapeInfo);
- if (code)
- ERROR_EXIT(code);
-
- error_exit:
- /* Now put this dump into the database */
- /* Make a dump entry from first tape */
- listEntryPtr = listEntryHead;
- if (listEntryPtr) {
- makeDbDumpEntry(tapeEntryPtr, &dumpEntry);
- if (dumpEntry.id != 0) {
- i = bcdb_CreateDump(&dumpEntry);
- if (i) {
- if (i == BUDB_DUMPIDEXISTS)
- fprintf(stderr,
- "Dump id %d not added to database - already exists\n",
- dumpEntry.id);
- else
- TapeLog(0, taskId, i, 0,
- "Dump id %d not added to database\n",
- dumpEntry.id);
- } else {
- i = addTapesToDb(taskId);
- if (!code)
- code = i;
-
- i = bcdb_FinishDump(&dumpEntry);
- if (!code)
- code = i;
- }
- }
- freeTapeList();
- }
-
- unmountTape(taskId, &tapeInfo);
- waitDbWatcher();
-
- if (code == TC_ABORTEDBYREQUEST) {
- TLog(taskId, "RestoreDb: Aborted by request\n");
- clearStatus(taskId, ABORT_REQUEST);
- setStatus(taskId, ABORT_DONE);
- } else if (code) {
- TapeLog(0, taskId, code, 0, "RestoreDb: Finished with errors\n");
- setStatus(taskId, TASK_ERROR);
- } else {
- TLog(taskId, "RestoreDb: Finished\n");
- }
-
- LeaveDeviceQueue(deviceLatch);
- setStatus(taskId, TASK_DONE);
-
- return (code);
-}
-
-/* KeepAlive
- *
- * While dumping the database, keeps the connection alive.
- * Every 10 seconds, wake up and ask to read 0 bytes of the database.
- * This resets the database's internal timer so that it does not
- * prematuraly quit (on asking for new tapes and such).
- *
- * Use the same udbHandle as writeDbDump so we go to the same server.
- */
-int
-KeepAlive()
-{
- charListT charList;
- afs_int32 code;
- afs_int32 done;
-
- extern struct udbHandleS udbHandle;
-
- while (1) {
-#ifdef AFS_PTHREAD_ENV
- sleep(5);
-#else
- IOMGR_Sleep(5);
-#endif
- charList.charListT_val = 0;
- charList.charListT_len = 0;
- code =
- ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
- UF_SINGLESERVER, 0, 0, &charList, &done);
- if (code || done)
- break;
- }
-}
-
-#define BIGCHUNK 102400
-
-/* writeDbDump
- * notes:
- * this code assumes that the blocksize on reads is smaller than
- * the blocksize on writes
- */
-
-static
-writeDbDump(tapeInfoPtr, taskId, expires, dumpid)
- struct butm_tapeInfo *tapeInfoPtr;
- afs_uint32 taskId;
- Date expires;
- afs_uint32 dumpid;
-{
- afs_int32 blockSize;
- afs_int32 writeBufNbytes = 0;
- char *writeBlock = 0;
- char *writeBuffer = 0;
- char *writeBufPtr;
- afs_int32 transferSize;
-
- char *readBufPtr;
- afs_int32 maxReadSize;
-
- charListT charList;
- afs_int32 done;
- afs_int32 code;
- afs_int32 chunksize = 0;
- afs_int32 tc_EndMargin, tc_KEndMargin, kRemaining;
- int sequence;
- int wroteLabel, new;
- int firstcall;
-#ifdef AFS_PTHREAD_ENV
- pthread_t alivePid;
- pthread_attr_t tattr;
- AFS_SIGSET_DECL;
-#else
- PROCESS alivePid;
-#endif
-
- extern struct tapeConfig globalTapeConfig;
- extern struct udbHandleS udbHandle;
-
- extern int KeepAlive();
-
- blockSize = BUTM_BLKSIZE;
- writeBlock = (char *)malloc(BUTM_BLOCKSIZE);
- if (!writeBlock)
- ERROR_EXIT(TC_NOMEMORY);
-
- writeBuffer = writeBlock + sizeof(struct blockMark);
- memset(writeBuffer, 0, BUTM_BLKSIZE);
- maxReadSize = 1024;
-
- /*
- * The margin of space to check for end of tape is set to the
- * amount of space used to write an end-of-tape multiplied by 2.
- * The amount of space is size of a 16K EODump marker, its EOF
- * marker, and up to two EOF markers done on close (1 16K blocks +
- * 3 EOF * markers).
- */
- tc_EndMargin = (16384 + 3 * globalTapeConfig.fileMarkSize) * 2;
- tc_KEndMargin = tc_EndMargin / 1024;
-
- /* have to write enclose the dump in file marks */
- code = butm_WriteFileBegin(tapeInfoPtr);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write FileBegin on tape\n");
- ERROR_EXIT(code);
- }
-
- writeBufPtr = &writeBuffer[0];
- firstcall = 1;
- sequence = 1;
- charList.charListT_val = 0;
- charList.charListT_len = 0;
-
- while (1) { /*w */
- /* When no data in buffer, read data from the budb_server */
- if (charList.charListT_len == 0) {
- /* get more data. let rx allocate space */
- if (charList.charListT_val) {
- free(charList.charListT_val);
- charList.charListT_val = 0;
- }
-
- /* get the data */
- code =
- ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
- UF_SINGLESERVER, firstcall,
- maxReadSize, &charList, &done);
- if (code) {
- ErrorLog(0, taskId, code, 0, "Can't read database\n");
- ERROR_EXIT(code);
- }
-
- /* If this if the first call to the budb server, create a thread
- * that will keep the connection alive (during tape changes).
- */
- if (firstcall) {
-#ifdef AFS_PTHREAD_ENV
- code = pthread_attr_init(&tattr);
- if (code) {
- ErrorLog(0, taskId, code, 0,
- "Can't pthread_attr_init Keep-alive process\n");
- ERROR_EXIT(code);
- }
-
- code =
- pthread_attr_setdetachstate(&tattr,
- PTHREAD_CREATE_DETACHED);
- if (code) {
- ErrorLog(0, taskId, code, 0,
- "Can't pthread_attr_setdetachstate Keep-alive process\n");
- ERROR_EXIT(code);
- }
-
- AFS_SIGSET_CLEAR();
- code = pthread_create(&alivePid, &tattr, KeepAlive, 0);
- AFS_SIGSET_RESTORE();
-#else
- code =
- LWP_CreateProcess(KeepAlive, 16384, 1, (void *)NULL,
- "Keep-alive process", &alivePid);
-#endif
- /* XXX should we check code here ??? XXX */
- }
- firstcall = 0;
-
- readBufPtr = charList.charListT_val;
- }
-
- if ((charList.charListT_len == 0) && done)
- break;
-
- /* compute how many bytes and transfer to the write Buffer */
- transferSize =
- (charList.charListT_len <
- (blockSize -
- writeBufNbytes)) ? charList.charListT_len : (blockSize -
- writeBufNbytes);
-
- memcpy(writeBufPtr, readBufPtr, transferSize);
- charList.charListT_len -= transferSize;
- writeBufPtr += transferSize;
- readBufPtr += transferSize;
- writeBufNbytes += transferSize;
-
- /* If filled the write buffer, then write it to tape */
- if (writeBufNbytes == blockSize) {
- code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write data on tape\n");
- ERROR_EXIT(code);
- }
-
- memset(writeBuffer, 0, blockSize);
- writeBufPtr = &writeBuffer[0];
- writeBufNbytes = 0;
-
- /* Every BIGCHUNK bytes check if aborted */
- chunksize += blockSize;
- if (chunksize > BIGCHUNK) {
- chunksize = 0;
- if (checkAbortByTaskId(taskId))
- ERROR_EXIT(TC_ABORTEDBYREQUEST);
- }
-
- /*
- * check if tape is full - since we filled a blockSize worth of data
- * assume that there is more data.
- */
- kRemaining = butm_remainingKSpace(tapeInfoPtr);
- if (kRemaining < tc_KEndMargin) {
- code = butm_WriteFileEnd(tapeInfoPtr);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write FileEnd on tape\n");
- ERROR_EXIT(code);
- }
+ code =
+ PromptForTape(RESTOREDBOPCODE, tapeName,
+ rstTapeInfoPtr->dumpid, taskId, tapecount);
+ if (code)
+ ERROR_EXIT(code);
+ }
+ interactiveFlag = 1;
+ tapecount++;
- code = butm_WriteEOT(tapeInfoPtr);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write end-of-dump on tape\n");
- ERROR_EXIT(code);
- }
+ code = butm_Mount(tapeInfoPtr, tapeName);
+ if (code) {
+ TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
+ goto getNewTape;
+ }
- /* Mark tape as having been written */
- tapeEntryPtr->useKBytes =
- tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
- tapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
+ code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1); /* will rewind the tape */
+ if (code) {
+ TapeLog(0, taskId, code, tapeInfoPtr->error,
+ "Can't read tape label\n");
+ goto getNewTape;
+ }
- unmountTape(taskId, tapeInfoPtr);
+ /* Check for name of tape and matching dump id (if applicable). */
+ if ((strcmp(oldTapeLabel.AFSName, AFStapeName) != 0)
+ || ((rstTapeInfoPtr->tapeSeq != 1)
+ && (oldTapeLabel.dumpid != rstTapeInfoPtr->dumpid))) {
+ char expTape[BU_MAXTAPELEN + 32];
+ char gotTape[BU_MAXTAPELEN + 32];
- /* Get next tape and writes its label */
- sequence++;
- code =
- GetDBTape(taskId, expires, tapeInfoPtr, dumpid, sequence,
- 1, &wroteLabel);
- if (code)
- ERROR_EXIT(code);
+ TAPENAME(expTape, tapeName, rstTapeInfoPtr->dumpid);
+ TAPENAME(gotTape, oldTapeLabel.AFSName, oldTapeLabel.dumpid);
- code = butm_WriteFileBegin(tapeInfoPtr);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write FileBegin on tape\n");
- ERROR_EXIT(code);
- }
- }
+ TLog(taskId, "Tape label expected %s, label seen %s\n", expTape,
+ gotTape);
+ goto getNewTape;
}
+
+ if (rstTapeInfoPtr->tapeSeq == 1) /* Remember this dumpId */
+ rstTapeInfoPtr->dumpid = oldTapeLabel.dumpid;
+
+ break;
+
+ getNewTape:
+ unmountTape(taskId, tapeInfoPtr);
} /*w */
- /* no more data to be read - if necessary, flush out the last buffer */
- if (writeBufNbytes > 0) {
- code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize);
- if (code) {
- ErrorLog(1, taskId, code, tapeInfoPtr->error,
- "Can't write data on tape\n");
- ERROR_EXIT(code);
- }
- }
- code = butm_WriteFileEnd(tapeInfoPtr);
- if (code) {
- ErrorLog(0, taskId, code, tapeInfoPtr->error,
- "Can't write FileEnd on tape\n");
- ERROR_EXIT(code);
- }
+ /* Initialize a tapeEntry for later inclusion into the database */
+ listEntryPtr =
+ (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList));
+ if (!listEntryPtr)
+ ERROR_EXIT(TC_NOMEMORY);
+ memset(listEntryPtr, 0, sizeof(struct tapeEntryList));
- /* Mark tape as having been written */
- tapeEntryPtr->useKBytes =
- tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
- tapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
+ /* Fill in tape entry so we can save it later */
+ strcpy(tapeEntryPtr->name, TNAME(&oldTapeLabel));
+ tapeEntryPtr->dump = oldTapeLabel.dumpid;
+ tapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
+ tapeEntryPtr->written = oldTapeLabel.creationTime;
+ tapeEntryPtr->expires = oldTapeLabel.expirationDate;
+ tapeEntryPtr->seq = extractTapeSeq(oldTapeLabel.AFSName);
+ tapeEntryPtr->useCount = oldTapeLabel.useCount;
+ tapeEntryPtr->useKBytes = 0;
+ tapeEntryPtr->labelpos = 0;
- error_exit:
- /* Let the KeepAlive process stop on its own */
- code =
- ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
- UF_END_SINGLESERVER, 0);
+ /* Thread onto end of single-linked list */
+ if (listEntryHead) {
+ endList = listEntryHead;
+ while (endList->next)
+ endList = endList->next;
+ endList->next = listEntryPtr;
+ } else
+ listEntryHead = listEntryPtr;
- if (writeBlock)
- free(writeBlock);
- if (charList.charListT_val)
- free(charList.charListT_val);
+ error_exit:
return (code);
}
+static afs_int32 nbytes = 0; /* # bytes left in buffer */
+static void
+initTapeBuffering()
+{
+ nbytes = 0;
+}
+
/* restoreDbEntries
* restore all the items on the tape
return (code);
}
+/* restoreDbFromTape
+ * restore the backup database from tape.
+ */
+
+void *
+restoreDbFromTape(void *param)
+{
+ afs_uint32 taskId = (afs_uint32) param;
+ afs_int32 code = 0;
+ afs_int32 i;
+ struct butm_tapeInfo tapeInfo;
+ struct rstTapeInfo rstTapeInfo;
+ struct budb_dumpEntry dumpEntry;
+
+ extern struct tapeConfig globalTapeConfig;
+ extern struct deviceSyncNode *deviceLatch;
+
+ setStatus(taskId, DRIVE_WAIT);
+ EnterDeviceQueue(deviceLatch); /* lock tape device */
+ clearStatus(taskId, DRIVE_WAIT);
+
+ printf("\n\n");
+ TLog(taskId, "RestoreDb\n");
+
+ tapeInfo.structVersion = BUTM_MAJORVERSION;
+ code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
+ if (code) {
+ ErrorLog(0, taskId, code, tapeInfo.error,
+ "Can't initialize tape module\n");
+ ERROR_EXIT(code);
+ }
+
+ listEntryHead = NULL;
+
+ rstTapeInfo.taskId = taskId;
+ rstTapeInfo.tapeSeq = 1;
+ rstTapeInfo.dumpid = 0;
+
+ code = readDbTape(&tapeInfo, &rstTapeInfo, autoQuery);
+ if (code)
+ ERROR_EXIT(code);
+
+ code = restoreDbEntries(&tapeInfo, &rstTapeInfo);
+ if (code)
+ ERROR_EXIT(code);
+
+ error_exit:
+ /* Now put this dump into the database */
+ /* Make a dump entry from first tape */
+ listEntryPtr = listEntryHead;
+ if (listEntryPtr) {
+ makeDbDumpEntry(tapeEntryPtr, &dumpEntry);
+ if (dumpEntry.id != 0) {
+ i = bcdb_CreateDump(&dumpEntry);
+ if (i) {
+ if (i == BUDB_DUMPIDEXISTS)
+ fprintf(stderr,
+ "Dump id %d not added to database - already exists\n",
+ dumpEntry.id);
+ else
+ TapeLog(0, taskId, i, 0,
+ "Dump id %d not added to database\n",
+ dumpEntry.id);
+ } else {
+ i = addTapesToDb(taskId);
+ if (!code)
+ code = i;
+
+ i = bcdb_FinishDump(&dumpEntry);
+ if (!code)
+ code = i;
+ }
+ }
+ freeTapeList();
+ }
+
+ unmountTape(taskId, &tapeInfo);
+ waitDbWatcher();
+
+ if (code == TC_ABORTEDBYREQUEST) {
+ TLog(taskId, "RestoreDb: Aborted by request\n");
+ clearStatus(taskId, ABORT_REQUEST);
+ setStatus(taskId, ABORT_DONE);
+ } else if (code) {
+ TapeLog(0, taskId, code, 0, "RestoreDb: Finished with errors\n");
+ setStatus(taskId, TASK_ERROR);
+ } else {
+ TLog(taskId, "RestoreDb: Finished\n");
+ }
+
+ LeaveDeviceQueue(deviceLatch);
+ setStatus(taskId, TASK_DONE);
+
+ return (void *)(code);
+}
+
+/* KeepAlive
+ *
+ * While dumping the database, keeps the connection alive.
+ * Every 10 seconds, wake up and ask to read 0 bytes of the database.
+ * This resets the database's internal timer so that it does not
+ * prematuraly quit (on asking for new tapes and such).
+ *
+ * Use the same udbHandle as writeDbDump so we go to the same server.
+ */
+void *
+KeepAlive(void *unused)
+{
+ charListT charList;
+ afs_int32 code;
+ afs_int32 done;
+
+ extern struct udbHandleS udbHandle;
+
+ while (1) {
+#ifdef AFS_PTHREAD_ENV
+ sleep(5);
+#else
+ IOMGR_Sleep(5);
+#endif
+ charList.charListT_val = 0;
+ charList.charListT_len = 0;
+ code =
+ ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
+ UF_SINGLESERVER, 0, 0, &charList, &done);
+ if (code || done)
+ break;
+ }
+ return 0;
+}
+
+
/* restoreDbHeader
* restore special items in the header
*/
/* Add the database header to the database */
code =
- ubik_Call(BUDB_RestoreDbHeader, udbHandle.uh_client, 0,
+ ubik_BUDB_RestoreDbHeader(udbHandle.uh_client, 0,
&hostDbHeader);
if (code) {
ErrorLog(0, rstTapeInfoPtr->taskId, code, 0,
struct budb_tapeEntry netTapeEntry, hostTapeEntry;
struct budb_volumeEntry netVolumeEntry, hostVolumeEntry;
struct structDumpHeader netItemHeader;
- afs_int32 newTape, taskId;
+ afs_int32 taskId;
int restoreThisDump = 1;
- afs_int32 code = 0, tcode;
+ afs_int32 code = 0;
extern struct udbHandleS udbHandle;
static char *tapeReadBuffer = 0; /* input buffer */
static char *tapeReadBufferPtr = 0; /* position in buffer */
-static afs_int32 nbytes = 0; /* # bytes left in buffer */
-
-static
-initTapeBuffering()
-{
- nbytes = 0;
-}
/* getTapeData
* Read information from tape, and place the requested number of bytes