butc: fix int to float conversion warning
[openafs.git] / src / butc / dbentries.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <afs/opr.h>
16 #include <rx/xdr.h>
17 #include <rx/rx.h>
18 #include <lwp.h>
19 #include <lock.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>
30
31 #include "butc_internal.h"
32 #include "error_macros.h"
33
34 dlqlinkT savedEntries;
35 static dlqlinkT entries_to_flush;
36
37 int dbWatcherinprogress;
38
39 afs_int32
40 threadEntryDir(void *anEntry, afs_int32 size, afs_int32 type)
41 {
42     dlqlinkP entryPtr;
43     void *entry = NULL;
44     int tried;
45
46     for (tried = 0; tried < 5; tried++) {
47         entryPtr = malloc(sizeof(dlqlinkT));
48         entry = malloc(size);
49         if (entryPtr && entry)
50             break;
51
52         /* sleep a minute and try again */
53         if (entryPtr)
54             free(entryPtr);
55         if (entry)
56             free(entry);
57
58         if ((tried > 0) && !dbWatcherinprogress)
59             return (TC_NOMEMORY);
60 #ifdef AFS_PTHREAD_ENV
61         sleep(60);
62 #else
63         IOMGR_Sleep(60);
64 #endif
65     }
66     entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
67     entryPtr->dlq_type = type;
68     entryPtr->dlq_structPtr = entry;
69
70     memcpy(entry, anEntry, size);
71     dlqLinkb(&entries_to_flush, entryPtr);
72     return (0);
73 }
74
75 /*
76  * threadEntry.
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.
80  */
81
82 afs_int32
83 threadEntry(void *anEntry, afs_int32 size, afs_int32 type)
84 {
85     dlqlinkP entryPtr;
86     void *entry = NULL;
87     int tried;
88
89     for (tried = 0; tried < 5; tried++) {
90         entryPtr = (dlqlinkP) malloc(sizeof(dlqlinkT));
91         entry = malloc(size);
92         if (entryPtr && entry)
93             break;
94
95         /* sleep a minute and try again */
96         if (entryPtr)
97             free(entryPtr);
98         if (entry)
99             free(entry);
100
101         if ((tried > 0) && !dbWatcherinprogress)
102             return (TC_NOMEMORY);
103 #ifdef AFS_PTHREAD_ENV
104         sleep(60);
105 #else
106         IOMGR_Sleep(60);
107 #endif
108     }
109
110     entryPtr->dlq_prev = entryPtr->dlq_next = (dlqlinkP) NULL;
111     entryPtr->dlq_type = type;
112     entryPtr->dlq_structPtr = entry;
113
114     memcpy(entry, anEntry, size);
115     dlqLinkb(&savedEntries, (dlqlinkP) entryPtr);
116     return (0);
117 }
118
119 /* ------------------------------------------------------------------ */
120
121 afs_int32
122 useDump(struct budb_dumpEntry *dumpEntryPtr)
123 {
124     afs_int32 code = 0;
125
126     code =
127         threadEntry(dumpEntryPtr, sizeof(struct budb_dumpEntry), DLQ_USEDUMP);
128     return (code);
129 }
130
131 /*
132  * finishDump
133  *     Creates a dump entry (finished) and puts it onto the savedEntries list.
134  */
135 afs_int32
136 finishDump(struct budb_dumpEntry *aDumpEntryPtr)
137 {
138     afs_int32 code = 0;
139
140     code =
141         threadEntry(aDumpEntryPtr, sizeof(struct budb_dumpEntry),
142                     DLQ_FINISHDUMP);
143     return (code);
144 }
145
146 /*
147  * useTape
148  *     Creates a tape entry and puts it onto the savedEntries list.
149  */
150 afs_int32
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)
154 {
155     afs_int32 code = 0;
156
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;
166
167     code =
168         threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
169                     DLQ_USETAPE);
170     return (code);
171 }
172
173 /*
174  * finishTape
175  *     Creates a tape entry (finished) and puts it onto the savedEntries list.
176  */
177 afs_int32
178 finishTape(struct budb_tapeEntry *aTapeEntryPtr, afs_int32 useKBytes)
179 {
180     afs_int32 code = 0;
181
182     aTapeEntryPtr->flags = BUDB_TAPE_WRITTEN;
183     aTapeEntryPtr->useKBytes = useKBytes;
184
185     code =
186         threadEntry(aTapeEntryPtr, sizeof(struct budb_tapeEntry),
187                     DLQ_FINISHTAPE);
188     return (code);
189 }
190
191 /*
192  * addVolume
193  *     Creates a volume entry and puts it onto the savedEntries list.
194  */
195 afs_int32
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)
200 {
201     afs_int32 code = 0;
202     int allo = 0;
203
204     if (!aVolEntryPtr) {
205         aVolEntryPtr = (struct budb_volumeEntry *)
206             malloc(sizeof(struct budb_volumeEntry));
207         if (!aVolEntryPtr)
208             ERROR_EXIT(TC_NOMEMORY);
209         allo = 1;
210     }
211
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);
222
223     code =
224         threadEntry(aVolEntryPtr, sizeof(struct budb_volumeEntry),
225                     DLQ_VOLENTRY);
226
227   error_exit:
228     if (code && allo)
229         free(aVolEntryPtr);
230     return (code);
231 }
232
233 static_inline int
234 freeEntry(void *e)
235 {
236     free(e);
237     return 0;
238 }
239
240 /*
241  * flushSavedEntries
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.
246  */
247 afs_int32
248 flushSavedEntries(afs_int32 status)
249 {
250     dlqlinkP entryPtr;
251     struct budb_tapeEntry *tapePtr;
252     struct budb_volumeEntry *volPtr;
253     afs_int32 code = 0;
254
255     /*
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.
260      */
261     if (status == DUMP_NORETRYEOT) {
262         entryPtr = dlqUnlinkb(&savedEntries);
263         if (!entryPtr || (entryPtr->dlq_type != DLQ_USETAPE))
264             ERROR_EXIT(TC_INTERNALERROR);
265
266         tapePtr = (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
267         if (tapePtr)
268             free(tapePtr);
269         if (entryPtr)
270             free(entryPtr);
271     }
272
273     /*
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.
276      */
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)
281                 free(volPtr);
282             if (entryPtr)
283                 free(entryPtr);
284         } else {
285             dlqLinkb(&entries_to_flush, entryPtr);
286         }
287     }
288
289   error_exit:
290     /* Free anything that remains on dlq */
291     dlqTraverseQueue(&savedEntries, freeEntry, freeEntry);
292     return (code);
293 }
294
295 void
296 waitDbWatcher(void)
297 {
298     int message = 0;
299
300     while (dbWatcherinprogress || !dlqEmpty(&entries_to_flush)) {
301         if (!message) {
302             printf("Updating database\n");
303             message++;
304         }
305 #ifdef AFS_PTHREAD_ENV
306         sleep(2);
307 #else
308         IOMGR_Sleep(2);
309 #endif
310     }
311
312     if (message) {
313         printf("Updating database - done\n");
314     }
315     return;
316 }
317
318 #define MAXVOLUMESTOADD 100
319 int addvolumes = 1;
320
321 void *
322 dbWatcher(void *unused)
323 {
324     dlqlinkP entryPtr;
325     struct budb_dumpEntry *dumpPtr;
326     struct budb_tapeEntry *tapePtr;
327     struct budb_volumeEntry *volPtr, volumes[MAXVOLUMESTOADD];
328     afs_int32 new;
329     afs_int32 code = 0;
330     int i, c, addedDump;
331
332     opr_threadname_set("dbWatcher");
333     dlqInit(&entries_to_flush);
334     dlqInit(&savedEntries);
335
336     dbWatcherinprogress = 0;
337     addedDump = 1;
338     while (1) {
339         /*while */
340         /* Add tape and volume enties to the backup database */
341         while ((entryPtr = dlqUnlinkf(&entries_to_flush))) {
342             dbWatcherinprogress = 1;
343
344             if (!entryPtr->dlq_structPtr) {
345                 ErrorLog(0, 0, TC_BADQUEUE, 0,
346                          "Warning: Invalid database entry - nota added\n");
347             } else
348                 switch (entryPtr->dlq_type) {
349                 case DLQ_USEDUMP:
350                     dumpPtr =
351                         (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
352                     /* Now call the database to create the entry */
353                     code = bcdb_CreateDump(dumpPtr);
354                     if (code) {
355                         if (code == BUDB_DUMPIDEXISTS) {
356                             printf
357                                 ("Dump %s (DumpID %u) already exists in backup database\n",
358                                  dumpPtr->name, dumpPtr->id);
359                         } else {
360                             ErrorLog(0, 0, code, 0,
361                                      "Warning: Can't create dump %s (DumpID %u) in backup database\n",
362                                      dumpPtr->name, dumpPtr->id);
363                         }
364                     }
365                     addedDump = (code ? 0 : 1);
366                     break;
367
368                 case DLQ_FINISHDUMP:
369                     dumpPtr =
370                         (struct budb_dumpEntry *)entryPtr->dlq_structPtr;
371                     if (addedDump) {
372                         code = bcdb_FinishDump(dumpPtr);
373                         if (code) {
374                             ErrorLog(0, 0, code, 0,
375                                      "Warning: Can't finish dump %s (DumpID %u) in backup database\n",
376                                      dumpPtr->name, dumpPtr->id);
377                         }
378                     }
379                     addedDump = 1;
380                     break;
381
382                 case DLQ_USETAPE:
383                     tapePtr =
384                         (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
385                     if (addedDump) {
386                         code = bcdb_UseTape(tapePtr, &new);
387                         if (code) {
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);
391                         }
392                     }
393                     break;
394
395                 case DLQ_FINISHTAPE:
396                     tapePtr =
397                         (struct budb_tapeEntry *)entryPtr->dlq_structPtr;
398                     if (addedDump) {
399                         code = bcdb_FinishTape(tapePtr);
400                         if (code) {
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);
404                         }
405                     }
406                     break;
407
408                 case DLQ_VOLENTRY:
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 */
413                             if (!entryPtr)
414                                 break;
415                         }
416
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 */
421                             break;
422                         }
423
424                         volPtr =
425                             (struct budb_volumeEntry *)entryPtr->
426                             dlq_structPtr;
427                         if (!volPtr) {
428                             ErrorLog(0, 0, TC_BADQUEUE, 0,
429                                      "Warning: Invalid database entry - not added\n");
430                             break;
431                         }
432
433                         memcpy(&volumes[c], volPtr,
434                                sizeof(struct budb_volumeEntry));
435                         free(volPtr);
436                         free(entryPtr);
437                         entryPtr = (dlqlinkP) 0;
438                     }
439
440                     if (addedDump) {
441                         if (addvolumes) {
442                             code = bcdb_AddVolumes(&volumes[0], c);
443                             if (code) {
444                                 if (code < 0)
445                                     addvolumes = 0;
446                                 else {
447                                     ErrorLog(0, 0, code, 0,
448                                              "Warning: Can't add %d volumes to dumpid %u\n",
449                                              c, volumes[0].dump);
450                                 }
451                             }
452                         }
453                         if (!addvolumes) {
454                             for (i = 0; i < c; i++) {
455                                 code = bcdb_AddVolume(&volumes[i]);
456                                 if (code) {
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);
460                                 }
461                             }
462                         }
463                     }
464                     break;
465
466                 default:
467                     ErrorLog(0, 0, 0, 0,
468                              "Warning: dbWatcher: Unrecognized entry type %d\n",
469                              entryPtr->dlq_type);
470                     break;      /* ignore */
471                 }
472
473             if (entryPtr) {
474                 if (entryPtr->dlq_structPtr)
475                     free(entryPtr->dlq_structPtr);
476                 free(entryPtr);
477             }
478         }                       /*while */
479
480         dbWatcherinprogress = 0;
481 #ifdef AFS_PTHREAD_ENV
482         sleep(2);
483 #else
484         IOMGR_Sleep(2);
485 #endif
486     }
487     AFS_UNREACHED(return(NULL));
488 }