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>
15 #include <sys/types.h>
20 #include <netinet/in.h>
21 #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>
40 #include <afs/bucoord_prototypes.h>
42 #include "butc_internal.h"
44 #include "error_macros.h"
46 dlqlinkT savedEntries;
47 dlqlinkT entries_to_flush;
49 int dbWatcherinprogress;
52 threadEntryDir(void *anEntry, afs_int32 size, afs_int32 type)
58 for (tried = 0; tried < 5; tried++) {
59 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
60 entry = (char *)malloc(size);
61 if (entryPtr && entry)
64 /* sleep a minute and try again */
70 if ((tried > 0) && !dbWatcherinprogress)
72 #ifdef AFS_PTHREAD_ENV
78 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
79 entryPtr->dlq_type = type;
80 entryPtr->dlq_structPtr = entry;
82 memcpy(entry, anEntry, size);
83 dlqLinkb(&entries_to_flush, entryPtr);
89 * Creates an entry and puts it onto the savedEntries list.
90 * Will retry up to 5 times if not enough memory. Hopfully, the
91 * Watcher thread will free up some memory for it to continue.
95 threadEntry(void *anEntry, afs_int32 size, afs_int32 type)
101 for (tried = 0; tried < 5; tried++) {
102 entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
103 entry = (char *)malloc(size);
104 if (entryPtr && entry)
107 /* sleep a minute and try again */
113 if ((tried > 0) && !dbWatcherinprogress)
114 return (TC_NOMEMORY);
115 #ifdef AFS_PTHREAD_ENV
122 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
123 entryPtr->dlq_type = type;
124 entryPtr->dlq_structPtr = entry;
126 memcpy(entry, anEntry, size);
127 dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
131 /* ------------------------------------------------------------------ */
134 useDump(struct budb_dumpEntry *dumpEntryPtr)
139 threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
145 * Creates a dump entry (finished) and puts it onto the savedEntries list.
148 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
153 threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
160 * Creates a tape entry and puts it onto the savedEntries list.
163 useTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 dumpID,
164 char *tapename, afs_int32 tapeSeq, afs_int32 useCount,
165 Date written, Date expiration, afs_int32 tapepos)
169 memset(aTapeEntryPtr, 0, sizeof(struct budb_tapeEntry));
170 strcpy(aTapeEntryPtr->name, tapename);
171 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
172 aTapeEntryPtr->written = written; /* When label was written */
173 aTapeEntryPtr->expires = expiration;
174 aTapeEntryPtr->seq = tapeSeq;
175 aTapeEntryPtr->useCount = useCount;
176 aTapeEntryPtr->dump = dumpID;
177 aTapeEntryPtr->labelpos = tapepos;
180 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
187 * Creates a tape entry (finished) and puts it onto the savedEntries list.
190 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
194 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
195 aTapeEntryPtr->useKBytes = useKBytes;
198 threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
205 * Creates a volume entry and puts it onto the savedEntries list.
208 addVolume(struct budb_volumeEntry *aVolEntryPtr, afs_int32 dumpID,
209 char *tapename, char *volname, afs_int32 volid,
210 Date cloneDate, afs_int32 startPos, afs_int32 volBytes,
211 int fragment, afs_int32 flags)
217 aVolEntryPtr = (struct budb_volumeEntry *)
218 malloc(sizeof(struct budb_volumeEntry));
220 ERROR_EXIT(TC_NOMEMORY);
224 memset(aVolEntryPtr, 0, sizeof(struct budb_volumeEntry));
225 strcpy(aVolEntryPtr->name, volname);
226 aVolEntryPtr->flags = flags;
227 aVolEntryPtr->id = volid;
228 aVolEntryPtr->position = startPos;
229 aVolEntryPtr->clone = cloneDate;
230 aVolEntryPtr->nBytes = volBytes;
231 aVolEntryPtr->seq = fragment;
232 aVolEntryPtr->dump = dumpID;
233 strcpy(aVolEntryPtr->tape, tapename);
236 threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
254 * Runs through the list of savedEntries and adds the volumes and
255 * tapes to the database.
256 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
257 * and tapes and volumes should not be added to the DB.
260 flushSavedEntries(afs_int32 status)
263 struct budb_tapeEntry *tapePtr;
264 struct budb_volumeEntry *volPtr;
268 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
269 * EOT. This means the volume is larger than the tape. Instead of going onto the next
270 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
271 * without adding it to the backup database.
273 if (status == DUMP_NORETRYEOT) {
274 entryPtr = dlqUnlinkb(&savedEntries);
275 if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
276 ERROR_EXIT(TC_INTERNALERROR);
278 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
286 * Add dump, tape, and volume entries to the list for the dbWatcher to
287 * flush. Volume entries are not added if the volume failed to dump.
289 while ((entryPtr = dlqUnlinkf(&savedEntries))) {
290 if ((entryPtr->dlq_type == DLQ_VOLENTRY) && (status != DUMP_SUCCESS)) {
291 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
297 dlqLinkb(&entries_to_flush, entryPtr);
302 /* Free anything that remains on dlq */
303 dlqTraverseQueue(&savedEntries, freeEntry, freeEntry);
312 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
314 printf("Updating database\n");
317 #ifdef AFS_PTHREAD_ENV
325 printf("Updating database - done\n");
330 #define MAXVOLUMESTOADD 100
334 dbWatcher(void *unused)
337 struct budb_dumpEntry *dumpPtr;
338 struct budb_tapeEntry *tapePtr;
339 struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
344 dlqInit(&entries_to_flush);
345 dlqInit(&savedEntries);
347 dbWatcherinprogress = 0;
351 /* Add tape and volume enties to the backup database */
352 while ((entryPtr = dlqUnlinkf(&entries_to_flush))) {
353 dbWatcherinprogress = 1;
355 if (!entryPtr->dlq_structPtr) {
356 ErrorLog(0, 0, TC_BADQUEUE, 0,
357 "Warning: Invalid database entry - nota added\n");
359 switch (entryPtr->dlq_type) {
362 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
363 /* Now call the database to create the entry */
364 code = bcdb_CreateDump(dumpPtr);
366 if (code == BUDB_DUMPIDEXISTS) {
368 ("Dump %s (DumpID %u) already exists in backup database\n",
369 dumpPtr->name, dumpPtr->id);
371 ErrorLog(0, 0, code, 0,
372 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
373 dumpPtr->name, dumpPtr->id);
376 addedDump = (code ? 0 : 1);
381 (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
383 code = bcdb_FinishDump(dumpPtr);
385 ErrorLog(0, 0, code, 0,
386 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
387 dumpPtr->name, dumpPtr->id);
395 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
397 code = bcdb_UseTape(tapePtr, &new);
399 ErrorLog(0, 0, code, 0,
400 "Warning: Can't add tape %s of DumpID %u to backup database\n",
401 tapePtr->name, tapePtr->dump);
408 (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
410 code = bcdb_FinishTape(tapePtr);
412 ErrorLog(0, 0, code, 0,
413 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
414 tapePtr->name, tapePtr->dump);
420 /* collect array of volumes to add to the dump */
421 for (c = 0; c < MAXVOLUMESTOADD; c++) {
422 if (c > 0) { /* don't read the 1st - already did */
423 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
428 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
429 /* Place back onto list and add the vol entries we have */
430 dlqLinkf(&entries_to_flush, entryPtr);
431 entryPtr = (dlqlinkP) 0; /* don't want to deallocate below */
436 (struct budb_volumeEntry *)entryPtr->
439 ErrorLog(0, 0, TC_BADQUEUE, 0,
440 "Warning: Invalid database entry - not added\n");
444 memcpy(&volumes[c], volPtr,
445 sizeof(struct budb_volumeEntry));
448 entryPtr = (dlqlinkP) 0;
453 code = bcdb_AddVolumes(&volumes[0], c);
458 ErrorLog(0, 0, code, 0,
459 "Warning: Can't add %d volumes to dumpid %u\n",
465 for (i = 0; i < c; i++) {
466 code = bcdb_AddVolume(&volumes[i]);
468 ErrorLog(0, 0, code, 0,
469 "Warning: Can't add volume %s %u to backup database\n",
470 volumes[i].name, volumes[i].id);
479 "Warning: dbWatcher: Unrecognized entry type %d\n",
485 if (entryPtr->dlq_structPtr)
486 free(entryPtr->dlq_structPtr);
489 entryPtr = (dlqlinkP) 0;
490 dumpPtr = (budb_dumpEntry *) 0;
491 volPtr = (budb_volumeEntry *) 0;
492 tapePtr = (budb_tapeEntry *) 0;
495 dbWatcherinprogress = 0;
496 #ifdef AFS_PTHREAD_ENV