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
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
31 #include <afs/tcdata.h>
32 #include <afs/bubasics.h>
33 #include <afs/budb_client.h>
34 #include <afs/vldbint.h>
36 #include <afs/vlserver.h>
37 #include <afs/volser.h>
38 #include <afs/volint.h>
39 #include <afs/cellconfig.h>
41 #include "error_macros.h"
43 dlqlinkT savedEntries;
44 dlqlinkT entries_to_flush;
46 int dbWatcherinprogress;
49 threadEntryDir(char *anEntry, afs_int32 size, afs_int32 type)
55 for (tried = 0; tried < 5; tried++) {
56 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
57 entry = (char *)malloc(size);
58 if (entryPtr && entry)
61 /* sleep a minute and try again */
67 if ((tried > 0) && !dbWatcherinprogress)
69 #ifdef AFS_PTHREAD_ENV
75 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
76 entryPtr->dlq_type = type;
77 entryPtr->dlq_structPtr = entry;
79 memcpy(entry, anEntry, size);
80 dlqLinkb(&entries_to_flush, entryPtr);
86 * Creates an entry and puts it onto the savedEntries list.
87 * Will retry up to 5 times if not enough memory. Hopfully, the
88 * Watcher thread will free up some memory for it to continue.
92 threadEntry(char *anEntry, afs_int32 size, afs_int32 type)
98 for (tried = 0; tried < 5; tried++) {
99 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
100 entry = (char *)malloc(size);
101 if (entryPtr && entry)
104 /* sleep a minute and try again */
110 if ((tried > 0) && !dbWatcherinprogress)
111 return (TC_NOMEMORY);
112 #ifdef AFS_PTHREAD_ENV
119 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
120 entryPtr->dlq_type = type;
121 entryPtr->dlq_structPtr = entry;
123 memcpy(entry, anEntry, size);
124 dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
128 /* ------------------------------------------------------------------ */
131 useDump(struct budb_dumpEntry *dumpEntryPtr)
136 threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
142 * Creates a dump entry (finished) and puts it onto the savedEntries list.
145 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
150 threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
157 * Creates a tape entry and puts it onto the savedEntries list.
160 useTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 dumpID, char *tapename, afs_int32 tapeSeq, afs_int32 useCount, Date written, Date expiration, afs_int32 tapepos)
164 memset(aTapeEntryPtr, 0, sizeof(struct budb_tapeEntry));
165 strcpy(aTapeEntryPtr->name, tapename);
166 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
167 aTapeEntryPtr->written = written; /* When label was written */
168 aTapeEntryPtr->expires = expiration;
169 aTapeEntryPtr->seq = tapeSeq;
170 aTapeEntryPtr->useCount = useCount;
171 aTapeEntryPtr->dump = dumpID;
172 aTapeEntryPtr->labelpos = tapepos;
175 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
182 * Creates a tape entry (finished) and puts it onto the savedEntries list.
185 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
189 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
190 aTapeEntryPtr->useKBytes = useKBytes;
193 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
200 * Creates a volume entry and puts it onto the savedEntries list.
203 addVolume(struct budb_volumeEntry *aVolEntryPtr, afs_int32 dumpID, char *tapename, char *volname, afs_int32 volid, Date cloneDate, afs_int32 startPos, afs_int32 volBytes, int fragment, afs_int32 flags)
209 aVolEntryPtr = (struct budb_volumeEntry *)
210 malloc(sizeof(struct budb_volumeEntry));
212 ERROR_EXIT(TC_NOMEMORY);
216 memset(aVolEntryPtr, 0, sizeof(struct budb_volumeEntry));
217 strcpy(aVolEntryPtr->name, volname);
218 aVolEntryPtr->flags = flags;
219 aVolEntryPtr->id = volid;
220 aVolEntryPtr->position = startPos;
221 aVolEntryPtr->clone = cloneDate;
222 aVolEntryPtr->nBytes = volBytes;
223 aVolEntryPtr->seq = fragment;
224 aVolEntryPtr->dump = dumpID;
225 strcpy(aVolEntryPtr->tape, tapename);
228 threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
239 * Runs through the list of savedEntries and adds the volumes and
240 * tapes to the database.
241 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
242 * and tapes and volumes should not be added to the DB.
245 flushSavedEntries(afs_int32 status)
248 struct budb_tapeEntry *tapePtr;
249 struct budb_volumeEntry *volPtr;
253 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
254 * EOT. This means the volume is larger than the tape. Instead of going onto the next
255 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
256 * without adding it to the backup database.
258 if (status == DUMP_NORETRYEOT) {
259 entryPtr = dlqUnlinkb(&savedEntries);
260 if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
261 ERROR_EXIT(TC_INTERNALERROR);
263 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
271 * Add dump, tape, and volume entries to the list for the dbWatcher to
272 * flush. Volume entries are not added if the volume failed to dump.
274 while (entryPtr = dlqUnlinkf(&savedEntries)) {
275 if ((entryPtr->dlq_type == DLQ_VOLENTRY) && (status != DUMP_SUCCESS)) {
276 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
282 dlqLinkb(&entries_to_flush, entryPtr);
287 /* Free anything that remains on dlq */
288 dlqTraverseQueue(&savedEntries, free, free);
297 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
299 printf("Updating database\n");
302 #ifdef AFS_PTHREAD_ENV
310 printf("Updating database - done\n");
314 #define MAXVOLUMESTOADD 100
321 struct budb_dumpEntry *dumpPtr;
322 struct budb_tapeEntry *tapePtr;
323 struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
328 dlqInit(&entries_to_flush);
329 dlqInit(&savedEntries);
331 dbWatcherinprogress = 0;
335 /* Add tape and volume enties to the backup database */
336 while (entryPtr = dlqUnlinkf(&entries_to_flush)) {
337 dbWatcherinprogress = 1;
339 if (!entryPtr->dlq_structPtr) {
340 ErrorLog(0, 0, TC_BADQUEUE, 0,
341 "Warning: Invalid database entry - nota added\n");
343 switch (entryPtr->dlq_type) {
346 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
347 /* Now call the database to create the entry */
348 code = bcdb_CreateDump(dumpPtr);
350 if (code == BUDB_DUMPIDEXISTS) {
352 ("Dump %s (DumpID %u) already exists in backup database\n",
353 dumpPtr->name, dumpPtr->id);
355 ErrorLog(0, 0, code, 0,
356 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
357 dumpPtr->name, dumpPtr->id);
360 addedDump = (code ? 0 : 1);
365 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
367 code = bcdb_FinishDump(dumpPtr);
369 ErrorLog(0, 0, code, 0,
370 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
371 dumpPtr->name, dumpPtr->id);
379 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
381 code = bcdb_UseTape(tapePtr, &new);
383 ErrorLog(0, 0, code, 0,
384 "Warning: Can't add tape %s of DumpID %u to backup database\n",
385 tapePtr->name, tapePtr->dump);
392 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
394 code = bcdb_FinishTape(tapePtr, &new);
396 ErrorLog(0, 0, code, 0,
397 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
398 tapePtr->name, tapePtr->dump);
404 /* collect array of volumes to add to the dump */
405 for (c = 0; c < MAXVOLUMESTOADD; c++) {
406 if (c > 0) { /* don't read the 1st - already did */
407 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
412 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
413 /* Place back onto list and add the vol entries we have */
414 dlqLinkf(&entries_to_flush, entryPtr);
415 entryPtr = (dlqlinkP) 0; /* don't want to deallocate below */
420 (struct budb_volumeEntry *)entryPtr->
423 ErrorLog(0, 0, TC_BADQUEUE, 0,
424 "Warning: Invalid database entry - not added\n");
428 memcpy(&volumes[c], volPtr,
429 sizeof(struct budb_volumeEntry));
432 entryPtr = (dlqlinkP) 0;
437 code = bcdb_AddVolumes(&volumes[0], c);
442 ErrorLog(0, 0, code, 0,
443 "Warning: Can't add %d volumes to dumpid %u\n",
449 for (i = 0; i < c; i++) {
450 code = bcdb_AddVolume(&volumes[i]);
452 ErrorLog(0, 0, code, 0,
453 "Warning: Can't add volume %s %u to backup database\n",
454 volumes[i].name, volumes[i].id);
463 "Warning: dbWatcher: Unrecognized entry type %d\n",
469 if (entryPtr->dlq_structPtr)
470 free(entryPtr->dlq_structPtr);
473 entryPtr = (dlqlinkP) 0;
474 dumpPtr = (budb_dumpEntry *) 0;
475 volPtr = (budb_volumeEntry *) 0;
476 tapePtr = (budb_tapeEntry *) 0;
479 dbWatcherinprogress = 0;
480 #ifdef AFS_PTHREAD_ENV