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/vldbint.h>
23 #include <afs/vlserver.h>
24 #include <afs/volser.h>
25 #include <afs/volint.h>
26 #include <afs/cellconfig.h>
27 #include <afs/bucoord_prototypes.h>
29 #include "butc_internal.h"
30 #include "error_macros.h"
32 dlqlinkT savedEntries;
33 dlqlinkT entries_to_flush;
35 int dbWatcherinprogress;
38 threadEntryDir(void *anEntry, afs_int32 size, afs_int32 type)
44 for (tried = 0; tried < 5; tried++) {
45 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
46 entry = (char *)malloc(size);
47 if (entryPtr && entry)
50 /* sleep a minute and try again */
56 if ((tried > 0) && !dbWatcherinprogress)
58 #ifdef AFS_PTHREAD_ENV
64 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
65 entryPtr->dlq_type = type;
66 entryPtr->dlq_structPtr = entry;
68 memcpy(entry, anEntry, size);
69 dlqLinkb(&entries_to_flush, entryPtr);
75 * Creates an entry and puts it onto the savedEntries list.
76 * Will retry up to 5 times if not enough memory. Hopfully, the
77 * Watcher thread will free up some memory for it to continue.
81 threadEntry(void *anEntry, afs_int32 size, afs_int32 type)
87 for (tried = 0; tried < 5; tried++) {
88 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
89 entry = (char *)malloc(size);
90 if (entryPtr && entry)
93 /* sleep a minute and try again */
99 if ((tried > 0) && !dbWatcherinprogress)
100 return (TC_NOMEMORY);
101 #ifdef AFS_PTHREAD_ENV
108 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
109 entryPtr->dlq_type = type;
110 entryPtr->dlq_structPtr = entry;
112 memcpy(entry, anEntry, size);
113 dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
117 /* ------------------------------------------------------------------ */
120 useDump(struct budb_dumpEntry *dumpEntryPtr)
125 threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
131 * Creates a dump entry (finished) and puts it onto the savedEntries list.
134 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
139 threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
146 * Creates a tape entry and puts it onto the savedEntries list.
149 useTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 dumpID,
150 char *tapename, afs_int32 tapeSeq, afs_int32 useCount,
151 Date written, Date expiration, afs_int32 tapepos)
155 memset(aTapeEntryPtr, 0, sizeof(struct budb_tapeEntry));
156 strcpy(aTapeEntryPtr->name, tapename);
157 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
158 aTapeEntryPtr->written = written; /* When label was written */
159 aTapeEntryPtr->expires = expiration;
160 aTapeEntryPtr->seq = tapeSeq;
161 aTapeEntryPtr->useCount = useCount;
162 aTapeEntryPtr->dump = dumpID;
163 aTapeEntryPtr->labelpos = tapepos;
166 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
173 * Creates a tape entry (finished) and puts it onto the savedEntries list.
176 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
180 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
181 aTapeEntryPtr->useKBytes = useKBytes;
184 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
191 * Creates a volume entry and puts it onto the savedEntries list.
194 addVolume(struct budb_volumeEntry *aVolEntryPtr, afs_int32 dumpID,
195 char *tapename, char *volname, afs_int32 volid,
196 Date cloneDate, afs_int32 startPos, afs_int32 volBytes,
197 int fragment, afs_int32 flags)
203 aVolEntryPtr = (struct budb_volumeEntry *)
204 malloc(sizeof(struct budb_volumeEntry));
206 ERROR_EXIT(TC_NOMEMORY);
210 memset(aVolEntryPtr, 0, sizeof(struct budb_volumeEntry));
211 strcpy(aVolEntryPtr->name, volname);
212 aVolEntryPtr->flags = flags;
213 aVolEntryPtr->id = volid;
214 aVolEntryPtr->position = startPos;
215 aVolEntryPtr->clone = cloneDate;
216 aVolEntryPtr->nBytes = volBytes;
217 aVolEntryPtr->seq = fragment;
218 aVolEntryPtr->dump = dumpID;
219 strcpy(aVolEntryPtr->tape, tapename);
222 threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
240 * Runs through the list of savedEntries and adds the volumes and
241 * tapes to the database.
242 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
243 * and tapes and volumes should not be added to the DB.
246 flushSavedEntries(afs_int32 status)
249 struct budb_tapeEntry *tapePtr;
250 struct budb_volumeEntry *volPtr;
254 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
255 * EOT. This means the volume is larger than the tape. Instead of going onto the next
256 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
257 * without adding it to the backup database.
259 if (status == DUMP_NORETRYEOT) {
260 entryPtr = dlqUnlinkb(&savedEntries);
261 if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
262 ERROR_EXIT(TC_INTERNALERROR);
264 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
272 * Add dump, tape, and volume entries to the list for the dbWatcher to
273 * flush. Volume entries are not added if the volume failed to dump.
275 while ((entryPtr = dlqUnlinkf(&savedEntries))) {
276 if ((entryPtr->dlq_type == DLQ_VOLENTRY) && (status != DUMP_SUCCESS)) {
277 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
283 dlqLinkb(&entries_to_flush, entryPtr);
288 /* Free anything that remains on dlq */
289 dlqTraverseQueue(&savedEntries, freeEntry, freeEntry);
298 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
300 printf("Updating database\n");
303 #ifdef AFS_PTHREAD_ENV
311 printf("Updating database - done\n");
316 #define MAXVOLUMESTOADD 100
320 dbWatcher(void *unused)
323 struct budb_dumpEntry *dumpPtr;
324 struct budb_tapeEntry *tapePtr;
325 struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
330 afs_pthread_setname_self("dbWatcher");
331 dlqInit(&entries_to_flush);
332 dlqInit(&savedEntries);
334 dbWatcherinprogress = 0;
338 /* Add tape and volume enties to the backup database */
339 while ((entryPtr = dlqUnlinkf(&entries_to_flush))) {
340 dbWatcherinprogress = 1;
342 if (!entryPtr->dlq_structPtr) {
343 ErrorLog(0, 0, TC_BADQUEUE, 0,
344 "Warning: Invalid database entry - nota added\n");
346 switch (entryPtr->dlq_type) {
349 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
350 /* Now call the database to create the entry */
351 code = bcdb_CreateDump(dumpPtr);
353 if (code == BUDB_DUMPIDEXISTS) {
355 ("Dump %s (DumpID %u) already exists in backup database\n",
356 dumpPtr->name, dumpPtr->id);
358 ErrorLog(0, 0, code, 0,
359 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
360 dumpPtr->name, dumpPtr->id);
363 addedDump = (code ? 0 : 1);
368 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
370 code = bcdb_FinishDump(dumpPtr);
372 ErrorLog(0, 0, code, 0,
373 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
374 dumpPtr->name, dumpPtr->id);
382 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
384 code = bcdb_UseTape(tapePtr, &new);
386 ErrorLog(0, 0, code, 0,
387 "Warning: Can't add tape %s of DumpID %u to backup database\n",
388 tapePtr->name, tapePtr->dump);
395 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
397 code = bcdb_FinishTape(tapePtr);
399 ErrorLog(0, 0, code, 0,
400 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
401 tapePtr->name, tapePtr->dump);
407 /* collect array of volumes to add to the dump */
408 for (c = 0; c < MAXVOLUMESTOADD; c++) {
409 if (c > 0) { /* don't read the 1st - already did */
410 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
415 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
416 /* Place back onto list and add the vol entries we have */
417 dlqLinkf(&entries_to_flush, entryPtr);
418 entryPtr = (dlqlinkP) 0; /* don't want to deallocate below */
423 (struct budb_volumeEntry *)entryPtr->
426 ErrorLog(0, 0, TC_BADQUEUE, 0,
427 "Warning: Invalid database entry - not added\n");
431 memcpy(&volumes[c], volPtr,
432 sizeof(struct budb_volumeEntry));
435 entryPtr = (dlqlinkP) 0;
440 code = bcdb_AddVolumes(&volumes[0], c);
445 ErrorLog(0, 0, code, 0,
446 "Warning: Can't add %d volumes to dumpid %u\n",
452 for (i = 0; i < c; i++) {
453 code = bcdb_AddVolume(&volumes[i]);
455 ErrorLog(0, 0, code, 0,
456 "Warning: Can't add volume %s %u to backup database\n",
457 volumes[i].name, volumes[i].id);
466 "Warning: dbWatcher: Unrecognized entry type %d\n",
472 if (entryPtr->dlq_structPtr)
473 free(entryPtr->dlq_structPtr);
476 entryPtr = (dlqlinkP) 0;
477 dumpPtr = (budb_dumpEntry *) 0;
478 volPtr = (budb_volumeEntry *) 0;
479 tapePtr = (budb_tapeEntry *) 0;
482 dbWatcherinprogress = 0;
483 #ifdef AFS_PTHREAD_ENV