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>
19 #include <afs/tcdata.h>
20 #include <afs/bubasics.h>
21 #include <afs/budb_client.h>
22 #include <afs/afsint.h>
23 #include <afs/vldbint.h>
24 #include <afs/vlserver.h>
25 #include <afs/volser.h>
26 #include <afs/volint.h>
27 #include <afs/cellconfig.h>
28 #include <afs/bucoord_prototypes.h>
30 #include "butc_internal.h"
31 #include "error_macros.h"
33 dlqlinkT savedEntries;
34 dlqlinkT entries_to_flush;
36 int dbWatcherinprogress;
39 threadEntryDir(void *anEntry, afs_int32 size, afs_int32 type)
45 for (tried = 0; tried < 5; tried++) {
46 entryPtr = malloc(sizeof(dlqlinkT));
48 if (entryPtr && entry)
51 /* sleep a minute and try again */
57 if ((tried > 0) && !dbWatcherinprogress)
59 #ifdef AFS_PTHREAD_ENV
65 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
66 entryPtr->dlq_type = type;
67 entryPtr->dlq_structPtr = entry;
69 memcpy(entry, anEntry, size);
70 dlqLinkb(&entries_to_flush, entryPtr);
76 * Creates an entry and puts it onto the savedEntries list.
77 * Will retry up to 5 times if not enough memory. Hopfully, the
78 * Watcher thread will free up some memory for it to continue.
82 threadEntry(void *anEntry, afs_int32 size, afs_int32 type)
88 for (tried = 0; tried < 5; tried++) {
89 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
91 if (entryPtr && entry)
94 /* sleep a minute and try again */
100 if ((tried > 0) && !dbWatcherinprogress)
101 return (TC_NOMEMORY);
102 #ifdef AFS_PTHREAD_ENV
109 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
110 entryPtr->dlq_type = type;
111 entryPtr->dlq_structPtr = entry;
113 memcpy(entry, anEntry, size);
114 dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
118 /* ------------------------------------------------------------------ */
121 useDump(struct budb_dumpEntry *dumpEntryPtr)
126 threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
132 * Creates a dump entry (finished) and puts it onto the savedEntries list.
135 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
140 threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
147 * Creates a tape entry and puts it onto the savedEntries list.
150 useTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 dumpID,
151 char *tapename, afs_int32 tapeSeq, afs_int32 useCount,
152 Date written, Date expiration, afs_int32 tapepos)
156 memset(aTapeEntryPtr, 0, sizeof(struct budb_tapeEntry));
157 strcpy(aTapeEntryPtr->name, tapename);
158 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
159 aTapeEntryPtr->written = written; /* When label was written */
160 aTapeEntryPtr->expires = expiration;
161 aTapeEntryPtr->seq = tapeSeq;
162 aTapeEntryPtr->useCount = useCount;
163 aTapeEntryPtr->dump = dumpID;
164 aTapeEntryPtr->labelpos = tapepos;
167 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
174 * Creates a tape entry (finished) and puts it onto the savedEntries list.
177 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
181 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
182 aTapeEntryPtr->useKBytes = useKBytes;
185 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
192 * Creates a volume entry and puts it onto the savedEntries list.
195 addVolume(struct budb_volumeEntry *aVolEntryPtr, afs_int32 dumpID,
196 char *tapename, char *volname, afs_int32 volid,
197 Date cloneDate, afs_int32 startPos, afs_int32 volBytes,
198 int fragment, afs_int32 flags)
204 aVolEntryPtr = (struct budb_volumeEntry *)
205 malloc(sizeof(struct budb_volumeEntry));
207 ERROR_EXIT(TC_NOMEMORY);
211 memset(aVolEntryPtr, 0, sizeof(struct budb_volumeEntry));
212 strcpy(aVolEntryPtr->name, volname);
213 aVolEntryPtr->flags = flags;
214 aVolEntryPtr->id = volid;
215 aVolEntryPtr->position = startPos;
216 aVolEntryPtr->clone = cloneDate;
217 aVolEntryPtr->nBytes = volBytes;
218 aVolEntryPtr->seq = fragment;
219 aVolEntryPtr->dump = dumpID;
220 strcpy(aVolEntryPtr->tape, tapename);
223 threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
241 * Runs through the list of savedEntries and adds the volumes and
242 * tapes to the database.
243 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
244 * and tapes and volumes should not be added to the DB.
247 flushSavedEntries(afs_int32 status)
250 struct budb_tapeEntry *tapePtr;
251 struct budb_volumeEntry *volPtr;
255 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
256 * EOT. This means the volume is larger than the tape. Instead of going onto the next
257 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
258 * without adding it to the backup database.
260 if (status == DUMP_NORETRYEOT) {
261 entryPtr = dlqUnlinkb(&savedEntries);
262 if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
263 ERROR_EXIT(TC_INTERNALERROR);
265 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
273 * Add dump, tape, and volume entries to the list for the dbWatcher to
274 * flush. Volume entries are not added if the volume failed to dump.
276 while ((entryPtr = dlqUnlinkf(&savedEntries))) {
277 if ((entryPtr->dlq_type == DLQ_VOLENTRY) && (status != DUMP_SUCCESS)) {
278 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
284 dlqLinkb(&entries_to_flush, entryPtr);
289 /* Free anything that remains on dlq */
290 dlqTraverseQueue(&savedEntries, freeEntry, freeEntry);
299 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
301 printf("Updating database\n");
304 #ifdef AFS_PTHREAD_ENV
312 printf("Updating database - done\n");
317 #define MAXVOLUMESTOADD 100
321 dbWatcher(void *unused)
324 struct budb_dumpEntry *dumpPtr;
325 struct budb_tapeEntry *tapePtr;
326 struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
331 afs_pthread_setname_self("dbWatcher");
332 dlqInit(&entries_to_flush);
333 dlqInit(&savedEntries);
335 dbWatcherinprogress = 0;
339 /* Add tape and volume enties to the backup database */
340 while ((entryPtr = dlqUnlinkf(&entries_to_flush))) {
341 dbWatcherinprogress = 1;
343 if (!entryPtr->dlq_structPtr) {
344 ErrorLog(0, 0, TC_BADQUEUE, 0,
345 "Warning: Invalid database entry - nota added\n");
347 switch (entryPtr->dlq_type) {
350 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
351 /* Now call the database to create the entry */
352 code = bcdb_CreateDump(dumpPtr);
354 if (code == BUDB_DUMPIDEXISTS) {
356 ("Dump %s (DumpID %u) already exists in backup database\n",
357 dumpPtr->name, dumpPtr->id);
359 ErrorLog(0, 0, code, 0,
360 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
361 dumpPtr->name, dumpPtr->id);
364 addedDump = (code ? 0 : 1);
369 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
371 code = bcdb_FinishDump(dumpPtr);
373 ErrorLog(0, 0, code, 0,
374 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
375 dumpPtr->name, dumpPtr->id);
383 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
385 code = bcdb_UseTape(tapePtr, &new);
387 ErrorLog(0, 0, code, 0,
388 "Warning: Can't add tape %s of DumpID %u to backup database\n",
389 tapePtr->name, tapePtr->dump);
396 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
398 code = bcdb_FinishTape(tapePtr);
400 ErrorLog(0, 0, code, 0,
401 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
402 tapePtr->name, tapePtr->dump);
408 /* collect array of volumes to add to the dump */
409 for (c = 0; c < MAXVOLUMESTOADD; c++) {
410 if (c > 0) { /* don't read the 1st - already did */
411 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
416 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
417 /* Place back onto list and add the vol entries we have */
418 dlqLinkf(&entries_to_flush, entryPtr);
419 entryPtr = (dlqlinkP) 0; /* don't want to deallocate below */
424 (struct budb_volumeEntry *)entryPtr->
427 ErrorLog(0, 0, TC_BADQUEUE, 0,
428 "Warning: Invalid database entry - not added\n");
432 memcpy(&volumes[c], volPtr,
433 sizeof(struct budb_volumeEntry));
436 entryPtr = (dlqlinkP) 0;
441 code = bcdb_AddVolumes(&volumes[0], c);
446 ErrorLog(0, 0, code, 0,
447 "Warning: Can't add %d volumes to dumpid %u\n",
453 for (i = 0; i < c; i++) {
454 code = bcdb_AddVolume(&volumes[i]);
456 ErrorLog(0, 0, code, 0,
457 "Warning: Can't add volume %s %u to backup database\n",
458 volumes[i].name, volumes[i].id);
467 "Warning: dbWatcher: Unrecognized entry type %d\n",
473 if (entryPtr->dlq_structPtr)
474 free(entryPtr->dlq_structPtr);
479 dbWatcherinprogress = 0;
480 #ifdef AFS_PTHREAD_ENV
486 AFS_UNREACHED(return(NULL));