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 <afs/param.h>
11 #include <afsconfig.h>
15 #include <sys/types.h>
20 #include <netinet/in.h>
21 #include <sys/socket.h>
30 #include <afs/tcdata.h>
31 #include <afs/bubasics.h>
32 #include <afs/budb_client.h>
33 #include <afs/vldbint.h>
35 #include <afs/vlserver.h>
36 #include <afs/volser.h>
37 #include <afs/volint.h>
38 #include <afs/cellconfig.h>
40 #include "error_macros.h"
42 extern struct ubik_client *cstruct;
43 dlqlinkT savedEntries;
44 dlqlinkT entries_to_flush;
46 int dbWatcherinprogress;
48 afs_int32 threadEntryDir(anEntry, size, type)
53 char *entry = (char *)0;
56 for (tried=0; tried<5; tried++) {
57 entryPtr = (dlqlinkP)malloc(sizeof(dlqlinkT));
58 entry = (char *) malloc(size);
59 if (entryPtr && entry)
62 /* sleep a minute and try again */
63 if (entryPtr) free(entryPtr);
64 if (entry) free(entry);
66 if ((tried > 0) && !dbWatcherinprogress)
68 #ifdef AFS_PTHREAD_ENV
74 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP)NULL;
75 entryPtr->dlq_type = type;
76 entryPtr->dlq_structPtr = entry;
78 bcopy (anEntry, entry, size);
79 dlqLinkb (&entries_to_flush, entryPtr);
85 * Creates an entry and puts it onto the savedEntries list.
86 * Will retry up to 5 times if not enough memory. Hopfully, the
87 * Watcher thread will free up some memory for it to continue.
91 threadEntry(anEntry, size, type)
96 char *entry = (char *)0;
99 for (tried=0; tried<5; tried++) {
100 entryPtr = (dlqlinkP)malloc(sizeof(dlqlinkT));
101 entry = (char *) malloc(size);
102 if (entryPtr && entry)
105 /* sleep a minute and try again */
106 if (entryPtr) free(entryPtr);
107 if (entry) free(entry);
109 if ((tried > 0) && !dbWatcherinprogress)
111 #ifdef AFS_PTHREAD_ENV
118 entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP)NULL;
119 entryPtr->dlq_type = type;
120 entryPtr->dlq_structPtr = entry;
122 bcopy (anEntry, entry, size);
123 dlqLinkb (&savedEntries, (dlqlinkP)entryPtr);
127 /* ------------------------------------------------------------------ */
129 afs_int32 useDump(dumpEntryPtr)
130 struct budb_dumpEntry *dumpEntryPtr;
134 code = threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
140 * Creates a dump entry (finished) and puts it onto the savedEntries list.
142 afs_int32 finishDump (aDumpEntryPtr)
143 struct budb_dumpEntry *aDumpEntryPtr;
147 code = threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_FINISHDUMP);
153 * Creates a tape entry and puts it onto the savedEntries list.
155 afs_int32 useTape (aTapeEntryPtr, dumpID, tapename, tapeSeq, useCount, written, expiration, tapepos)
156 struct budb_tapeEntry *aTapeEntryPtr;
167 bzero(aTapeEntryPtr, sizeof(struct budb_tapeEntry));
168 strcpy(aTapeEntryPtr->name, tapename);
169 aTapeEntryPtr->flags = BUDB_TAPE_BEINGWRITTEN;
170 aTapeEntryPtr->written = written; /* When label was written */
171 aTapeEntryPtr->expires = expiration;
172 aTapeEntryPtr->seq = tapeSeq;
173 aTapeEntryPtr->useCount = useCount;
174 aTapeEntryPtr->dump = dumpID;
175 aTapeEntryPtr->labelpos = tapepos;
177 code = threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry), DLQ_USETAPE);
183 * Creates a tape entry (finished) and puts it onto the savedEntries list.
185 afs_int32 finishTape (aTapeEntryPtr, useKBytes)
186 struct budb_tapeEntry *aTapeEntryPtr;
191 aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
192 aTapeEntryPtr->useKBytes = useKBytes;
194 code = threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry), DLQ_FINISHTAPE);
200 * Creates a volume entry and puts it onto the savedEntries list.
202 afs_int32 addVolume(aVolEntryPtr, dumpID, tapename, volname, volid, cloneDate,
203 startPos, volBytes, fragment, flags)
204 struct budb_volumeEntry *aVolEntryPtr;
219 aVolEntryPtr = (struct budb_volumeEntry *)malloc(sizeof(struct budb_volumeEntry));
220 if (!aVolEntryPtr) ERROR_EXIT(TC_NOMEMORY);
224 bzero(aVolEntryPtr, 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);
235 code = threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry), DLQ_VOLENTRY);
238 if (code && allo) free(aVolEntryPtr);
244 * Runs through the list of savedEntries and adds the volumes and
245 * tapes to the database.
246 * A status of DUMP_NORETRYEOT means the tape(s) contains no useful data,
247 * and tapes and volumes should not be added to the DB.
249 afs_int32 flushSavedEntries (status)
253 struct budb_tapeEntry *tapePtr;
254 struct budb_volumeEntry *volPtr;
258 * On DUMP_NORETRYEOT, the volume being dumped was the first on the tape and hit the
259 * EOT. This means the volume is larger than the tape. Instead of going onto the next
260 * tape, backup reuses the tape. Thus, we must remove this tape entry and free it
261 * without adding it to the backup database.
263 if (status == DUMP_NORETRYEOT) {
264 entryPtr = dlqUnlinkb(&savedEntries);
265 if ( !entryPtr || (entryPtr->dlq_type != DLQ_USETAPE) )
266 ERROR_EXIT(TC_INTERNALERROR);
268 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
269 if (tapePtr) free(tapePtr);
270 if (entryPtr) free(entryPtr);
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;
280 if (volPtr) free(volPtr);
281 if (entryPtr) free(entryPtr);
284 dlqLinkb (&entries_to_flush, entryPtr);
289 /* Free anything that remains on dlq */
290 dlqTraverseQueue (&savedEntries, free, free);
298 while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
300 printf("Updating database\n");
303 #ifdef AFS_PTHREAD_ENV
311 printf("Updating database - done\n");
315 #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 else switch (entryPtr->dlq_type) {
345 dumpPtr = (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
346 /* Now call the database to create the entry */
347 code = bcdb_CreateDump(dumpPtr);
349 if (code == BUDB_DUMPIDEXISTS) {
350 printf("Dump %s (DumpID %u) already exists in backup database\n",
351 dumpPtr->name, dumpPtr->id);
353 ErrorLog(0, 0, code, 0,
354 "Warning: Can't create dump %s (DumpID %u) in backup database\n",
355 dumpPtr->name, dumpPtr->id);
358 addedDump = (code ? 0 : 1);
362 dumpPtr = (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
364 code = bcdb_FinishDump(dumpPtr);
366 ErrorLog(0, 0, code, 0,
367 "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
368 dumpPtr->name, dumpPtr->id);
375 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
377 code = bcdb_UseTape(tapePtr, &new);
379 ErrorLog(0, 0, code, 0,
380 "Warning: Can't add tape %s of DumpID %u to backup database\n",
381 tapePtr->name, tapePtr->dump);
387 tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
389 code = bcdb_FinishTape(tapePtr, &new);
391 ErrorLog(0, 0, code, 0,
392 "Warning: Can't finish tape %s of DumpID %u in backup database\n",
393 tapePtr->name, tapePtr->dump);
399 /* collect array of volumes to add to the dump */
400 for (c=0; c<MAXVOLUMESTOADD; c++) {
401 if (c > 0) { /* don't read the 1st - already did */
402 entryPtr = dlqUnlinkf(&entries_to_flush); /* Get the next entry */
403 if (!entryPtr) break;
406 if (entryPtr->dlq_type != DLQ_VOLENTRY) {
407 /* Place back onto list and add the vol entries we have */
408 dlqLinkf(&entries_to_flush, entryPtr);
409 entryPtr = (dlqlinkP)0; /* don't want to deallocate below */
413 volPtr = (struct budb_volumeEntry *)entryPtr->dlq_structPtr;
415 ErrorLog(0, 0, TC_BADQUEUE, 0,
416 "Warning: Invalid database entry - not added\n");
420 bcopy(volPtr, &volumes[c], sizeof(struct budb_volumeEntry));
423 entryPtr = (dlqlinkP)0;
428 code = bcdb_AddVolumes(&volumes[0], c);
433 ErrorLog(0, 0, code, 0,
434 "Warning: Can't add %d volumes to dumpid %u\n",
440 for (i=0; i<c; i++) {
441 code = bcdb_AddVolume(&volumes[i]);
443 ErrorLog(0, 0, code, 0,
444 "Warning: Can't add volume %s %u to backup database\n",
445 volumes[i].name, volumes[i].id);
454 "Warning: dbWatcher: Unrecognized entry type %d\n",
460 if (entryPtr->dlq_structPtr)
461 free(entryPtr->dlq_structPtr);
464 entryPtr = (dlqlinkP)0;
465 dumpPtr = (budb_dumpEntry *)0;
466 volPtr = (budb_volumeEntry *)0;
467 tapePtr = (budb_tapeEntry *)0;
470 dbWatcherinprogress = 0;
471 #ifdef AFS_PTHREAD_ENV