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>
20 #include <afs/tcdata.h>
21 #include <afs/bubasics.h>
22 #include <afs/budb_client.h>
23 #include <afs/afsint.h>
24 #include <afs/vldbint.h>
25 #include <afs/vlserver.h>
26 #include <afs/volser.h>
27 #include <afs/volint.h>
28 #include <afs/cellconfig.h>
29 #include <afs/bucoord_prototypes.h>
31 #include "butc_internal.h"
32 #include "error_macros.h"
34 dlqlinkT savedEntries;
35 dlqlinkT entries_to_flush;
37 int dbWatcherinprogress;
40 threadEntryDir(void *anEntry, afs_int32 size, afs_int32 type)
46 for (tried = 0; tried < 5; tried++) {
47 entryPtr = malloc(sizeof(dlqlinkT));
49 if (entryPtr && entry)
52 /* sleep a minute and try again */
58 if ((tried > 0) && !dbWatcherinprogress)
60 #ifdef AFS_PTHREAD_ENV
66 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
67 entryPtr->dlq_type = type;
68 entryPtr->dlq_structPtr = entry;
70 memcpy(entry, anEntry, size);
71 dlqLinkb(&entries_to_flush, entryPtr);
77 * Creates an entry and puts it onto the savedEntries list.
78 * Will retry up to 5 times if not enough memory. Hopfully, the
79 * Watcher thread will free up some memory for it to continue.
83 threadEntry(void *anEntry, afs_int32 size, afs_int32 type)
89 for (tried = 0; tried < 5; tried++) {
90 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
92 if (entryPtr && entry)
95 /* sleep a minute and try again */
101 if ((tried > 0) && !dbWatcherinprogress)
102 return (TC_NOMEMORY);
103 #ifdef AFS_PTHREAD_ENV
110 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
111 entryPtr->dlq_type = type;
112 entryPtr->dlq_structPtr = entry;
114 memcpy(entry, anEntry, size);
115 dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
119 /* ------------------------------------------------------------------ */
122 useDump(struct budb_dumpEntry *dumpEntryPtr)
127 threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
133 * Creates a dump entry (finished) and puts it onto the savedEntries list.
136 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
141 threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
148 * Creates a tape entry and puts it onto the savedEntries list.
151 useTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 dumpID,
152 char *tapename, afs_int32 tapeSeq, afs_int32 useCount,
153 Date written, Date expiration, afs_int32 tapepos)
157 memset(aTapeEntryPtr, 0, sizeof(struct budb_tapeEntry));
158 strcpy(aTapeEntryPtr->name, tapename);
159 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
160 aTapeEntryPtr->written = written; /* When label was written */
161 aTapeEntryPtr->expires = expiration;
162 aTapeEntryPtr->seq = tapeSeq;
163 aTapeEntryPtr->useCount = useCount;
164 aTapeEntryPtr->dump = dumpID;
165 aTapeEntryPtr->labelpos = tapepos;
168 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
175 * Creates a tape entry (finished) and puts it onto the savedEntries list.
178 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
182 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
183 aTapeEntryPtr->useKBytes = useKBytes;
186 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
193 * Creates a volume entry and puts it onto the savedEntries list.
196 addVolume(struct budb_volumeEntry *aVolEntryPtr, afs_int32 dumpID,
197 char *tapename, char *volname, afs_int32 volid,
198 Date cloneDate, afs_int32 startPos, afs_int32 volBytes,
199 int fragment, afs_int32 flags)
205 aVolEntryPtr = (struct budb_volumeEntry *)
206 malloc(sizeof(struct budb_volumeEntry));
208 ERROR_EXIT(TC_NOMEMORY);
212 memset(aVolEntryPtr, 0, sizeof(struct budb_volumeEntry));
213 strcpy(aVolEntryPtr->name, volname);
214 aVolEntryPtr->flags = flags;
215 aVolEntryPtr->id = volid;
216 aVolEntryPtr->position = startPos;
217 aVolEntryPtr->clone = cloneDate;
218 aVolEntryPtr->nBytes = volBytes;
219 aVolEntryPtr->seq = fragment;
220 aVolEntryPtr->dump = dumpID;
221 strcpy(aVolEntryPtr->tape, tapename);
224 threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
242 * Runs through the list of savedEntries and adds the volumes and
243 * tapes to the database.
244 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
245 * and tapes and volumes should not be added to the DB.
248 flushSavedEntries(afs_int32 status)
251 struct budb_tapeEntry *tapePtr;
252 struct budb_volumeEntry *volPtr;
256 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
257 * EOT. This means the volume is larger than the tape. Instead of going onto the next
258 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
259 * without adding it to the backup database.
261 if (status == DUMP_NORETRYEOT) {
262 entryPtr = dlqUnlinkb(&savedEntries);
263 if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
264 ERROR_EXIT(TC_INTERNALERROR);
266 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
274 * Add dump, tape, and volume entries to the list for the dbWatcher to
275 * flush. Volume entries are not added if the volume failed to dump.
277 while ((entryPtr = dlqUnlinkf(&savedEntries))) {
278 if ((entryPtr->dlq_type == DLQ_VOLENTRY) && (status != DUMP_SUCCESS)) {
279 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
285 dlqLinkb(&entries_to_flush, entryPtr);
290 /* Free anything that remains on dlq */
291 dlqTraverseQueue(&savedEntries, freeEntry, freeEntry);
300 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
302 printf("Updating database\n");
305 #ifdef AFS_PTHREAD_ENV
313 printf("Updating database - done\n");
318 #define MAXVOLUMESTOADD 100
322 dbWatcher(void *unused)
325 struct budb_dumpEntry *dumpPtr;
326 struct budb_tapeEntry *tapePtr;
327 struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
332 opr_threadname_set("dbWatcher");
333 dlqInit(&entries_to_flush);
334 dlqInit(&savedEntries);
336 dbWatcherinprogress = 0;
340 /* Add tape and volume enties to the backup database */
341 while ((entryPtr = dlqUnlinkf(&entries_to_flush))) {
342 dbWatcherinprogress = 1;
344 if (!entryPtr->dlq_structPtr) {
345 ErrorLog(0, 0, TC_BADQUEUE, 0,
346 "Warning: Invalid database entry - nota added\n");
348 switch (entryPtr->dlq_type) {
351 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
352 /* Now call the database to create the entry */
353 code = bcdb_CreateDump(dumpPtr);
355 if (code == BUDB_DUMPIDEXISTS) {
357 ("Dump %s (DumpID %u) already exists in backup database\n",
358 dumpPtr->name, dumpPtr->id);
360 ErrorLog(0, 0, code, 0,
361 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
362 dumpPtr->name, dumpPtr->id);
365 addedDump = (code ? 0 : 1);
370 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
372 code = bcdb_FinishDump(dumpPtr);
374 ErrorLog(0, 0, code, 0,
375 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
376 dumpPtr->name, dumpPtr->id);
384 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
386 code = bcdb_UseTape(tapePtr, &new);
388 ErrorLog(0, 0, code, 0,
389 "Warning: Can't add tape %s of DumpID %u to backup database\n",
390 tapePtr->name, tapePtr->dump);
397 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
399 code = bcdb_FinishTape(tapePtr);
401 ErrorLog(0, 0, code, 0,
402 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
403 tapePtr->name, tapePtr->dump);
409 /* collect array of volumes to add to the dump */
410 for (c = 0; c < MAXVOLUMESTOADD; c++) {
411 if (c > 0) { /* don't read the 1st - already did */
412 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
417 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
418 /* Place back onto list and add the vol entries we have */
419 dlqLinkf(&entries_to_flush, entryPtr);
420 entryPtr = (dlqlinkP) 0; /* don't want to deallocate below */
425 (struct budb_volumeEntry *)entryPtr->
428 ErrorLog(0, 0, TC_BADQUEUE, 0,
429 "Warning: Invalid database entry - not added\n");
433 memcpy(&volumes[c], volPtr,
434 sizeof(struct budb_volumeEntry));
437 entryPtr = (dlqlinkP) 0;
442 code = bcdb_AddVolumes(&volumes[0], c);
447 ErrorLog(0, 0, code, 0,
448 "Warning: Can't add %d volumes to dumpid %u\n",
454 for (i = 0; i < c; i++) {
455 code = bcdb_AddVolume(&volumes[i]);
457 ErrorLog(0, 0, code, 0,
458 "Warning: Can't add volume %s %u to backup database\n",
459 volumes[i].name, volumes[i].id);
468 "Warning: dbWatcher: Unrecognized entry type %d\n",
474 if (entryPtr->dlq_structPtr)
475 free(entryPtr->dlq_structPtr);
480 dbWatcherinprogress = 0;
481 #ifdef AFS_PTHREAD_ENV
487 AFS_UNREACHED(return(NULL));