Bug Summary

File:butc/tcudbprocs.c
Location:line 1174, column 2
Description:Assigned value is always the same as the existing value

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10#include <afsconfig.h>
11#include <afs/param.h>
12
13#include <afs/procmgmt.h>
14#include <roken.h>
15
16#ifdef IGNORE_SOME_GCC_WARNINGS
17# pragma GCC diagnostic warning "-Wimplicit-function-declaration"
18#endif
19
20#include <rx/xdr.h>
21#include <rx/rx.h>
22#include <afs/afsint.h>
23#include <afs/afs_assert.h>
24#include <afs/prs_fs.h>
25#include <afs/nfs.h>
26#include <lwp.h>
27#include <lock.h>
28#include <afs/cellconfig.h>
29#include <afs/keys.h>
30#include <ubik.h>
31#include <afs/acl.h>
32#include <afs/volser.h>
33#include <afs/vlserver.h>
34#include <afs/tcdata.h>
35#include <afs/budb.h>
36#include <afs/budb_client.h>
37#include <afs/bubasics.h>
38#include <afs/bucoord_prototypes.h>
39#include <afs/butm_prototypes.h>
40#include <afs/budb_prototypes.h>
41#include <afs/afsutil.h>
42
43#include "butc_internal.h"
44#include "error_macros.h"
45
46/* GLOBAL CONFIGURATION PARAMETERS */
47#define BIGCHUNK102400 102400
48
49extern int dump_namecheck;
50extern int autoQuery;
51
52struct rstTapeInfo {
53 afs_int32 taskId;
54 afs_int32 tapeSeq;
55 afs_uint32 dumpid;
56};
57
58static void initTapeBuffering(void);
59static int writeDbDump(struct butm_tapeInfo *, afs_uint32, Dateafs_uint32, afs_uint32);
60static int restoreDbEntries(struct butm_tapeInfo *, struct rstTapeInfo *);
61
62int getTapeData(struct butm_tapeInfo *, struct rstTapeInfo *, void *,
63 afs_int32);
64int restoreDbHeader(struct butm_tapeInfo *, struct rstTapeInfo *,
65 struct structDumpHeader *);
66int restoreDbDump(struct butm_tapeInfo *, struct rstTapeInfo *,
67 struct structDumpHeader *);
68int restoreText(struct butm_tapeInfo *, struct rstTapeInfo *,
69 struct structDumpHeader *);
70
71
72
73void * KeepAlive(void *);
74/* CreateDBDump
75 * create a dump entry for a saved database
76 */
77
78afs_int32
79CreateDBDump(struct budb_dumpEntry *dumpEntryPtr)
80{
81 afs_int32 code = 0;
82
83 memset(dumpEntryPtr, 0, sizeof(struct budb_dumpEntry));
84
85 strcpy(dumpEntryPtr->name, DUMP_TAPE_NAME"Ubik_db_dump");
86 strcpy(dumpEntryPtr->tapes.format, DUMP_TAPE_NAME"Ubik_db_dump");
87 strcat(dumpEntryPtr->tapes.format, ".%d");
88 strcpy(dumpEntryPtr->volumeSetName, "");
89 strcpy(dumpEntryPtr->dumpPath, "");
90 dumpEntryPtr->created = 0; /* let database assign it */
91 dumpEntryPtr->incTime = 0;
92 dumpEntryPtr->nVolumes = 0;
93 dumpEntryPtr->initialDumpID = 0;
94 dumpEntryPtr->parent = 0;
95 dumpEntryPtr->level = 0;
96 dumpEntryPtr->tapes.maxTapes = 0;
97 dumpEntryPtr->tapes.b = 1;
98
99 /* now call the database to create the entry */
100 code = bcdb_CreateDump(dumpEntryPtr);
101 return (code);
102}
103
104struct tapeEntryList {
105 struct tapeEntryList *next;
106 afs_uint32 oldDumpId;
107 struct budb_tapeEntry tapeEnt;
108};
109struct tapeEntryList *listEntryHead;
110struct tapeEntryList *listEntryPtr;
111#define tapeEntryPtr(&listEntryPtr->tapeEnt) (&listEntryPtr->tapeEnt)
112struct budb_dumpEntry lastDump; /* the last dump of this volset */
113
114/* GetDBTape
115 * Load a DB tape, read and over write its label.
116 * Leave the tape mounted.
117 */
118afs_int32
119GetDBTape(afs_int32 taskId, Dateafs_uint32 expires, struct butm_tapeInfo *tapeInfoPtr,
120 afs_uint32 dumpid, afs_int32 sequence, int queryFlag,
121 int *wroteLabel)
122{
123 afs_int32 code = 0;
124 int interactiveFlag;
125 char tapeName[BU_MAXTAPELEN32];
126 char strlevel[5];
127 struct timeval tp;
128 afs_int32 curTime;
129 int tapecount = 1;
130
131 struct butm_tapeLabel oldTapeLabel, newLabel;
132 struct tapeEntryList *endList;
133
134 /* construct the name of the tape */
135 sprintf(tapeName, "%s.%-d", DUMP_TAPE_NAME"Ubik_db_dump", sequence);
136
137 interactiveFlag = queryFlag;
138 *wroteLabel = 0;
139
140 while (!*wroteLabel) { /*w */
141 if (interactiveFlag) { /* need a tape to write */
142 code =
143 PromptForTape(SAVEDBOPCODE6, tapeName, dumpid, taskId,
144 tapecount);
145 if (code)
146 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
147 }
148 interactiveFlag = 1;
149 tapecount++;
150
151 code = butm_Mount(tapeInfoPtr, tapeName)(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,tapeName);
152 if (code) {
153 TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
154 goto getNewTape;
155 }
156
157 memset(&oldTapeLabel, 0, sizeof(oldTapeLabel));
158 code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&oldTapeLabel
,1)
; /* rewind tape */
159 if (code) {
160 oldTapeLabel.useCount = 0; /* no label exists */
161 oldTapeLabel.structVersion = 0;
162 strcpy(oldTapeLabel.pName, "");
163 } else {
164 /* If tape has a name, it must be null or database tape name */
165 if (dump_namecheck && strcmp(oldTapeLabel.AFSName, "")
166 && !databaseTape(oldTapeLabel.AFSName)) {
167 char gotName[BU_MAXTAPELEN32 + 32];
168
169 LABELNAME(gotName, &oldTapeLabel)if (!strcmp("", ( strcmp((&oldTapeLabel)->pName,"") ? (
&oldTapeLabel)->pName : ( strcmp((&oldTapeLabel)->
AFSName,"") ? (&oldTapeLabel)->AFSName : "<NULL>"
) ))) sprintf(gotName, "<NULL>"); else if ((&oldTapeLabel
)->dumpid == 0) sprintf(gotName, "%s", ( strcmp((&oldTapeLabel
)->pName,"") ? (&oldTapeLabel)->pName : ( strcmp((&
oldTapeLabel)->AFSName,"") ? (&oldTapeLabel)->AFSName
: "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp
((&oldTapeLabel)->pName,"") ? (&oldTapeLabel)->
pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (&
oldTapeLabel)->AFSName : "<NULL>" ) ), (&oldTapeLabel
)->dumpid);
;
170 TLog(taskId,
171 "This tape %s must be a database tape or NULL tape\n",
172 gotName);
173
174 getNewTape:
175 unmountTape(taskId, tapeInfoPtr);
176 continue;
177 }
178
179 /* Do not overwrite a tape that belongs to this dump */
180 if (oldTapeLabel.dumpid && (oldTapeLabel.dumpid == dumpid)) {
181 ErrorLog(0, taskId, 0, 0,
182 "Can't overwrite tape containing the dump in progress\n");
183 goto getNewTape;
184 }
185
186 /* On first tape, the savedb has not started yet, so the database is not locked
187 * and we can therefore, access information from it. This is easier to do because
188 * database dumps don't have appended dumps (nor appended).
189 */
190 if (sequence == 1) {
191 afs_uint32 dmp;
192 struct budb_dumpEntry de, de2;
193
194 /* Verify the tape has not expired
195 * Early database dumps don't have a dumpid
196 */
197 if (!tapeExpired(&oldTapeLabel)) {
198 TLog(taskId, "This tape has not expired\n");
199 goto getNewTape;
200 }
201
202 /* Since the dumpset on this tape will be deleted from database, check if
203 * any of the dumps in this dumpset are most-recent-dumps.
204 */
205 for (dmp = oldTapeLabel.dumpid; dmp; dmp = de.appendedDumpID) {
206 if (dmp == lastDump.id) {
207 memcpy(&de, &lastDump, sizeof(de));
208 memcpy(&de2, &lastDump, sizeof(de2));
209 } else {
210 code = bcdb_FindDumpByID(dmp, &de);
211 if (code)
212 break;
213 sprintf(strlevel, "%d", de.level);
214 code =
215 bcdb_FindLatestDump(de.volumeSetName, strlevel,
216 &de2);
217 if (code)
218 continue;
219 }
220
221 if (de.id == de2.id) {
222 if (strcmp(DUMP_TAPE_NAME"Ubik_db_dump", de2.name) == 0) {
223 ErrorLog(0, taskId, 0, 0,
224 "Warning: Overwriting most recent dump %s (DumpID %u)\n",
225 de.name, de.id);
226 } else {
227 ErrorLog(0, taskId, 0, 0,
228 "Warning: Overwriting most recent dump of the '%s' volumeset: %s (DumpID %u)\n",
229 de.volumeSetName, de.name, de.id);
230 }
231 }
232 }
233 }
234
235 /* Otherwise, the savedb is in progress and we can't
236 * access the database (it's locked). So we rely on the
237 * information available (and not the backup database).
238 */
239 else {
240 /* Check the tape's expiration date. Use the expiration on the label */
241 gettimeofday(&tp, NULL((void *)0));
242 curTime = tp.tv_sec;
243 if (curTime < oldTapeLabel.expirationDate) {
244 TLog(taskId, "This tape has not expired\n");
245 goto getNewTape;
246 }
247
248 /* Check if this previous-dump of the dump-in-progress is on this tape */
249 if (oldTapeLabel.dumpid
250 && (oldTapeLabel.dumpid == lastDump.id)) {
251 ErrorLog(0, taskId, 0, 0,
252 "Warning: Overwriting most recent dump %s (DumpID %u)\n",
253 lastDump.name, lastDump.id);
254 }
255
256 }
257 }
258
259 GetNewLabel(tapeInfoPtr, oldTapeLabel.pName, tapeName, &newLabel);
260 newLabel.expirationDate = expires;
261 newLabel.useCount = oldTapeLabel.useCount + 1;
262 newLabel.dumpid = dumpid;
263 newLabel.size = tapeInfoPtr->tapeSize;
264
265 code = butm_Create(tapeInfoPtr, &newLabel, 1)(*((tapeInfoPtr)->ops.create))(tapeInfoPtr,&newLabel,1
)
; /* rewind tape */
266 if (code) {
267 TapeLog(0, taskId, code, tapeInfoPtr->error,
268 "Can't label tape\n");
269 goto getNewTape;
270 }
271
272 *wroteLabel = 1;
273
274 /* Initialize a tapeEntry for later inclusion into the database */
275 listEntryPtr =
276 (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList));
277 if (!listEntryPtr)
278 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
279 memset(listEntryPtr, 0, sizeof(struct tapeEntryList));
280
281 /* Remember dumpid so we can delete it later */
282 if ((oldTapeLabel.structVersion >= TAPE_VERSION_33)
283 && oldTapeLabel.dumpid)
284 listEntryPtr->oldDumpId = oldTapeLabel.dumpid;
285
286 /* Fill in tape entry so we can save it later */
287 strcpy(tapeEntryPtr(&listEntryPtr->tapeEnt)->name, TNAME(&newLabel)( strcmp((&newLabel)->pName,"") ? (&newLabel)->
pName : ( strcmp((&newLabel)->AFSName,"") ? (&newLabel
)->AFSName : "<NULL>" ) )
);
288 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_BEINGWRITTEN(1<<2);
289 tapeEntryPtr(&listEntryPtr->tapeEnt)->written = newLabel.creationTime;
290 tapeEntryPtr(&listEntryPtr->tapeEnt)->expires = expires;
291 tapeEntryPtr(&listEntryPtr->tapeEnt)->seq = sequence;
292 tapeEntryPtr(&listEntryPtr->tapeEnt)->useCount = oldTapeLabel.useCount + 1;
293 tapeEntryPtr(&listEntryPtr->tapeEnt)->dump = dumpid;
294 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes = 0;
295 tapeEntryPtr(&listEntryPtr->tapeEnt)->labelpos = 0;
296
297 /* Thread onto end of single-linked list */
298 if (listEntryHead) {
299 endList = listEntryHead;
300 while (endList->next)
301 endList = endList->next;
302 endList->next = listEntryPtr;
303 } else
304 listEntryHead = listEntryPtr;
305 } /*w */
306
307 error_exit:
308 return (code);
309}
310
311/* freeTapeList
312 * With the list of tapes, free the structures.
313 */
314
315afs_int32
316freeTapeList(void)
317{
318 struct tapeEntryList *next;
319
320 listEntryPtr = listEntryHead;
321 while (listEntryPtr) {
322 next = listEntryPtr->next;
323 free(listEntryPtr);
324 listEntryPtr = next;
325 }
326
327 listEntryHead = NULL((void *)0);
328 return (0);
329}
330
331/* addTapesToDb
332 * With the list of tapes, add them to the database.
333 * Also delete any olddumpids that are around.
334 */
335
336afs_int32
337addTapesToDb(afs_int32 taskId)
338{
339 afs_int32 code = 0;
340 afs_int32 i, new;
341 struct tapeEntryList *next;
342
343 listEntryPtr = listEntryHead;
344 while (listEntryPtr) {
345 next = listEntryPtr->next;
346
347 /* Remove the old database entry */
348 if (listEntryPtr->oldDumpId) {
349 i = bcdb_deleteDump(listEntryPtr->oldDumpId, 0, 0, 0);
350 if (i && (i != BUDB_NOENT(156303877L))) {
351 ErrorLog(0, taskId, i, 0,
352 "Unable to delete old DB entry %u.\n",
353 listEntryPtr->oldDumpId);
354 }
355 }
356
357 /* Add the tape to the database */
358 code = bcdb_UseTape(tapeEntryPtr(&listEntryPtr->tapeEnt), &new);
359 if (code) {
360 ErrorLog(0, taskId, code, 0, "Can't add tape to database: %s\n",
361 tapeEntryPtr(&listEntryPtr->tapeEnt)->name);
362 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
363 }
364
365 code = bcdb_FinishTape(tapeEntryPtr(&listEntryPtr->tapeEnt));
366 if (code) {
367 ErrorLog(0, taskId, code, 0, "Can't finish tape: %s\n",
368 tapeEntryPtr(&listEntryPtr->tapeEnt)->name);
369 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
370 }
371
372 listEntryPtr = next;
373 }
374
375 error_exit:
376 return (code);
377}
378
379/* writeDbDump
380 * notes:
381 * this code assumes that the blocksize on reads is smaller than
382 * the blocksize on writes
383 */
384
385static int
386writeDbDump(struct butm_tapeInfo *tapeInfoPtr, afs_uint32 taskId,
387 Dateafs_uint32 expires, afs_uint32 dumpid)
388{
389 afs_int32 blockSize;
390 afs_int32 writeBufNbytes = 0;
391 char *writeBlock = 0;
392 char *writeBuffer = 0;
393 char *writeBufPtr;
394 afs_int32 transferSize;
395
396 char *readBufPtr = NULL((void *)0);
397 afs_int32 maxReadSize;
398
399 charListT charList;
400 afs_int32 done;
401 afs_int32 code;
402 afs_int32 chunksize = 0;
403 afs_int32 tc_EndMargin, tc_KEndMargin, kRemaining;
404 int sequence;
405 int wroteLabel;
406 int firstcall;
407#ifdef AFS_PTHREAD_ENV
408 pthread_t alivePid;
409 pthread_attr_t tattr;
410 AFS_SIGSET_DECL;
411#else
412 PROCESS alivePid;
413#endif
414
415 extern struct tapeConfig globalTapeConfig;
416 extern struct udbHandleS udbHandle;
417
418 blockSize = BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
419 writeBlock = (char *)malloc(BUTM_BLOCKSIZE16384);
420 if (!writeBlock)
421 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
422
423 writeBuffer = writeBlock + sizeof(struct blockMark);
424 memset(writeBuffer, 0, BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))));
425 maxReadSize = 1024;
426
427 /*
428 * The margin of space to check for end of tape is set to the
429 * amount of space used to write an end-of-tape multiplied by 2.
430 * The amount of space is size of a 16K EODump marker, its EOF
431 * marker, and up to two EOF markers done on close (1 16K blocks +
432 * 3 EOF * markers).
433 */
434 tc_EndMargin = (16384 + 3 * globalTapeConfig.fileMarkSize) * 2;
435 tc_KEndMargin = tc_EndMargin / 1024;
436
437 /* have to write enclose the dump in file marks */
438 code = butm_WriteFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileBegin))(tapeInfoPtr);
439 if (code) {
440 ErrorLog(0, taskId, code, tapeInfoPtr->error,
441 "Can't write FileBegin on tape\n");
442 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
443 }
444
445 writeBufPtr = &writeBuffer[0];
446 firstcall = 1;
447 sequence = 1;
448 charList.charListT_val = 0;
449 charList.charListT_len = 0;
450
451 while (1) { /*w */
452 /* When no data in buffer, read data from the budb_server */
453 if (charList.charListT_len == 0) {
454 /* get more data. let rx allocate space */
455 if (charList.charListT_val) {
456 free(charList.charListT_val);
457 charList.charListT_val = 0;
458 }
459
460 /* get the data */
461 code =
462 ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
463 UF_SINGLESERVER1, firstcall,
464 maxReadSize, &charList, &done);
465 if (code) {
466 ErrorLog(0, taskId, code, 0, "Can't read database\n");
467 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
468 }
469
470 /* If this if the first call to the budb server, create a thread
471 * that will keep the connection alive (during tape changes).
472 */
473 if (firstcall) {
474#ifdef AFS_PTHREAD_ENV
475 code = pthread_attr_init(&tattr);
476 if (code) {
477 ErrorLog(0, taskId, code, 0,
478 "Can't pthread_attr_init Keep-alive process\n");
479 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
480 }
481
482 code =
483 pthread_attr_setdetachstate(&tattr,
484 PTHREAD_CREATE_DETACHED);
485 if (code) {
486 ErrorLog(0, taskId, code, 0,
487 "Can't pthread_attr_setdetachstate Keep-alive process\n");
488 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
489 }
490
491 AFS_SIGSET_CLEAR();
492 code = pthread_create(&alivePid, &tattr, KeepAlive, 0);
493 AFS_SIGSET_RESTORE();
494#else
495 code =
496 LWP_CreateProcess(KeepAlive, 16384, 1, (void *)NULL((void *)0),
497 "Keep-alive process", &alivePid);
498#endif
499 /* XXX should we check code here ??? XXX */
500 }
501 firstcall = 0;
502
503 readBufPtr = charList.charListT_val;
504 }
505
506 if ((charList.charListT_len == 0) && done)
507 break;
508
509 /* compute how many bytes and transfer to the write Buffer */
510 transferSize =
511 (charList.charListT_len <
512 (blockSize -
513 writeBufNbytes)) ? charList.charListT_len : (blockSize -
514 writeBufNbytes);
515
516 memcpy(writeBufPtr, readBufPtr, transferSize);
517 charList.charListT_len -= transferSize;
518 writeBufPtr += transferSize;
519 readBufPtr += transferSize;
520 writeBufNbytes += transferSize;
521
522 /* If filled the write buffer, then write it to tape */
523 if (writeBufNbytes == blockSize) {
524 code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize)(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,writeBuffer
,1,blockSize)
;
525 if (code) {
526 ErrorLog(0, taskId, code, tapeInfoPtr->error,
527 "Can't write data on tape\n");
528 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
529 }
530
531 memset(writeBuffer, 0, blockSize);
532 writeBufPtr = &writeBuffer[0];
533 writeBufNbytes = 0;
534
535 /* Every BIGCHUNK bytes check if aborted */
536 chunksize += blockSize;
537 if (chunksize > BIGCHUNK102400) {
538 chunksize = 0;
539 if (checkAbortByTaskId(taskId))
540 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
541 }
542
543 /*
544 * check if tape is full - since we filled a blockSize worth of data
545 * assume that there is more data.
546 */
547 kRemaining = butm_remainingKSpace(tapeInfoPtr)((tapeInfoPtr)->tapeSize - ((tapeInfoPtr)->kBytes*(tapeInfoPtr
)->coefBytes ))
;
548 if (kRemaining < tc_KEndMargin) {
549 code = butm_WriteFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileEnd))(tapeInfoPtr);
550 if (code) {
551 ErrorLog(0, taskId, code, tapeInfoPtr->error,
552 "Can't write FileEnd on tape\n");
553 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
554 }
555
556 code = butm_WriteEOT(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeEOT))(tapeInfoPtr);
557 if (code) {
558 ErrorLog(0, taskId, code, tapeInfoPtr->error,
559 "Can't write end-of-dump on tape\n");
560 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
561 }
562
563 /* Mark tape as having been written */
564 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes =
565 tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
566 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_WRITTEN(1<<5);
567
568 unmountTape(taskId, tapeInfoPtr);
569
570 /* Get next tape and writes its label */
571 sequence++;
572 code =
573 GetDBTape(taskId, expires, tapeInfoPtr, dumpid, sequence,
574 1, &wroteLabel);
575 if (code)
576 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
577
578 code = butm_WriteFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileBegin))(tapeInfoPtr);
579 if (code) {
580 ErrorLog(0, taskId, code, tapeInfoPtr->error,
581 "Can't write FileBegin on tape\n");
582 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
583 }
584 }
585 }
586 } /*w */
587
588 /* no more data to be read - if necessary, flush out the last buffer */
589 if (writeBufNbytes > 0) {
590 code = butm_WriteFileData(tapeInfoPtr, writeBuffer, 1, blockSize)(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,writeBuffer
,1,blockSize)
;
591 if (code) {
592 ErrorLog(1, taskId, code, tapeInfoPtr->error,
593 "Can't write data on tape\n");
594 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
595 }
596 }
597
598 code = butm_WriteFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileEnd))(tapeInfoPtr);
599 if (code) {
600 ErrorLog(0, taskId, code, tapeInfoPtr->error,
601 "Can't write FileEnd on tape\n");
602 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
603 }
604
605 /* Mark tape as having been written */
606 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes =
607 tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
608 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_WRITTEN(1<<5);
609
610 error_exit:
611 /* Let the KeepAlive process stop on its own */
612 code =
613 ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
614 UF_END_SINGLESERVER2, 0);
615
616 if (writeBlock)
617 free(writeBlock);
618 if (charList.charListT_val)
619 free(charList.charListT_val);
620 return (code);
621}
622
623/* saveDbToTape
624 * dump backup database to tape
625 */
626
627void *
628saveDbToTape(void *param)
629{
630 struct saveDbIf *saveDbIfPtr = (struct saveDbIf *)param;
631 afs_int32 code = 0;
632 afs_int32 i;
633 int wroteLabel;
634 afs_uint32 taskId;
635 Dateafs_uint32 expires;
636
637 struct butm_tapeInfo tapeInfo;
638 struct budb_dumpEntry dumpEntry;
639
640 extern struct deviceSyncNode *deviceLatch;
641 extern struct tapeConfig globalTapeConfig;
642
643 afs_pthread_setname_self("Db save")(void)0;
644 expires = (saveDbIfPtr->archiveTime ? NEVERDATE037777777777 : 0);
645 taskId = saveDbIfPtr->taskId;
646
647 setStatus(taskId, DRIVE_WAIT0x100);
648 EnterDeviceQueue(deviceLatch); /* lock tape device */
649 clearStatus(taskId, DRIVE_WAIT0x100);
650
651 printf("\n\n");
652 TLog(taskId, "SaveDb\n");
653
654 tapeInfo.structVersion = BUTM_MAJORVERSION2;
655 code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
656 if (code) {
657 ErrorLog(0, taskId, code, tapeInfo.error,
658 "Can't initialize tape module\n");
659 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
660 }
661
662 /* Determine what the last database dump was */
663 memset(&lastDump, 0, sizeof(lastDump));
664 code = bcdb_FindLatestDump("", "", &lastDump);
665 if (code) {
666 if (code != BUDB_NODUMPNAME(156303874L)) {
667 ErrorLog(0, taskId, code, 0, "Can't read backup database\n");
668 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
669 }
670 memset(&lastDump, 0, sizeof(lastDump));
671 }
672
673 code = CreateDBDump(&dumpEntry); /* Create a dump for this tape */
674 if (code) {
675 ErrorLog(0, taskId, code, 0, "Can't create dump in database\n");
676 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
677 }
678
679
680 listEntryHead = NULL((void *)0);
681
682 /* Get the tape and write a new label to it */
683 code =
684 GetDBTape(taskId, expires, &tapeInfo, dumpEntry.id, 1, autoQuery,
685 &wroteLabel);
686
687 /*
688 * If did not write the label, remove created dump
689 * Else if wrote the label, remove old dump from db so it's not saved.
690 */
691 if (!wroteLabel) {
692 i = bcdb_deleteDump(dumpEntry.id, 0, 0, 0);
693 dumpEntry.id = 0;
694 if (i && (i != BUDB_NOENT(156303877L)))
695 ErrorLog(0, taskId, i, 0, "Unable to delete DB entry %u.\n",
696 dumpEntry.id);
697 } else if (listEntryHead->oldDumpId) {
698 i = bcdb_deleteDump(listEntryHead->oldDumpId, 0, 0, 0);
699 listEntryHead->oldDumpId = 0;
700 if (i && (i != BUDB_NOENT(156303877L))) {
701 ErrorLog(0, taskId, i, 0, "Unable to delete old DB entry %u.\n",
702 listEntryHead->oldDumpId);
703 ERROR_EXIT(i)do { code = i; goto error_exit; } while (0);
704 }
705 }
706 if (code)
707 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
708
709 TapeLog(1, taskId, 0, 0, "Tape accepted - now dumping database\n");
710
711 /* we have a writable tape */
712 code = writeDbDump(&tapeInfo, taskId, expires, dumpEntry.id);
713 if (code)
714 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
715
716 /* Now delete the entries between time 0 and archive-time */
717 if (saveDbIfPtr->archiveTime)
718 code = bcdb_deleteDump(0, 0, saveDbIfPtr->archiveTime, 0);
719
720 error_exit:
721 unmountTape(taskId, &tapeInfo);
722
723 /* Add this dump's tapes to the database and mark it finished */
724 if (dumpEntry.id) {
725 i = addTapesToDb(taskId);
726 if (!code)
727 code = i;
728
729 i = bcdb_FinishDump(&dumpEntry);
730 if (!code)
731 code = i;
732 }
733 freeTapeList();
734
735 if (code == TC_ABORTEDBYREQUEST(156566278L)) {
736 TLog(taskId, "SaveDb: Aborted by request\n");
737 clearStatus(taskId, ABORT_REQUEST0x2);
738 setStatus(taskId, ABORT_DONE0x8);
739 } else if (code) {
740 TapeLog(0, taskId, code, 0, "SaveDb: Finished with errors\n");
741 setStatus(taskId, TASK_ERROR0x80);
742 } else {
743 TLog(taskId, "SaveDb: Finished\n");
744 }
745 setStatus(taskId, TASK_DONE0x20);
746
747 free(saveDbIfPtr);
748 LeaveDeviceQueue(deviceLatch);
749 return (void *)(intptr_t)(code);
750}
751
752
753/* makeDbDumpEntry()
754 * Make a database dump entry given a tape label.
755 */
756
757afs_int32
758makeDbDumpEntry(struct budb_tapeEntry *tapeEntPtr,
759 struct budb_dumpEntry *dumpEntryPtr)
760{
761 memset(dumpEntryPtr, 0, sizeof(struct budb_dumpEntry));
762
763 dumpEntryPtr->id = tapeEntPtr->dump;
764 dumpEntryPtr->initialDumpID = 0;
765 dumpEntryPtr->parent = 0;
766 dumpEntryPtr->level = 0;
767 dumpEntryPtr->flags = 0;
768
769 strcpy(dumpEntryPtr->volumeSetName, "");
770 strcpy(dumpEntryPtr->dumpPath, "");
771 strcpy(dumpEntryPtr->name, DUMP_TAPE_NAME"Ubik_db_dump");
772
773 dumpEntryPtr->created = tapeEntPtr->dump;
774 dumpEntryPtr->incTime = 0;
775 dumpEntryPtr->nVolumes = 0;
776
777 strcpy(dumpEntryPtr->tapes.format, DUMP_TAPE_NAME"Ubik_db_dump");
778 strcat(dumpEntryPtr->tapes.format, ".%d");
779 dumpEntryPtr->tapes.b = tapeEntPtr->seq;
780 dumpEntryPtr->tapes.maxTapes = 0;
781 return 0;
782}
783
784/* readDbTape
785 * prompt for a specific database tape
786 */
787
788afs_int32
789readDbTape(struct butm_tapeInfo *tapeInfoPtr,
790 struct rstTapeInfo *rstTapeInfoPtr, int query)
791{
792 afs_int32 code = 0;
793 int interactiveFlag;
794 afs_int32 taskId;
795 struct butm_tapeLabel oldTapeLabel;
796 char AFStapeName[BU_MAXTAPELEN32], tapeName[BU_MAXTAPELEN32];
797 struct tapeEntryList *endList;
798 int tapecount = 1;
799 struct budb_dumpEntry de;
800 struct budb_tapeEntry te;
801
802 taskId = rstTapeInfoPtr->taskId;
803 interactiveFlag = query;
804
805 /* construct the name of the tape */
806 sprintf(AFStapeName, "%s.%-d", DUMP_TAPE_NAME"Ubik_db_dump", rstTapeInfoPtr->tapeSeq);
807 strcpy(tapeName, AFStapeName);
808
809 /* Will prompt for the latest saved database tape, but will accept any one */
810 if (rstTapeInfoPtr->tapeSeq == 1) {
811 code = bcdb_FindLatestDump("", "", &de);
812 if (!code)
813 rstTapeInfoPtr->dumpid = de.id;
814 }
815 if (rstTapeInfoPtr->dumpid) {
816 code =
817 bcdb_FindTapeSeq(rstTapeInfoPtr->dumpid, rstTapeInfoPtr->tapeSeq,
818 &te);
819 if (!code)
820 strcpy(tapeName, te.name);
821 }
822 code = 0;
823
824 while (1) { /*w */
825 if (interactiveFlag) { /* need a tape to read */
826 code =
827 PromptForTape(RESTOREDBOPCODE7, tapeName,
828 rstTapeInfoPtr->dumpid, taskId, tapecount);
829 if (code)
830 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
831 }
832 interactiveFlag = 1;
833 tapecount++;
834
835 code = butm_Mount(tapeInfoPtr, tapeName)(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,tapeName);
836 if (code) {
837 TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
838 goto getNewTape;
839 }
840
841 code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&oldTapeLabel
,1)
; /* will rewind the tape */
842 if (code) {
843 TapeLog(0, taskId, code, tapeInfoPtr->error,
844 "Can't read tape label\n");
845 goto getNewTape;
846 }
847
848 /* Check for name of tape and matching dump id (if applicable). */
849 if ((strcmp(oldTapeLabel.AFSName, AFStapeName) != 0)
850 || ((rstTapeInfoPtr->tapeSeq != 1)
851 && (oldTapeLabel.dumpid != rstTapeInfoPtr->dumpid))) {
852 char expTape[BU_MAXTAPELEN32 + 32];
853 char gotTape[BU_MAXTAPELEN32 + 32];
854
855 TAPENAME(expTape, tapeName, rstTapeInfoPtr->dumpid)if (!strcmp("", tapeName)) sprintf(expTape, "<NULL>"); else
if (rstTapeInfoPtr->dumpid == 0) sprintf(expTape, "%s", tapeName
); else sprintf(expTape, "%s (%u)", tapeName, rstTapeInfoPtr->
dumpid);
;
856 TAPENAME(gotTape, oldTapeLabel.AFSName, oldTapeLabel.dumpid)if (!strcmp("", oldTapeLabel.AFSName)) sprintf(gotTape, "<NULL>"
); else if (oldTapeLabel.dumpid == 0) sprintf(gotTape, "%s", oldTapeLabel
.AFSName); else sprintf(gotTape, "%s (%u)", oldTapeLabel.AFSName
, oldTapeLabel.dumpid);
;
857
858 TLog(taskId, "Tape label expected %s, label seen %s\n", expTape,
859 gotTape);
860 goto getNewTape;
861 }
862
863 if (rstTapeInfoPtr->tapeSeq == 1) /* Remember this dumpId */
864 rstTapeInfoPtr->dumpid = oldTapeLabel.dumpid;
865
866 break;
867
868 getNewTape:
869 unmountTape(taskId, tapeInfoPtr);
870 } /*w */
871
872
873 /* Initialize a tapeEntry for later inclusion into the database */
874 listEntryPtr =
875 (struct tapeEntryList *)malloc(sizeof(struct tapeEntryList));
876 if (!listEntryPtr)
877 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
878 memset(listEntryPtr, 0, sizeof(struct tapeEntryList));
879
880 /* Fill in tape entry so we can save it later */
881 strcpy(tapeEntryPtr(&listEntryPtr->tapeEnt)->name, TNAME(&oldTapeLabel)( strcmp((&oldTapeLabel)->pName,"") ? (&oldTapeLabel
)->pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (
&oldTapeLabel)->AFSName : "<NULL>" ) )
);
882 tapeEntryPtr(&listEntryPtr->tapeEnt)->dump = oldTapeLabel.dumpid;
883 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_BEINGWRITTEN(1<<2);
884 tapeEntryPtr(&listEntryPtr->tapeEnt)->written = oldTapeLabel.creationTime;
885 tapeEntryPtr(&listEntryPtr->tapeEnt)->expires = oldTapeLabel.expirationDate;
886 tapeEntryPtr(&listEntryPtr->tapeEnt)->seq = extractTapeSeq(oldTapeLabel.AFSName);
887 tapeEntryPtr(&listEntryPtr->tapeEnt)->useCount = oldTapeLabel.useCount;
888 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes = 0;
889 tapeEntryPtr(&listEntryPtr->tapeEnt)->labelpos = 0;
890
891 /* Thread onto end of single-linked list */
892 if (listEntryHead) {
893 endList = listEntryHead;
894 while (endList->next)
895 endList = endList->next;
896 endList->next = listEntryPtr;
897 } else
898 listEntryHead = listEntryPtr;
899
900 error_exit:
901 return (code);
902}
903
904static afs_int32 nbytes = 0; /* # bytes left in buffer */
905static void
906initTapeBuffering(void)
907{
908 nbytes = 0;
909}
910
911
912/* restoreDbEntries
913 * restore all the items on the tape
914 * entry:
915 * tape positioned after tape label
916 */
917
918static int
919restoreDbEntries(struct butm_tapeInfo *tapeInfoPtr,
920 struct rstTapeInfo *rstTapeInfoPtr)
921{
922 struct structDumpHeader netItemHeader, hostItemHeader;
923 afs_int32 more = 1;
924 afs_int32 taskId, code = 0;
925 int count = 0;
926
927 taskId = rstTapeInfoPtr->taskId;
928
929 /* clear state for the buffer routine(s) */
930 initTapeBuffering();
931
932 code = butm_ReadFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileBegin))(tapeInfoPtr);
933 if (code) {
934 ErrorLog(0, taskId, code, tapeInfoPtr->error,
935 "Can't read FileBegin on tape\n");
936 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
937 }
938
939 /* get the first item-header */
940 memset(&netItemHeader, 0, sizeof(netItemHeader));
941 code =
942 getTapeData(tapeInfoPtr, rstTapeInfoPtr, &netItemHeader,
943 sizeof(netItemHeader));
944 if (code)
945 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
946 structDumpHeader_ntoh(&netItemHeader, &hostItemHeader);
947
948 while (more) {
949 switch (hostItemHeader.type) {
950 case SD_DBHEADER1:
951 code =
952 restoreDbHeader(tapeInfoPtr, rstTapeInfoPtr, &hostItemHeader);
953 if (code)
954 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
955 break;
956
957 case SD_DUMP2:
958 if (++count > 25) { /*every 25 dumps, wait */
959 waitDbWatcher();
960 count = 0;
961 }
962 code =
963 restoreDbDump(tapeInfoPtr, rstTapeInfoPtr, &hostItemHeader);
964 if (code)
965 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
966 break;
967
968 case SD_TAPE3:
969 case SD_VOLUME4:
970 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
971 break;
972
973 case SD_TEXT_DUMPSCHEDULE5:
974 case SD_TEXT_VOLUMESET6:
975 case SD_TEXT_TAPEHOSTS7:
976 code = restoreText(tapeInfoPtr, rstTapeInfoPtr, &hostItemHeader);
977 if (code)
978 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
979 break;
980
981 case SD_END8:
982 more = 0;
983 break;
984
985 default:
986 TLog(taskId, "Unknown database header type %d\n",
987 hostItemHeader.type);
988 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
989 break;
990 }
991 }
992
993 code = butm_ReadFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileEnd))(tapeInfoPtr);
994 if (code) {
995 ErrorLog(0, taskId, code, tapeInfoPtr->error,
996 "Can't read EOF on tape\n");
997 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
998 }
999
1000 /* Mark tape as having been written */
1001 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes =
1002 tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
1003 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_WRITTEN(1<<5);
1004
1005 error_exit:
1006 return (code);
1007}
1008
1009/* restoreDbFromTape
1010 * restore the backup database from tape.
1011 */
1012
1013void *
1014restoreDbFromTape(void *param)
1015{
1016 afs_uint32 taskId = (intptr_t) param;
1017 afs_int32 code = 0;
1018 afs_int32 i;
1019 struct butm_tapeInfo tapeInfo;
1020 struct rstTapeInfo rstTapeInfo;
1021 struct budb_dumpEntry dumpEntry;
1022
1023 extern struct tapeConfig globalTapeConfig;
1024 extern struct deviceSyncNode *deviceLatch;
1025
1026 afs_pthread_setname_self("Db restore")(void)0;
1027 setStatus(taskId, DRIVE_WAIT0x100);
1028 EnterDeviceQueue(deviceLatch); /* lock tape device */
1029 clearStatus(taskId, DRIVE_WAIT0x100);
1030
1031 printf("\n\n");
1032 TLog(taskId, "RestoreDb\n");
1033
1034 tapeInfo.structVersion = BUTM_MAJORVERSION2;
1035 code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
1036 if (code) {
1037 ErrorLog(0, taskId, code, tapeInfo.error,
1038 "Can't initialize tape module\n");
1039 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1040 }
1041
1042 listEntryHead = NULL((void *)0);
1043
1044 rstTapeInfo.taskId = taskId;
1045 rstTapeInfo.tapeSeq = 1;
1046 rstTapeInfo.dumpid = 0;
1047
1048 code = readDbTape(&tapeInfo, &rstTapeInfo, autoQuery);
1049 if (code)
1050 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1051
1052 code = restoreDbEntries(&tapeInfo, &rstTapeInfo);
1053 if (code)
1054 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1055
1056 error_exit:
1057 /* Now put this dump into the database */
1058 /* Make a dump entry from first tape */
1059 listEntryPtr = listEntryHead;
1060 if (listEntryPtr) {
1061 makeDbDumpEntry(tapeEntryPtr(&listEntryPtr->tapeEnt), &dumpEntry);
1062 if (dumpEntry.id != 0) {
1063 i = bcdb_CreateDump(&dumpEntry);
1064 if (i) {
1065 if (i == BUDB_DUMPIDEXISTS(156303872L))
1066 fprintf(stderr__stderrp,
1067 "Dump id %d not added to database - already exists\n",
1068 dumpEntry.id);
1069 else
1070 TapeLog(0, taskId, i, 0,
1071 "Dump id %d not added to database\n",
1072 dumpEntry.id);
1073 } else {
1074 i = addTapesToDb(taskId);
1075 if (!code)
1076 code = i;
1077
1078 i = bcdb_FinishDump(&dumpEntry);
1079 if (!code)
1080 code = i;
1081 }
1082 }
1083 freeTapeList();
1084 }
1085
1086 unmountTape(taskId, &tapeInfo);
1087 waitDbWatcher();
1088
1089 if (code == TC_ABORTEDBYREQUEST(156566278L)) {
1090 TLog(taskId, "RestoreDb: Aborted by request\n");
1091 clearStatus(taskId, ABORT_REQUEST0x2);
1092 setStatus(taskId, ABORT_DONE0x8);
1093 } else if (code) {
1094 TapeLog(0, taskId, code, 0, "RestoreDb: Finished with errors\n");
1095 setStatus(taskId, TASK_ERROR0x80);
1096 } else {
1097 TLog(taskId, "RestoreDb: Finished\n");
1098 }
1099
1100 LeaveDeviceQueue(deviceLatch);
1101 setStatus(taskId, TASK_DONE0x20);
1102
1103 return (void *)(intptr_t)(code);
1104}
1105
1106/* KeepAlive
1107 *
1108 * While dumping the database, keeps the connection alive.
1109 * Every 10 seconds, wake up and ask to read 0 bytes of the database.
1110 * This resets the database's internal timer so that it does not
1111 * prematuraly quit (on asking for new tapes and such).
1112 *
1113 * Use the same udbHandle as writeDbDump so we go to the same server.
1114 */
1115void *
1116KeepAlive(void *unused)
1117{
1118 charListT charList;
1119 afs_int32 code;
1120 afs_int32 done;
1121
1122 extern struct udbHandleS udbHandle;
1123
1124 afs_pthread_setname_self("Keep-alive")(void)0;
1125 while (1) {
1126#ifdef AFS_PTHREAD_ENV
1127 sleep(5);
1128#else
1129 IOMGR_Sleep(5);
1130#endif
1131 charList.charListT_val = 0;
1132 charList.charListT_len = 0;
1133 code =
1134 ubik_Call_SingleServer(BUDB_DumpDB, udbHandle.uh_client,
1135 UF_SINGLESERVER1, 0, 0, &charList, &done);
1136 if (code || done)
1137 break;
1138 }
1139 return 0;
1140}
1141
1142
1143/* restoreDbHeader
1144 * restore special items in the header
1145 */
1146
1147int
1148restoreDbHeader(struct butm_tapeInfo *tapeInfo,
1149 struct rstTapeInfo *rstTapeInfoPtr,
1150 struct structDumpHeader *nextHeader)
1151{
1152 struct structDumpHeader netItemHeader;
1153 struct DbHeader netDbHeader, hostDbHeader;
1154 afs_int32 code = 0;
1155
1156 extern struct udbHandleS udbHandle;
1157
1158 /* Read the database header */
1159 memset(&netDbHeader, 0, sizeof(netDbHeader));
1160 code =
1161 getTapeData(tapeInfo, rstTapeInfoPtr, &netDbHeader,
1162 sizeof(netDbHeader));
1163 if (code)
1
Taking false branch
1164 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1165 DbHeader_ntoh(&netDbHeader, &hostDbHeader);
1166
1167 /* Add the database header to the database */
1168 code =
1169 ubik_BUDB_RestoreDbHeader(udbHandle.uh_client, 0,
1170 &hostDbHeader);
1171 if (code) {
2
Taking true branch
1172 ErrorLog(0, rstTapeInfoPtr->taskId, code, 0,
1173 "Can't restore DB Header\n");
1174 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
3
Within the expansion of the macro 'ERROR_EXIT':
a
Assigned value is always the same as the existing value
1175 }
1176
1177 /* get the next item-header */
1178 memset(nextHeader, 0, sizeof(*nextHeader));
1179 code =
1180 getTapeData(tapeInfo, rstTapeInfoPtr, &netItemHeader,
1181 sizeof(netItemHeader));
1182 if (code)
1183 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1184 structDumpHeader_ntoh(&netItemHeader, nextHeader);
1185
1186 error_exit:
1187 return (code);
1188}
1189
1190
1191/* restoreDbDump
1192 * restore a single dump, including all its tapes and volumes, from
1193 * the tape.
1194 * entry:
1195 * nextHeader - ptr to structure for return value
1196 * exit:
1197 * nextHeader - next structure header from tape
1198 * notes:
1199 * upon entry, the dump structure header has been read confirming that
1200 * a database dump tree exists on the tape
1201 */
1202
1203int
1204restoreDbDump(struct butm_tapeInfo *tapeInfo,
1205 struct rstTapeInfo *rstTapeInfoPtr,
1206 struct structDumpHeader *nextHeader)
1207{
1208 struct budb_dumpEntry netDumpEntry, hostDumpEntry;
1209 struct budb_tapeEntry netTapeEntry, hostTapeEntry;
1210 struct budb_volumeEntry netVolumeEntry, hostVolumeEntry;
1211 struct structDumpHeader netItemHeader;
1212 int restoreThisDump = 1;
1213 afs_int32 code = 0;
1214
1215 extern struct udbHandleS udbHandle;
1216
1217 /* read dump entry */
1218 memset(&netDumpEntry, 0, sizeof(netDumpEntry));
1219 code =
1220 getTapeData(tapeInfo, rstTapeInfoPtr, &netDumpEntry,
1221 sizeof(netDumpEntry));
1222 if (code)
1223 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1224
1225 /* If database tape does not have a dumpid (AFS 3.3) then no initial/appended dumps */
1226 if (rstTapeInfoPtr->dumpid == 0) {
1227 netDumpEntry.initialDumpID = 0;
1228 netDumpEntry.appendedDumpID = 0;
1229 }
1230
1231 dumpEntry_ntoh(&netDumpEntry, &hostDumpEntry);
1232
1233 /* The dump entry for this database tape is incomplete, so don't include it */
1234 if (hostDumpEntry.id == rstTapeInfoPtr->dumpid)
1235 restoreThisDump = 0;
1236
1237 /* add the dump to the database */
1238 if (restoreThisDump) {
1239 code =
1240 threadEntryDir(&hostDumpEntry, sizeof(hostDumpEntry),
1241 DLQ_USEDUMP14);
1242 if (code)
1243 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1244 }
1245
1246 /* get the next item-header */
1247 memset(nextHeader, 0, sizeof(*nextHeader));
1248 code =
1249 getTapeData(tapeInfo, rstTapeInfoPtr, &netItemHeader,
1250 sizeof(netItemHeader));
1251 if (code)
1252 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1253 structDumpHeader_ntoh(&netItemHeader, nextHeader);
1254
1255 /* Add every tape to the db */
1256 while (nextHeader->type == SD_TAPE3) { /*t */
1257
1258 /* read the tape entry */
1259 memset(&netTapeEntry, 0, sizeof(netTapeEntry));
1260 code =
1261 getTapeData(tapeInfo, rstTapeInfoPtr, &netTapeEntry,
1262 sizeof(netTapeEntry));
1263 if (code)
1264 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1265 tapeEntry_ntoh(&netTapeEntry, &hostTapeEntry);
1266
1267 /* Add the tape to the database */
1268 if (restoreThisDump) {
1269 code =
1270 threadEntryDir(&hostTapeEntry, sizeof(hostTapeEntry),
1271 DLQ_USETAPE12);
1272 if (code)
1273 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1274 }
1275
1276 /* get the next item-header */
1277 memset(nextHeader, 0, sizeof(*nextHeader));
1278 code =
1279 getTapeData(tapeInfo, rstTapeInfoPtr, &netItemHeader,
1280 sizeof(netItemHeader));
1281 if (code)
1282 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1283 structDumpHeader_ntoh(&netItemHeader, nextHeader);
1284
1285 /* Add every volume to the db */
1286 while (nextHeader->type == SD_VOLUME4) { /*v */
1287
1288 /* read the volume entry */
1289 memset(&netVolumeEntry, 0, sizeof(netVolumeEntry));
1290 code =
1291 getTapeData(tapeInfo, rstTapeInfoPtr, &netVolumeEntry,
1292 sizeof(netVolumeEntry));
1293 if (code)
1294 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1295 volumeEntry_ntoh(&netVolumeEntry, &hostVolumeEntry);
1296
1297 if (restoreThisDump) {
1298 code =
1299 threadEntryDir(&hostVolumeEntry, sizeof(hostVolumeEntry),
1300 DLQ_VOLENTRY10);
1301 if (code)
1302 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1303 }
1304
1305 /* get the next item-header */
1306 memset(nextHeader, 0, sizeof(*nextHeader));
1307 code =
1308 getTapeData(tapeInfo, rstTapeInfoPtr, &netItemHeader,
1309 sizeof(netItemHeader));
1310 if (code)
1311 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1312 structDumpHeader_ntoh(&netItemHeader, nextHeader);
1313 } /*v */
1314
1315 /* Finish the tape */
1316 if (restoreThisDump) {
1317 code =
1318 threadEntryDir(&hostTapeEntry, sizeof(hostTapeEntry),
1319 DLQ_FINISHTAPE11);
1320 if (code)
1321 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1322 }
1323 } /*t */
1324
1325 /* Finish the dump */
1326 if (restoreThisDump) {
1327 code =
1328 threadEntryDir(&hostDumpEntry, sizeof(hostDumpEntry),
1329 DLQ_FINISHDUMP13);
1330 if (code)
1331 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1332 }
1333
1334 error_exit:
1335 return (code);
1336}
1337
1338/* saveTextFile
1339 * Save the specified file as configuration text in the ubik database.
1340 * Have to setup the client text structure so that we can call
1341 * the routine to transmit the text to the db.
1342 */
1343
1344afs_int32
1345saveTextFile(afs_int32 taskId, afs_int32 textType, char *fileName)
1346{
1347 udbClientTextP ctPtr = 0;
1348 afs_int32 code = 0;
1349 int tlock = 0;
1350
1351 ctPtr = (udbClientTextP) malloc(sizeof(*ctPtr));
1352 if (!ctPtr)
1353 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1354
1355 memset(ctPtr, 0, sizeof(*ctPtr));
1356 ctPtr->textType = textType;
1357
1358 /* lock the text in the database */
1359 code = bc_LockText(ctPtr);
1360 if (code) {
1361 ErrorLog(0, taskId, code, 0, "Can't lock text file\n");
1362 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1363 }
1364 tlock = 1;
1365
1366 ctPtr->textStream = fopen(fileName, "r");
1367 if (!ctPtr->textStream) {
1368 ErrorLog(0, taskId, errno(* __error()), 0, "Can't open text file\n");
1369 ERROR_EXIT(errno)do { code = (* __error()); goto error_exit; } while (0);
1370 }
1371
1372 /* now send the text to the database */
1373 code = bcdb_SaveTextFile(ctPtr);
1374 if (code) {
1375 ErrorLog(0, taskId, code, 0, "Can't save text file\n");
1376 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1377 }
1378
1379 error_exit:
1380 if (ctPtr) {
1381 if (ctPtr->textStream)
1382 fclose(ctPtr->textStream);
1383 if (tlock)
1384 bc_UnlockText(ctPtr);
1385 free(ctPtr);
1386 }
1387 return (code);
1388}
1389
1390/* restoreText
1391 * read the text off the tape, and store it in the appropriate
1392 * text type in the database.
1393 * entry:
1394 * nextHeader - ptr to struct for return information
1395 * exit:
1396 * nextHeader - struct header for next item on the tape
1397 */
1398
1399int
1400restoreText(struct butm_tapeInfo *tapeInfo,
1401 struct rstTapeInfo *rstTapeInfoPtr,
1402 struct structDumpHeader *nextHeader)
1403{
1404 char filename[64];
1405 afs_int32 nbytes;
1406 char *readBuffer = 0;
1407 afs_int32 readBlockSize;
1408 afs_int32 transferSize;
1409 struct structDumpHeader netItemHeader;
1410 int fid = -1;
1411 afs_int32 code = 0;
1412
1413 udbClientTextP ctPtr = 0;
1414 afs_int32 textType;
1415
1416 ctPtr = (udbClientTextP) malloc(sizeof(*ctPtr));
1417 if (!ctPtr)
1418 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1419
1420 /* determine the type of text block */
1421 switch (nextHeader->type) {
1422 case SD_TEXT_DUMPSCHEDULE5:
1423 textType = TB_DUMPSCHEDULE0;
1424 break;
1425
1426 case SD_TEXT_VOLUMESET6:
1427 textType = TB_VOLUMESET1;
1428 break;
1429
1430 case SD_TEXT_TAPEHOSTS7:
1431 textType = TB_TAPEHOSTS2;
1432 break;
1433
1434 default:
1435 ErrorLog(0, rstTapeInfoPtr->taskId, TC_INTERNALERROR(156566288L), 0,
1436 "Unknown text block\n");
1437 ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0);
1438 break;
1439 }
1440
1441 /* open the text file */
1442 sprintf(filename, "%s/bu_XXXXXX", gettmpdir());
1443 fid = mkstemp(filename);
1444 if (fid < 0) {
1445 ErrorLog(0, rstTapeInfoPtr->taskId, errno(* __error()), 0,
1446 "Can't open temporary text file: %s\n", filename);
1447 ERROR_EXIT(errno)do { code = (* __error()); goto error_exit; } while (0);
1448 }
1449
1450 /* allocate buffer for text */
1451 readBlockSize = BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
1452 readBuffer = (char *)malloc(readBlockSize);
1453 if (!readBuffer)
1454 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1455
1456 /* read the text into the temporary file */
1457 nbytes = nextHeader->size;
1458 while (nbytes > 0) {
1459 transferSize = (readBlockSize < nbytes) ? readBlockSize : nbytes;
1460
1461 /* read it from the tape */
1462 code =
1463 getTapeData(tapeInfo, rstTapeInfoPtr, readBuffer, transferSize);
1464 if (code)
1465 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1466
1467 /* write to the file */
1468 if (write(fid, readBuffer, transferSize) != transferSize) {
1469 ErrorLog(0, rstTapeInfoPtr->taskId, errno(* __error()), 0,
1470 "Can't write temporary text file: %s\n", filename);
1471 ERROR_EXIT(errno)do { code = (* __error()); goto error_exit; } while (0);
1472 }
1473
1474 nbytes -= transferSize;
1475 }
1476
1477 close(fid);
1478 fid = -1;
1479 code = saveTextFile(rstTapeInfoPtr->taskId, textType, filename);
1480 if (code)
1481 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1482 unlink(filename);
1483
1484 /* get the next item-header */
1485 memset(nextHeader, 0, sizeof(*nextHeader));
1486 code =
1487 getTapeData(tapeInfo, rstTapeInfoPtr, &netItemHeader,
1488 sizeof(netItemHeader));
1489 if (code)
1490 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1491 structDumpHeader_ntoh(&netItemHeader, nextHeader);
1492
1493 error_exit:
1494 if (ctPtr)
1495 free(ctPtr);
1496 if (readBuffer)
1497 free(readBuffer);
1498 if (fid != -1) {
1499 close(fid);
1500 unlink(filename);
1501 }
1502 return (code);
1503}
1504
1505
1506/* ----------------------------------
1507 * Tape data buffering - for reading database dumps
1508 * ----------------------------------
1509 */
1510
1511static char *tapeReadBuffer = 0; /* input buffer */
1512static char *tapeReadBufferPtr = 0; /* position in buffer */
1513
1514/* getTapeData
1515 * Read information from tape, and place the requested number of bytes
1516 * in the buffer supplied
1517 * entry:
1518 * tapeInfo
1519 * rstTapeInfoPtr - Info about the dump being restored.
1520 * buffer - buffer for requested data
1521 * requestedBytes - no. of bytes requested
1522 * exit:
1523 * fn retn - 0, ok, n, error
1524 */
1525
1526int
1527getTapeData(struct butm_tapeInfo *tapeInfoPtr,
1528 struct rstTapeInfo *rstTapeInfoPtr,
1529 void *out, afs_int32 requestedBytes)
1530{
1531 char *buffer = (char *) out;
1532 afs_int32 taskId, transferBytes;
1533 afs_int32 code = 0;
1534
1535 taskId = rstTapeInfoPtr->taskId;
1536
1537 if (checkAbortByTaskId(taskId))
1538 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1539
1540 if (!tapeReadBuffer) {
1541 tapeReadBuffer = (char *)malloc(BUTM_BLOCKSIZE16384);
1542 if (!tapeReadBuffer)
1543 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1544 }
1545
1546 while (requestedBytes > 0) {
1547 if (nbytes == 0) {
1548 tapeReadBufferPtr = &tapeReadBuffer[sizeof(struct blockMark)];
1549
1550 /* get more data */
1551 code =
1552 butm_ReadFileData(tapeInfoPtr, tapeReadBufferPtr,(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,tapeReadBufferPtr
,(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&nbytes)
1553 BUTM_BLKSIZE, &nbytes)(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,tapeReadBufferPtr
,(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&nbytes)
;
1554 if (code) {
1555 /* detect if we hit the end-of-tape and get next tape */
1556 if (code == BUTM_ENDVOLUME(156568845L)) {
1557 /* Update fields in tape entry for this tape */
1558 tapeEntryPtr(&listEntryPtr->tapeEnt)->flags = BUDB_TAPE_WRITTEN(1<<5);
1559 tapeEntryPtr(&listEntryPtr->tapeEnt)->useKBytes =
1560 tapeInfoPtr->kBytes + (tapeInfoPtr->nBytes ? 1 : 0);
1561
1562 unmountTape(taskId, tapeInfoPtr);
1563
1564 rstTapeInfoPtr->tapeSeq++;
1565 code = readDbTape(tapeInfoPtr, rstTapeInfoPtr, 1);
1566 if (code)
1567 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1568
1569 code = butm_ReadFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileBegin))(tapeInfoPtr);
1570 if (code) {
1571 ErrorLog(0, taskId, code, tapeInfoPtr->error,
1572 "Can't read FileBegin on tape\n");
1573 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1574 }
1575
1576 continue;
1577 }
1578
1579 ErrorLog(0, taskId, code, tapeInfoPtr->error,
1580 "Can't read FileData on tape\n");
1581 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1582 }
1583 }
1584
1585 /* copy out data */
1586 transferBytes = (nbytes < requestedBytes) ? nbytes : requestedBytes;
1587 memcpy(buffer, tapeReadBufferPtr, transferBytes);
1588 tapeReadBufferPtr += transferBytes;
1589 buffer += transferBytes;
1590 nbytes -= transferBytes;
1591 requestedBytes -= transferBytes;
1592 }
1593
1594 error_exit:
1595 return (code);
1596}