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
));