Imported Upstream version 3.3.2
[debian/amanda] / server-src / driver.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: driver.c 6512 2007-05-24 17:00:24Z ian $
28  *
29  * controlling process for the Amanda backup system
30  */
31
32 /*
33  * XXX possibly modify tape queue to be cognizant of how much room is left on
34  *     tape.  Probably not effective though, should do this in planner.
35  */
36
37 #include "amanda.h"
38 #include "find.h"
39 #include "clock.h"
40 #include "conffile.h"
41 #include "diskfile.h"
42 #include "event.h"
43 #include "holding.h"
44 #include "infofile.h"
45 #include "logfile.h"
46 #include "fsusage.h"
47 #include "driverio.h"
48 #include "server_util.h"
49 #include "timestamp.h"
50
51 #define driver_debug(i, ...) do {       \
52         if ((i) <= debug_driver) {      \
53             dbprintf(__VA_ARGS__);      \
54         }                               \
55 } while (0)
56
57 #define hold_debug(i, ...) do {         \
58         if ((i) <= debug_holding) {     \
59             dbprintf(__VA_ARGS__);      \
60         }                               \
61 } while (0)
62
63 static disklist_t waitq;        // dle waiting estimate result
64 static disklist_t runq;         // dle waiting to be dumped to holding disk
65 static disklist_t directq;      // dle waiting to be dumped directly to tape
66 static disklist_t tapeq;        // dle on holding disk waiting to be written
67                                 //   to tape
68 static disklist_t roomq;        // dle waiting for more space on holding disk
69 static int pending_aborts;
70 static int degraded_mode;
71 static off_t reserved_space;
72 static off_t total_disksize;
73 static char *dumper_program;
74 static char *chunker_program;
75 static int  inparallel;
76 static int nodump = 0;
77 static off_t tape_length = (off_t)0;
78 static int current_tape = 0;
79 static int conf_max_dle_by_volume;
80 static int conf_taperalgo;
81 static int conf_taper_parallel_write;
82 static int conf_runtapes;
83 static time_t sleep_time;
84 static int idle_reason;
85 static char *driver_timestamp;
86 static char *hd_driver_timestamp;
87 static am_host_t *flushhost = NULL;
88 static int need_degraded=0;
89 static holdalloc_t *holdalloc;
90 static int num_holdalloc;
91 static event_handle_t *dumpers_ev_time = NULL;
92 static event_handle_t *flush_ev_read = NULL;
93 static event_handle_t *schedule_ev_read = NULL;
94 static int   conf_flush_threshold_dumped;
95 static int   conf_flush_threshold_scheduled;
96 static int   conf_taperflush;
97 static off_t flush_threshold_dumped;
98 static off_t flush_threshold_scheduled;
99 static off_t taperflush;
100 static int   schedule_done;                     // 1 if we don't wait for a
101                                                 //   schedule from the planner
102 static int   force_flush;                       // All dump are terminated, we
103                                                 // must now respect taper_flush
104 static int taper_nb_scan_volume = 0;
105 static int nb_sent_new_tape = 0;
106 static int taper_started = 0;
107 static taper_t *last_started_taper;
108
109 static int wait_children(int count);
110 static void wait_for_children(void);
111 static void allocate_bandwidth(netif_t *ip, unsigned long kps);
112 static int assign_holdingdisk(assignedhd_t **holdp, disk_t *diskp);
113 static void adjust_diskspace(disk_t *diskp, cmd_t cmd);
114 static void delete_diskspace(disk_t *diskp);
115 static assignedhd_t **build_diskspace(char *destname);
116 static int client_constrained(disk_t *dp);
117 static void deallocate_bandwidth(netif_t *ip, unsigned long kps);
118 static void dump_schedule(disklist_t *qp, char *str);
119 static assignedhd_t **find_diskspace(off_t size, int *cur_idle,
120                                         assignedhd_t *preferred);
121 static unsigned long free_kps(netif_t *ip);
122 static off_t free_space(void);
123 static void dumper_chunker_result(disk_t *dp);
124 static void dumper_taper_result(disk_t *dp);
125 static void file_taper_result(disk_t *dp);
126 static void handle_dumper_result(void *);
127 static void handle_chunker_result(void *);
128 static void handle_dumpers_time(void *);
129 static void handle_taper_result(void *);
130
131 static void holdingdisk_state(char *time_str);
132 static taper_t *idle_taper(void);
133 static taper_t *taper_from_name(char *name);
134 static void interface_state(char *time_str);
135 static int queue_length(disklist_t q);
136 static void read_flush(void *cookie);
137 static void read_schedule(void *cookie);
138 static void short_dump_state(void);
139 static void startaflush(void);
140 static void start_degraded_mode(disklist_t *queuep);
141 static void start_some_dumps(disklist_t *rq);
142 static void continue_port_dumps(void);
143 static void update_failed_dump(disk_t *);
144 static int no_taper_flushing(void);
145
146 typedef enum {
147     TAPE_ACTION_NO_ACTION         = 0,
148     TAPE_ACTION_SCAN              = (1 << 0),
149     TAPE_ACTION_NEW_TAPE          = (1 << 1),
150     TAPE_ACTION_NO_NEW_TAPE       = (1 << 2),
151     TAPE_ACTION_START_A_FLUSH     = (1 << 3),
152     TAPE_ACTION_START_A_FLUSH_FIT = (1 << 4),
153     TAPE_ACTION_MOVE              = (1 << 5)
154 } TapeAction;
155
156 static TapeAction tape_action(taper_t *taper, char **why_no_new_tape);
157
158 static const char *idle_strings[] = {
159 #define NOT_IDLE                0
160     T_("not-idle"),
161 #define IDLE_NO_DUMPERS         1
162     T_("no-dumpers"),
163 #define IDLE_START_WAIT         2
164     T_("start-wait"),
165 #define IDLE_NO_HOLD            3
166     T_("no-hold"),
167 #define IDLE_CLIENT_CONSTRAINED 4
168     T_("client-constrained"),
169 #define IDLE_NO_BANDWIDTH       5
170     T_("no-bandwidth"),
171 #define IDLE_NO_DISKSPACE       6
172     T_("no-diskspace")
173 };
174
175 int
176 main(
177     int         argc,
178     char **     argv)
179 {
180     disklist_t origq;
181     disk_t *diskp;
182     int dsk;
183     dumper_t *dumper;
184     char *newdir = NULL;
185     struct fs_usage fsusage;
186     holdingdisk_t *hdp;
187     identlist_t    il;
188     unsigned long reserve = 100;
189     char *conf_diskfile;
190     char **result_argv = NULL;
191     char *taper_program;
192     char *conf_tapetype;
193     tapetype_t *tape;
194     char *line;
195     char hostname[1025];
196     intmax_t kb_avail;
197     config_overrides_t *cfg_ovr = NULL;
198     char *cfg_opt = NULL;
199     holdalloc_t *ha, *ha_last;
200     find_result_t *holding_files;
201     disklist_t holding_disklist = { NULL, NULL };
202     int no_taper = FALSE;
203     int from_client = FALSE;
204
205     if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
206         printf("driver-%s\n", VERSION);
207         return (0);
208     }
209
210     /*
211      * Configure program for internationalization:
212      *   1) Only set the message locale for now.
213      *   2) Set textdomain for all amanda related programs to "amanda"
214      *      We don't want to be forced to support dozens of message catalogs.
215      */  
216     setlocale(LC_MESSAGES, "C");
217     textdomain("amanda");
218
219     safe_fd(-1, 0);
220
221     setvbuf(stdout, (char *)NULL, (int)_IOLBF, 0);
222     setvbuf(stderr, (char *)NULL, (int)_IOLBF, 0);
223
224     set_pname("driver");
225
226     dbopen(DBG_SUBDIR_SERVER);
227
228     atexit(wait_for_children);
229
230     /* Don't die when child closes pipe */
231     signal(SIGPIPE, SIG_IGN);
232
233     add_amanda_log_handler(amanda_log_stderr);
234     add_amanda_log_handler(amanda_log_trace_log);
235
236     startclock();
237
238     cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
239
240     if (argc > 1)
241         cfg_opt = argv[1];
242     set_config_overrides(cfg_ovr);
243     config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt);
244
245     conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
246     read_diskfile(conf_diskfile, &origq);
247     disable_skip_disk(&origq);
248     amfree(conf_diskfile);
249
250     if (config_errors(NULL) >= CFGERR_WARNINGS) {
251         config_print_errors();
252         if (config_errors(NULL) >= CFGERR_ERRORS) {
253             g_critical(_("errors processing config file"));
254         }
255     }
256
257     log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid());
258     g_printf(_("%s: pid %ld executable %s version %s\n"),
259            get_pname(), (long) getpid(), argv[0], VERSION);
260
261     if(argc > 2) {
262         if(strcmp(argv[2], "nodump") == 0) {
263             nodump = 1;
264             argv++;
265             argc--;
266         }
267     }
268
269     if (argc > 2) {
270         if (strcmp(argv[2], "--no-taper") == 0) {
271             no_taper = TRUE;
272             argv++;
273             argc--;
274         }
275     }
276
277     if (argc > 2) {
278         if (strcmp(argv[2], "--from-client") == 0) {
279             from_client = TRUE;
280             from_client = from_client;
281             argv++;
282             argc--;
283         }
284     }
285
286     safe_cd(); /* do this *after* config_init */
287
288     check_running_as(RUNNING_AS_DUMPUSER);
289
290     dbrename(get_config_name(), DBG_SUBDIR_SERVER);
291
292     /* load DLEs from the holding disk, in case there's anything to flush there */
293     search_holding_disk(&holding_files, &holding_disklist);
294     /* note that the dumps are added to the global disklist, so we need not consult
295      * holding_files or holding_disklist after this */
296
297     amfree(driver_timestamp);
298     /* read timestamp from stdin */
299     while ((line = agets(stdin)) != NULL) {
300         if (line[0] != '\0')
301             break;
302         amfree(line);
303     }
304     if ( line == NULL ) {
305       error(_("Did not get DATE line from planner"));
306       /*NOTREACHED*/
307     }
308     driver_timestamp = alloc(15);
309     strncpy(driver_timestamp, &line[5], 14);
310     driver_timestamp[14] = '\0';
311     amfree(line);
312     log_add(L_START,_("date %s"), driver_timestamp);
313
314     gethostname(hostname, SIZEOF(hostname));
315     log_add(L_STATS,_("hostname %s"), hostname);
316
317     /* check that we don't do many dump in a day and usetimestamps is off */
318     if(strlen(driver_timestamp) == 8) {
319         if (!nodump) {
320             char *conf_logdir = getconf_str(CNF_LOGDIR);
321             char *logfile    = vstralloc(conf_logdir, "/log.",
322                                          driver_timestamp, ".0", NULL);
323             char *oldlogfile = vstralloc(conf_logdir, "/oldlog/log.",
324                                          driver_timestamp, ".0", NULL);
325             if(access(logfile, F_OK) == 0 || access(oldlogfile, F_OK) == 0) {
326                 log_add(L_WARNING, _("WARNING: This is not the first amdump run today. Enable the usetimestamps option in the configuration file if you want to run amdump more than once per calendar day."));
327             }
328             amfree(oldlogfile);
329             amfree(logfile);
330         }
331         hd_driver_timestamp = get_timestamp_from_time(0);
332     }
333     else {
334         hd_driver_timestamp = stralloc(driver_timestamp);
335     }
336
337     taper_program = vstralloc(amlibexecdir, "/", "taper", NULL);
338     dumper_program = vstralloc(amlibexecdir, "/", "dumper", NULL);
339     chunker_program = vstralloc(amlibexecdir, "/", "chunker", NULL);
340
341     conf_taperalgo = getconf_taperalgo(CNF_TAPERALGO);
342     conf_taper_parallel_write = getconf_int(CNF_TAPER_PARALLEL_WRITE);
343     conf_tapetype = getconf_str(CNF_TAPETYPE);
344     conf_runtapes = getconf_int(CNF_RUNTAPES);
345     conf_max_dle_by_volume = getconf_int(CNF_MAX_DLE_BY_VOLUME);
346     if (conf_taper_parallel_write > conf_runtapes) {
347         conf_taper_parallel_write = conf_runtapes;
348     }
349     tape = lookup_tapetype(conf_tapetype);
350     tape_length = tapetype_get_length(tape);
351     g_printf("driver: tape size %lld\n", (long long)tape_length);
352     conf_flush_threshold_dumped = getconf_int(CNF_FLUSH_THRESHOLD_DUMPED);
353     conf_flush_threshold_scheduled = getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED);
354     conf_taperflush = getconf_int(CNF_TAPERFLUSH);
355     flush_threshold_dumped = (conf_flush_threshold_dumped * tape_length) / 100;
356     flush_threshold_scheduled = (conf_flush_threshold_scheduled * tape_length) / 100;
357     taperflush = (conf_taperflush *tape_length) / 100;
358
359     driver_debug(1, _("flush-threshold-dumped: %lld\n"), (long long)flush_threshold_dumped);
360     driver_debug(1, _("flush-threshold-scheduled: %lld\n"), (long long)flush_threshold_scheduled);
361     driver_debug(1, _("taperflush: %lld\n"), (long long)taperflush);
362
363     /* set up any configuration-dependent variables */
364
365     inparallel  = getconf_int(CNF_INPARALLEL);
366
367     reserve = (unsigned long)getconf_int(CNF_RESERVE);
368
369     total_disksize = (off_t)0;
370     ha_last = NULL;
371     num_holdalloc = 0;
372     for (il = getconf_identlist(CNF_HOLDINGDISK), dsk = 0;
373          il != NULL;
374          il = il->next, dsk++) {
375         hdp = lookup_holdingdisk(il->data);
376         ha = alloc(SIZEOF(holdalloc_t));
377         num_holdalloc++;
378
379         /* link the list in the same order as getconf_holdingdisks's results */
380         ha->next = NULL;
381         if (ha_last == NULL)
382             holdalloc = ha;
383         else
384             ha_last->next = ha;
385         ha_last = ha;
386
387         ha->hdisk = hdp;
388         ha->allocated_dumpers = 0;
389         ha->allocated_space = (off_t)0;
390         ha->disksize = holdingdisk_get_disksize(hdp);
391
392         /* get disk size */
393         if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1
394            || access(holdingdisk_get_diskdir(hdp), W_OK) == -1) {
395             log_add(L_WARNING, _("WARNING: ignoring holding disk %s: %s\n"),
396                     holdingdisk_get_diskdir(hdp), strerror(errno));
397             ha->disksize = 0L;
398             continue;
399         }
400
401         /* do the division first to avoid potential integer overflow */
402         if (fsusage.fsu_bavail_top_bit_set)
403             kb_avail = 0;
404         else
405             kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize;
406
407         if(ha->disksize > (off_t)0) {
408             if(ha->disksize > kb_avail) {
409                 log_add(L_WARNING,
410                         _("WARNING: %s: %lld KB requested, "
411                         "but only %lld KB available."),
412                         holdingdisk_get_diskdir(hdp),
413                         (long long)ha->disksize,
414                         (long long)kb_avail);
415                         ha->disksize = kb_avail;
416             }
417         }
418         /* ha->disksize is negative; use all but that amount */
419         else if(kb_avail < -ha->disksize) {
420             log_add(L_WARNING,
421                     _("WARNING: %s: not %lld KB free."),
422                     holdingdisk_get_diskdir(hdp),
423                     (long long)-ha->disksize);
424             ha->disksize = (off_t)0;
425             continue;
426         }
427         else
428             ha->disksize += kb_avail;
429
430         g_printf(_("driver: adding holding disk %d dir %s size %lld chunksize %lld\n"),
431                dsk, holdingdisk_get_diskdir(hdp),
432                (long long)ha->disksize,
433                (long long)(holdingdisk_get_chunksize(hdp)));
434
435         newdir = newvstralloc(newdir,
436                               holdingdisk_get_diskdir(hdp), "/", hd_driver_timestamp,
437                               NULL);
438         if(!mkholdingdir(newdir)) {
439             ha->disksize = (off_t)0;
440         }
441         total_disksize += ha->disksize;
442     }
443
444     reserved_space = total_disksize * (off_t)(reserve / 100);
445
446     g_printf(_("reserving %lld out of %lld for degraded-mode dumps\n"),
447            (long long)reserved_space, (long long)free_space());
448
449     amfree(newdir);
450
451     if(inparallel > MAX_DUMPERS) inparallel = MAX_DUMPERS;
452
453     /* taper takes a while to get going, so start it up right away */
454
455     init_driverio();
456     startup_tape_process(taper_program, conf_taper_parallel_write, no_taper);
457
458     /* fire up the dumpers now while we are waiting */
459     if(!nodump) startup_dump_processes(dumper_program, inparallel, driver_timestamp);
460
461     /*
462      * Read schedule from stdin.  Usually, this is a pipe from planner,
463      * so the effect is that we wait here for the planner to
464      * finish, but meanwhile the taper is rewinding the tape, reading
465      * the label, checking it, writing a new label and all that jazz
466      * in parallel with the planner.
467      */
468
469     runq.head = NULL;
470     runq.tail = NULL;
471     directq.head = NULL;
472     directq.tail = NULL;
473     waitq = origq;
474     tapeq.head = NULL;
475     tapeq.tail = NULL;
476     roomq.head = NULL;
477     roomq.tail = NULL;
478     taper_nb_wait_reply = 0;
479
480     need_degraded = 0;
481     if (no_taper || conf_runtapes <= 0) {
482         taper_started = 1; /* we'll pretend the taper started and failed immediately */
483         need_degraded = 1;
484     } else {
485         tapetable[0].state = TAPER_STATE_INIT;
486         taper_nb_wait_reply++;
487         taper_nb_scan_volume++;
488         taper_ev_read = event_register(taper_fd, EV_READFD,
489                                        handle_taper_result, NULL);
490         taper_cmd(START_TAPER, NULL, tapetable[0].name, 0, driver_timestamp);
491     }
492
493     flush_ev_read = event_register((event_id_t)0, EV_READFD, read_flush, NULL);
494
495     log_add(L_STATS, _("startup time %s"), walltime_str(curclock()));
496
497     g_printf(_("driver: start time %s inparallel %d bandwidth %lu diskspace %lld "), walltime_str(curclock()), inparallel,
498            free_kps(NULL), (long long)free_space());
499     g_printf(_(" dir %s datestamp %s driver: drain-ends tapeq %s big-dumpers %s\n"),
500            "OBSOLETE", driver_timestamp, taperalgo2str(conf_taperalgo),
501            getconf_str(CNF_DUMPORDER));
502     fflush(stdout);
503
504     schedule_done = nodump;
505     force_flush = 0;
506
507     short_dump_state();
508     event_loop(0);
509
510     force_flush = 1;
511
512     /* mv runq to directq */
513     while (!empty(runq)) {
514         diskp = dequeue_disk(&runq);
515         headqueue_disk(&directq, diskp);
516     }
517
518     run_server_global_scripts(EXECUTE_ON_POST_BACKUP, get_config_name());
519
520     /* log error for any remaining dumps */
521     while(!empty(directq)) {
522         diskp = dequeue_disk(&directq);
523
524         if (diskp->to_holdingdisk == HOLD_REQUIRED) {
525             char *qname = quote_string(diskp->name);
526             log_add(L_FAIL, "%s %s %s %d [%s]",
527                 diskp->host->hostname, qname, sched(diskp)->datestamp,
528                 sched(diskp)->level,
529                 _("can't dump required holdingdisk"));
530             amfree(qname);
531         }
532         else if (!degraded_mode) {
533             char *qname = quote_string(diskp->name);
534             log_add(L_FAIL, "%s %s %s %d [%s]",
535                 diskp->host->hostname, qname, sched(diskp)->datestamp,
536                 sched(diskp)->level,
537                 _("can't dump in non degraded mode"));
538             amfree(qname);
539         }
540         else {
541             char *qname = quote_string(diskp->name);
542             log_add(L_FAIL, "%s %s %s %d [%s]",
543                 diskp->host->hostname, qname, sched(diskp)->datestamp,
544                 sched(diskp)->level,
545                 num_holdalloc == 0 ?
546                     _("can't do degraded dump without holding disk") :
547                 diskp->to_holdingdisk != HOLD_NEVER ?
548                     _("out of holding space in degraded mode") :
549                     _("can't dump 'holdingdisk never' dle in degraded mode"));
550             amfree(qname);
551         }
552     }
553
554     short_dump_state();                         /* for amstatus */
555
556     g_printf(_("driver: QUITTING time %s telling children to quit\n"),
557            walltime_str(curclock()));
558     fflush(stdout);
559
560     if(!nodump) {
561         for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) {
562             if(dumper->fd >= 0)
563                 dumper_cmd(dumper, QUIT, NULL, NULL);
564         }
565     }
566
567     if(taper_fd >= 0) {
568         taper_cmd(QUIT, NULL, NULL, 0, NULL);
569     }
570
571     /* wait for all to die */
572     wait_children(600);
573
574     /* cleanup */
575     holding_cleanup(NULL, NULL);
576
577     amfree(newdir);
578
579     check_unfree_serial();
580     g_printf(_("driver: FINISHED time %s\n"), walltime_str(curclock()));
581     fflush(stdout);
582     log_add(L_FINISH,_("date %s time %s"), driver_timestamp, walltime_str(curclock()));
583     log_add(L_INFO, "pid-done %ld", (long)getpid());
584     amfree(driver_timestamp);
585
586     amfree(dumper_program);
587     amfree(taper_program);
588     if (result_argv)
589         g_strfreev(result_argv);
590
591     dbclose();
592
593     return 0;
594 }
595
596 /* sleep up to count seconds, and wait for terminating child process */
597 /* if sleep is negative, this function will not timeout              */
598 /* exit once all child process are finished or the timout expired    */
599 /* return 0 if no more children to wait                              */
600 /* return 1 if some children are still alive                         */
601 static int
602 wait_children(int count)
603 {
604     pid_t     pid;
605     amwait_t  retstat;
606     char     *who;
607     char     *what;
608     int       code=0;
609     dumper_t *dumper;
610     int       wait_errno;
611
612     do {
613         do {
614             pid = waitpid((pid_t)-1, &retstat, WNOHANG);
615             wait_errno = errno;
616             if (pid > 0) {
617                 what = NULL;
618                 if (! WIFEXITED(retstat)) {
619                     what = _("signal");
620                     code = WTERMSIG(retstat);
621                 } else if (WEXITSTATUS(retstat) != 0) {
622                     what = _("code");
623                     code = WEXITSTATUS(retstat);
624                 }
625                 who = NULL;
626                 for (dumper = dmptable; dumper < dmptable + inparallel;
627                      dumper++) {
628                     if (pid == dumper->pid) {
629                         who = stralloc(dumper->name);
630                         dumper->pid = -1;
631                         break;
632                     }
633                     if (dumper->chunker && pid == dumper->chunker->pid) {
634                         who = stralloc(dumper->chunker->name);
635                         dumper->chunker->pid = -1;
636                         break;
637                     }
638                 }
639                 if (who == NULL && pid == taper_pid) {
640                     who = stralloc("taper");
641                     taper_pid = -1;
642                 }
643                 if(what != NULL && who == NULL) {
644                     who = stralloc("unknown");
645                 }
646                 if(who && what) {
647                     log_add(L_WARNING, _("%s pid %u exited with %s %d\n"), who, 
648                             (unsigned)pid, what, code);
649                     g_printf(_("driver: %s pid %u exited with %s %d\n"), who,
650                            (unsigned)pid, what, code);
651                 }
652                 amfree(who);
653             }
654         } while (pid > 0 || wait_errno == EINTR);
655         if (errno != ECHILD)
656             sleep(1);
657         if (count > 0)
658             count--;
659     } while ((errno != ECHILD) && (count != 0));
660     return (errno != ECHILD);
661 }
662
663 static void
664 kill_children(int signal)
665 {
666     dumper_t *dumper;
667
668     if(!nodump) {
669         for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) {
670             if (!dumper->down && dumper->pid > 1) {
671                 g_printf(_("driver: sending signal %d to %s pid %u\n"), signal,
672                        dumper->name, (unsigned)dumper->pid);
673                 if (kill(dumper->pid, signal) == -1 && errno == ESRCH) {
674                     if (dumper->chunker)
675                         dumper->chunker->pid = 0;
676                 }
677                 if (dumper->chunker && dumper->chunker->pid > 1) {
678                     g_printf(_("driver: sending signal %d to %s pid %u\n"), signal,
679                            dumper->chunker->name,
680                            (unsigned)dumper->chunker->pid);
681                     if (kill(dumper->chunker->pid, signal) == -1 &&
682                         errno == ESRCH)
683                         dumper->chunker->pid = 0;
684                 }
685             }
686         }
687     }
688
689     if(taper_pid > 1) {
690         g_printf(_("driver: sending signal %d to %s pid %u\n"), signal,
691                "taper", (unsigned)taper_pid);
692         if (kill(taper_pid, signal) == -1 && errno == ESRCH)
693             taper_pid = 0;
694     }
695 }
696
697 static void
698 wait_for_children(void)
699 {
700     dumper_t *dumper;
701
702     if(!nodump) {
703         for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) {
704             if (dumper->pid > 1 && dumper->fd >= 0) {
705                 dumper_cmd(dumper, QUIT, NULL, NULL);
706                 if (dumper->chunker && dumper->chunker->pid > 1 &&
707                     dumper->chunker->fd >= 0)
708                     chunker_cmd(dumper->chunker, QUIT, NULL, NULL);
709             }
710         }
711     }
712
713     if(taper_pid > 1 && taper_fd > 0) {
714         taper_cmd(QUIT, NULL, NULL, 0, NULL);
715     }
716
717     if(wait_children(60) == 0)
718         return;
719
720     kill_children(SIGHUP);
721     if(wait_children(60) == 0)
722         return;
723
724     kill_children(SIGKILL);
725     if(wait_children(-1) == 0)
726         return;
727
728 }
729
730 static void startaflush_tape(taper_t *taper, gboolean *state_changed);
731
732 static void
733 startaflush(void)
734 {
735     taper_t *taper;
736     gboolean state_changed = FALSE;
737
738     for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write;
739         taper++) {
740         if (!(taper->state & TAPER_STATE_DONE) &&
741             taper->state & TAPER_STATE_WAIT_FOR_TAPE) {
742             startaflush_tape(taper, &state_changed);
743         }
744     }
745     for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write;
746         taper++) {
747         if (!(taper->state & TAPER_STATE_DONE) &&
748             taper->state & TAPER_STATE_TAPE_REQUESTED) {
749             startaflush_tape(taper, &state_changed);
750         }
751     }
752     for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write;
753         taper++) {
754         if (!(taper->state & TAPER_STATE_DONE) &&
755             taper->state & TAPER_STATE_INIT) {
756             startaflush_tape(taper, &state_changed);
757         }
758     }
759     for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write;
760         taper++) {
761         if (!(taper->state & TAPER_STATE_DONE) &&
762             taper->state & TAPER_STATE_IDLE) {
763             startaflush_tape(taper, &state_changed);
764         }
765     }
766     if (state_changed) {
767         short_dump_state();
768     }
769 }
770
771 static void
772 startaflush_tape(
773     taper_t  *taper,
774     gboolean *state_changed)
775 {
776     disk_t *dp = NULL;
777     disk_t *fit = NULL;
778     char *datestamp;
779     off_t extra_tapes_size = 0;
780     off_t taper_left;
781     char *qname;
782     TapeAction result_tape_action;
783     char *why_no_new_tape = NULL;
784     taper_t *taper1;
785
786     result_tape_action = tape_action(taper, &why_no_new_tape);
787
788     if (result_tape_action & TAPE_ACTION_SCAN) {
789         taper->state &= ~TAPER_STATE_TAPE_REQUESTED;
790         taper->state |= TAPER_STATE_WAIT_FOR_TAPE;
791         taper_nb_scan_volume++;
792         taper_cmd(START_SCAN, taper->disk, NULL, 0, NULL);
793     } else if (result_tape_action & TAPE_ACTION_NEW_TAPE) {
794         taper->state &= ~TAPER_STATE_WAIT_FOR_TAPE;
795         taper->state |= TAPER_STATE_WAIT_NEW_TAPE;
796         nb_sent_new_tape++;
797         taper_cmd(NEW_TAPE, taper->disk, NULL, 0, NULL);
798     } else if (result_tape_action & TAPE_ACTION_NO_NEW_TAPE) {
799         taper->state &= ~TAPER_STATE_WAIT_FOR_TAPE;
800         taper_cmd(NO_NEW_TAPE, taper->disk, why_no_new_tape, 0, NULL);
801         taper->state |= TAPER_STATE_DONE;
802         start_degraded_mode(&runq);
803         *state_changed = TRUE;
804     } else if (result_tape_action & TAPE_ACTION_MOVE) {
805         taper_t *taper1 = idle_taper();
806         if (taper1) {
807             taper->state &= ~TAPER_STATE_TAPE_REQUESTED;
808             taper->state &= ~TAPER_STATE_WAIT_FOR_TAPE;
809             taper_cmd(TAKE_SCRIBE_FROM, taper->disk, taper1->name, 0 , NULL);
810             taper1->state = TAPER_STATE_DEFAULT;
811             taper->state |= TAPER_STATE_TAPE_STARTED;
812             taper->left = taper1->left;
813             taper->nb_dle++;
814             if (last_started_taper == taper1) {
815                 last_started_taper = taper;
816             }
817             *state_changed = TRUE;
818         }
819     }
820
821     if (!degraded_mode &&
822         taper->state & TAPER_STATE_IDLE &&
823         !empty(tapeq) &&
824         (result_tape_action & TAPE_ACTION_START_A_FLUSH ||
825          result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT)) {
826
827         int taperalgo = conf_taperalgo;
828         if (result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT) {
829             if (taperalgo == ALGO_FIRST)
830                 taperalgo = ALGO_FIRSTFIT;
831             else if (taperalgo == ALGO_LARGEST)
832                 taperalgo = ALGO_LARGESTFIT;
833             else if (taperalgo == ALGO_SMALLEST)
834                 taperalgo = ALGO_SMALLESTFIT;
835             else if (taperalgo == ALGO_LAST)
836                 taperalgo = ALGO_LASTFIT;
837         }
838
839         extra_tapes_size = tape_length * (off_t)(conf_runtapes - current_tape);
840         for (taper1 = tapetable; taper1 < tapetable + conf_taper_parallel_write;
841                                  taper1++) {
842             if (taper1->state & TAPER_STATE_TAPE_STARTED) {
843                 extra_tapes_size += taper1->left;
844             }
845             dp = taper1->disk;
846             if (dp) {
847                 extra_tapes_size -= (sched(dp)->act_size - taper1->written);
848             }
849         }
850
851         if (taper->state & TAPER_STATE_TAPE_STARTED) {
852             taper_left = taper->left;
853         } else {
854             taper_left = tape_length;
855         }
856         dp = NULL;
857         datestamp = sched(tapeq.head)->datestamp;
858         switch(taperalgo) {
859         case ALGO_FIRST:
860                 dp = dequeue_disk(&tapeq);
861                 break;
862         case ALGO_FIRSTFIT:
863                 fit = tapeq.head;
864                 while (fit != NULL) {
865                     if (sched(fit)->act_size <=
866                              (fit->splitsize ? extra_tapes_size : taper_left) &&
867                              strcmp(sched(fit)->datestamp, datestamp) <= 0) {
868                         dp = fit;
869                         fit = NULL;
870                     }
871                     else {
872                         fit = fit->next;
873                     }
874                 }
875                 if(dp) remove_disk(&tapeq, dp);
876                 break;
877         case ALGO_LARGEST:
878                 fit = dp = tapeq.head;
879                 while (fit != NULL) {
880                     if(sched(fit)->act_size > sched(dp)->act_size &&
881                        strcmp(sched(fit)->datestamp, datestamp) <= 0) {
882                         dp = fit;
883                     }
884                     fit = fit->next;
885                 }
886                 if(dp) remove_disk(&tapeq, dp);
887                 break;
888         case ALGO_LARGESTFIT:
889                 fit = tapeq.head;
890                 while (fit != NULL) {
891                     if(sched(fit)->act_size <=
892                        (fit->splitsize ? extra_tapes_size : taper_left) &&
893                        (!dp || sched(fit)->act_size > sched(dp)->act_size) &&
894                        strcmp(sched(fit)->datestamp, datestamp) <= 0) {
895                         dp = fit;
896                     }
897                     fit = fit->next;
898                 }
899                 if(dp) remove_disk(&tapeq, dp);
900                 break;
901         case ALGO_SMALLEST:
902                 fit = dp = tapeq.head;
903                 while (fit != NULL) {
904                     if (sched(fit)->act_size < sched(dp)->act_size &&
905                         strcmp(sched(fit)->datestamp, datestamp) <= 0) {
906                         dp = fit;
907                     }
908                     fit = fit->next;
909                 }
910                 if(dp) remove_disk(&tapeq, dp);
911                 break;
912         case ALGO_SMALLESTFIT:
913                 fit = dp = tapeq.head;
914                 while (fit != NULL) {
915                     if (sched(fit)->act_size <=
916                         (fit->splitsize ? extra_tapes_size : taper_left) &&
917                         (!dp || sched(fit)->act_size < sched(dp)->act_size) &&
918                         strcmp(sched(fit)->datestamp, datestamp) <= 0) {
919                         dp = fit;
920                     }
921                     fit = fit->next;
922                 }
923                 if(dp) remove_disk(&tapeq, dp);
924                 break;
925         case ALGO_LAST:
926                 dp = tapeq.tail;
927                 remove_disk(&tapeq, dp);
928                 break;
929         case ALGO_LASTFIT:
930                 fit = tapeq.tail;
931                 while (fit != NULL) {
932                     if (sched(fit)->act_size <=
933                         (fit->splitsize ? extra_tapes_size : taper_left) &&
934                         (!dp || sched(fit)->act_size < sched(dp)->act_size) &&
935                         strcmp(sched(fit)->datestamp, datestamp) <= 0) {
936                         dp = fit;
937                     }
938                     fit = fit->prev;
939                 }
940                 if(dp) remove_disk(&tapeq, dp);
941                 break;
942         }
943         if (!dp) {
944             if (!(result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT)) {
945                 if(conf_taperalgo != ALGO_SMALLEST)  {
946                     g_fprintf(stderr,
947                         _("driver: startaflush: Using SMALLEST because nothing fit\n"));
948                 }
949                 
950                 fit = dp = tapeq.head;
951                 while (fit != NULL) {
952                     if (sched(fit)->act_size < sched(dp)->act_size &&
953                         strcmp(sched(fit)->datestamp, datestamp) <= 0) {
954                         dp = fit;
955                     }
956                     fit = fit->next;
957                 }
958                 if(dp) remove_disk(&tapeq, dp);
959             }
960         }
961         if (dp) {
962             taper->disk = dp;
963             taper->dumper = NULL;
964             amfree(taper->input_error);
965             amfree(taper->tape_error);
966             taper->result = LAST_TOK;
967             taper->sendresult = 0;
968             amfree(taper->first_label);
969             taper->written = 0;
970             taper->state &= ~TAPER_STATE_IDLE;
971             taper->state |= TAPER_STATE_FILE_TO_TAPE;
972             taper->dumper = NULL;
973             qname = quote_string(dp->name);
974             if (taper_nb_wait_reply == 0) {
975                 taper_ev_read = event_register(taper_fd, EV_READFD,
976                                                handle_taper_result, NULL);
977             }
978             taper_nb_wait_reply++;
979             taper->nb_dle++;
980             sched(dp)->taper = taper;
981             taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level,
982                       sched(dp)->datestamp);
983             g_fprintf(stderr,_("driver: startaflush: %s %s %s %lld %lld\n"),
984                     taperalgo2str(taperalgo), dp->host->hostname, qname,
985                     (long long)sched(taper->disk)->act_size,
986                     (long long)taper->left);
987             amfree(qname);
988             *state_changed = TRUE;
989         }
990     }
991 }
992
993 static int
994 client_constrained(
995     disk_t *    dp)
996 {
997     disk_t *dp2;
998
999     /* first, check if host is too busy */
1000
1001     if(dp->host->inprogress >= dp->host->maxdumps) {
1002         return 1;
1003     }
1004
1005     /* next, check conflict with other dumps on same spindle */
1006
1007     if(dp->spindle == -1) {     /* but spindle -1 never conflicts by def. */
1008         return 0;
1009     }
1010
1011     for(dp2 = dp->host->disks; dp2 != NULL; dp2 = dp2->hostnext)
1012         if(dp2->inprogress && dp2->spindle == dp->spindle) {
1013             return 1;
1014         }
1015
1016     return 0;
1017 }
1018
1019 static void
1020 allow_dump_dle(
1021     disk_t         *diskp,
1022     taper_t        *taper,
1023     char            dumptype,
1024     disklist_t     *rq,
1025     const time_t    now,
1026     int             dumper_to_holding,
1027     int            *cur_idle,
1028     disk_t        **delayed_diskp,
1029     disk_t        **diskp_accept,
1030     assignedhd_t ***holdp_accept,
1031     off_t           extra_tapes_size)
1032 {
1033     assignedhd_t **holdp=NULL;
1034
1035     if (diskp->host->start_t > now) {
1036         *cur_idle = max(*cur_idle, IDLE_START_WAIT);
1037         if (*delayed_diskp == NULL || sleep_time > diskp->host->start_t) {
1038             *delayed_diskp = diskp;
1039             sleep_time = diskp->host->start_t;
1040         }
1041     } else if(diskp->start_t > now) {
1042         *cur_idle = max(*cur_idle, IDLE_START_WAIT);
1043         if (*delayed_diskp == NULL || sleep_time > diskp->start_t) {
1044             *delayed_diskp = diskp;
1045             sleep_time = diskp->start_t;
1046         }
1047     } else if (diskp->host->netif->curusage > 0 &&
1048                sched(diskp)->est_kps > free_kps(diskp->host->netif)) {
1049         *cur_idle = max(*cur_idle, IDLE_NO_BANDWIDTH);
1050     } else if (!taper && sched(diskp)->no_space) {
1051         *cur_idle = max(*cur_idle, IDLE_NO_DISKSPACE);
1052     } else if (!taper && diskp->to_holdingdisk == HOLD_NEVER) {
1053         *cur_idle = max(*cur_idle, IDLE_NO_HOLD);
1054     } else if (extra_tapes_size && sched(diskp)->est_size > extra_tapes_size) {
1055         *cur_idle = max(*cur_idle, IDLE_NO_DISKSPACE);
1056         /* no tape space */
1057     } else if (!taper && (holdp =
1058         find_diskspace(sched(diskp)->est_size, cur_idle, NULL)) == NULL) {
1059         *cur_idle = max(*cur_idle, IDLE_NO_DISKSPACE);
1060         if (empty(tapeq) && dumper_to_holding == 0 && rq != &directq && no_taper_flushing()) {
1061             remove_disk(rq, diskp);
1062             if (diskp->to_holdingdisk != HOLD_REQUIRED) {
1063                 enqueue_disk(&directq, diskp);
1064                 diskp->to_holdingdisk = HOLD_NEVER;
1065             }
1066             if (empty(*rq)) force_flush = 1;
1067         }
1068     } else if (client_constrained(diskp)) {
1069         free_assignedhd(holdp);
1070         *cur_idle = max(*cur_idle, IDLE_CLIENT_CONSTRAINED);
1071     } else {
1072
1073         /* disk fits, dump it */
1074         int accept = !*diskp_accept;
1075         if(!accept) {
1076             switch(dumptype) {
1077               case 's': accept = (sched(diskp)->est_size < sched(*diskp_accept)->est_size);
1078                         break;
1079               case 'S': accept = (sched(diskp)->est_size > sched(*diskp_accept)->est_size);
1080                         break;
1081               case 't': accept = (sched(diskp)->est_time < sched(*diskp_accept)->est_time);
1082                         break;
1083               case 'T': accept = (sched(diskp)->est_time > sched(*diskp_accept)->est_time);
1084                         break;
1085               case 'b': accept = (sched(diskp)->est_kps < sched(*diskp_accept)->est_kps);
1086                         break;
1087               case 'B': accept = (sched(diskp)->est_kps > sched(*diskp_accept)->est_kps);
1088                         break;
1089               default:  log_add(L_WARNING, _("Unknown dumporder character \'%c\', using 's'.\n"),
1090                                 dumptype);
1091                         accept = (sched(diskp)->est_size < sched(*diskp_accept)->est_size);
1092                         break;
1093             }
1094         }
1095         if(accept) {
1096             if( !*diskp_accept || !degraded_mode || diskp->priority >= (*diskp_accept)->priority) {
1097                 if(*holdp_accept) free_assignedhd(*holdp_accept);
1098                 *diskp_accept = diskp;
1099                 *holdp_accept = holdp;
1100             }
1101             else {
1102                 free_assignedhd(holdp);
1103             }
1104         }
1105         else {
1106             free_assignedhd(holdp);
1107         }
1108     }
1109 }
1110
1111 static void
1112 start_some_dumps(
1113     disklist_t *rq)
1114 {
1115     const time_t now = time(NULL);
1116     int cur_idle;
1117     disk_t *diskp, *delayed_diskp, *diskp_accept, *diskp_next;
1118     disk_t *dp;
1119     assignedhd_t **holdp=NULL, **holdp_accept;
1120     cmd_t cmd;
1121     int result_argc;
1122     char **result_argv;
1123     chunker_t *chunker;
1124     dumper_t *dumper;
1125     taper_t  *taper;
1126     char dumptype;
1127     char *dumporder;
1128     int  dumper_to_holding = 0;
1129     gboolean state_changed = FALSE;
1130
1131     /* don't start any actual dumps until the taper is started */
1132     if (!taper_started) return;
1133
1134     idle_reason = IDLE_NO_DUMPERS;
1135     sleep_time = 0;
1136
1137     if(dumpers_ev_time != NULL) {
1138         event_release(dumpers_ev_time);
1139         dumpers_ev_time = NULL;
1140     }
1141
1142     for(dumper = dmptable; dumper < (dmptable+inparallel); dumper++) {
1143         if (dumper->busy && dumper->dp->to_holdingdisk != HOLD_NEVER) {
1144             dumper_to_holding++;
1145         }
1146     }
1147     for (dumper = dmptable; dumper < dmptable+inparallel; dumper++) {
1148
1149         if( dumper->busy || dumper->down) {
1150             continue;
1151         }
1152
1153         if (dumper->ev_read != NULL) {
1154             event_release(dumper->ev_read);
1155             dumper->ev_read = NULL;
1156         }
1157
1158         /*
1159          * A potential problem with starting from the bottom of the dump time
1160          * distribution is that a slave host will have both one of the shortest
1161          * and one of the longest disks, so starting its shortest disk first will
1162          * tie up the host and eliminate its longest disk from consideration the
1163          * first pass through.  This could cause a big delay in starting that long
1164          * disk, which could drag out the whole night's dumps.
1165          *
1166          * While starting from the top of the dump time distribution solves the
1167          * above problem, this turns out to be a bad idea, because the big dumps
1168          * will almost certainly pack the holding disk completely, leaving no
1169          * room for even one small dump to start.  This ends up shutting out the
1170          * small-end dumpers completely (they stay idle).
1171          *
1172          * The introduction of multiple simultaneous dumps to one host alleviates
1173          * the biggest&smallest dumps problem: both can be started at the
1174          * beginning.
1175          */
1176
1177         diskp_accept = NULL;
1178         holdp_accept = NULL;
1179         delayed_diskp = NULL;
1180
1181         cur_idle = NOT_IDLE;
1182
1183         dumporder = getconf_str(CNF_DUMPORDER);
1184         if(strlen(dumporder) > (size_t)(dumper-dmptable)) {
1185             dumptype = dumporder[dumper-dmptable];
1186         }
1187         else {
1188             if(dumper-dmptable < 3)
1189                 dumptype = 't';
1190             else
1191                 dumptype = 'T';
1192         }
1193
1194         diskp = NULL;
1195         taper = NULL;
1196         if (!empty(directq)) {
1197             taper = idle_taper();
1198             if (taper) {
1199                 TapeAction result_tape_action;
1200                 char *why_no_new_tape = NULL;
1201                 result_tape_action = tape_action(taper, &why_no_new_tape);
1202                 if (result_tape_action & TAPE_ACTION_START_A_FLUSH ||
1203                     result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT) {
1204                     off_t extra_tapes_size = 0;
1205                     taper_t *taper1;
1206
1207                     if (result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT) {
1208                         extra_tapes_size = tape_length *
1209                                           (off_t)(conf_runtapes - current_tape);
1210                         for (taper1 = tapetable;
1211                              taper1 < tapetable + conf_taper_parallel_write;
1212                              taper1++) {
1213                             if (taper1->state & TAPER_STATE_TAPE_STARTED) {
1214                                 extra_tapes_size += taper1->left;
1215                             }
1216                             dp = taper1->disk;
1217                             if (dp) {
1218                                 extra_tapes_size -= (sched(dp)->est_size -
1219                                                     taper1->written);
1220                             }
1221                         }
1222                     }
1223
1224                     for (diskp = directq.head; diskp != NULL;
1225                                                diskp = diskp_next) {
1226                         diskp_next = diskp->next;
1227                         allow_dump_dle(diskp, taper, dumptype, &directq, now,
1228                                        dumper_to_holding, &cur_idle,
1229                                        &delayed_diskp, &diskp_accept,
1230                                        &holdp_accept, extra_tapes_size);
1231                     }
1232                     if (diskp_accept) {
1233                         diskp = diskp_accept;
1234                         holdp = holdp_accept;
1235                     } else {
1236                         taper = NULL;
1237                     }
1238                 } else {
1239                     taper = NULL;
1240                 }
1241             }
1242         }
1243
1244         if (diskp == NULL) {
1245             for(diskp = rq->head; diskp != NULL; diskp = diskp_next) {
1246                 diskp_next = diskp->next;
1247                 assert(diskp->host != NULL && sched(diskp) != NULL);
1248
1249                 allow_dump_dle(diskp, NULL, dumptype, rq, now,
1250                                dumper_to_holding, &cur_idle, &delayed_diskp,
1251                                &diskp_accept, &holdp_accept, 0);
1252             }
1253             diskp = diskp_accept;
1254             holdp = holdp_accept;
1255         }
1256
1257         idle_reason = max(idle_reason, cur_idle);
1258         if (diskp == NULL && idle_reason == IDLE_NO_DISKSPACE) {
1259             /* continue flush waiting for new tape */
1260             startaflush();
1261         }
1262
1263         /*
1264          * If we have no disk at this point, and there are disks that
1265          * are delayed, then schedule a time event to call this dumper
1266          * with the disk with the shortest delay.
1267          */
1268         if (diskp == NULL && delayed_diskp != NULL) {
1269             assert(sleep_time > now);
1270             sleep_time -= now;
1271             dumpers_ev_time = event_register((event_id_t)sleep_time, EV_TIME,
1272                 handle_dumpers_time, &runq);
1273             return;
1274         } else if (diskp != NULL && taper == NULL) {
1275             sched(diskp)->act_size = (off_t)0;
1276             allocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps);
1277             sched(diskp)->activehd = assign_holdingdisk(holdp, diskp);
1278             amfree(holdp);
1279             sched(diskp)->destname = newstralloc(sched(diskp)->destname,
1280                                                  sched(diskp)->holdp[0]->destname);
1281             diskp->host->inprogress++;  /* host is now busy */
1282             diskp->inprogress = 1;
1283             sched(diskp)->dumper = dumper;
1284             sched(diskp)->timestamp = now;
1285             amfree(diskp->dataport_list);
1286
1287             dumper->busy = 1;           /* dumper is now busy */
1288             dumper->dp = diskp;         /* link disk to dumper */
1289             remove_disk(rq, diskp);             /* take it off the run queue */
1290
1291             sched(diskp)->origsize = (off_t)-1;
1292             sched(diskp)->dumpsize = (off_t)-1;
1293             sched(diskp)->dumptime = (time_t)0;
1294             sched(diskp)->tapetime = (time_t)0;
1295             chunker = dumper->chunker = &chktable[dumper - dmptable];
1296             chunker->result = LAST_TOK;
1297             dumper->result = LAST_TOK;
1298             startup_chunk_process(chunker,chunker_program);
1299             chunker_cmd(chunker, START, NULL, driver_timestamp);
1300             chunker->dumper = dumper;
1301             chunker_cmd(chunker, PORT_WRITE, diskp, NULL);
1302             cmd = getresult(chunker->fd, 1, &result_argc, &result_argv);
1303             if(cmd != PORT) {
1304                 assignedhd_t **h=NULL;
1305                 int activehd;
1306                 char *qname = quote_string(diskp->name);
1307
1308                 g_printf(_("driver: did not get PORT from %s for %s:%s\n"),
1309                        chunker->name, diskp->host->hostname, qname);
1310                 amfree(qname);
1311                 fflush(stdout);
1312
1313                 deallocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps);
1314                 h = sched(diskp)->holdp;
1315                 activehd = sched(diskp)->activehd;
1316                 h[activehd]->used = 0;
1317                 h[activehd]->disk->allocated_dumpers--;
1318                 adjust_diskspace(diskp, DONE);
1319                 delete_diskspace(diskp);
1320                 diskp->host->inprogress--;
1321                 diskp->inprogress = 0;
1322                 sched(diskp)->dumper = NULL;
1323                 dumper->busy = 0;
1324                 dumper->dp = NULL;
1325                 sched(diskp)->dump_attempted++;
1326                 free_serial_dp(diskp);
1327                 if(sched(diskp)->dump_attempted < 2)
1328                     enqueue_disk(rq, diskp);
1329             }
1330             else {
1331                 dumper->ev_read = event_register((event_id_t)dumper->fd, EV_READFD,
1332                                                  handle_dumper_result, dumper);
1333                 chunker->ev_read = event_register((event_id_t)chunker->fd, EV_READFD,
1334                                                    handle_chunker_result, chunker);
1335                 dumper->output_port = atoi(result_argv[1]);
1336                 amfree(diskp->dataport_list);
1337                 diskp->dataport_list = stralloc(result_argv[2]);
1338
1339                 if (diskp->host->pre_script == 0) {
1340                     run_server_host_scripts(EXECUTE_ON_PRE_HOST_BACKUP,
1341                                             get_config_name(), diskp->host);
1342                     diskp->host->pre_script = 1;
1343                 }
1344                 run_server_dle_scripts(EXECUTE_ON_PRE_DLE_BACKUP,
1345                                    get_config_name(), diskp,
1346                                    sched(diskp)->level);
1347                 dumper_cmd(dumper, PORT_DUMP, diskp, NULL);
1348             }
1349             diskp->host->start_t = now + 15;
1350             if (empty(*rq)) force_flush = 1;
1351
1352             if (result_argv)
1353                 g_strfreev(result_argv);
1354             short_dump_state();
1355         } else if (diskp != NULL && taper != NULL) { /* dump to tape */
1356             sched(diskp)->act_size = (off_t)0;
1357             allocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps);
1358             diskp->host->inprogress++;  /* host is now busy */
1359             diskp->inprogress = 1;
1360             sched(diskp)->dumper = dumper;
1361             sched(diskp)->taper = taper;
1362             sched(diskp)->timestamp = now;
1363             dumper->chunker = NULL;
1364             amfree(diskp->dataport_list);
1365
1366             dumper->busy = 1;           /* dumper is now busy */
1367             dumper->dp = diskp;         /* link disk to dumper */
1368             remove_disk(&directq, diskp);  /* take it off the direct queue */
1369
1370             sched(diskp)->origsize = (off_t)-1;
1371             sched(diskp)->dumpsize = (off_t)-1;
1372             sched(diskp)->dumptime = (time_t)0;
1373             sched(diskp)->tapetime = (time_t)0;
1374             dumper->result = LAST_TOK;
1375             taper->result = LAST_TOK;
1376             taper->input_error = NULL;
1377             taper->tape_error = NULL;
1378             taper->disk = diskp;
1379             taper->first_label = NULL;
1380             taper->written = 0;
1381             taper->dumper = dumper;
1382             taper->state |= TAPER_STATE_DUMP_TO_TAPE;
1383             taper->state &= ~TAPER_STATE_IDLE;
1384             taper->nb_dle++;
1385             if (taper_nb_wait_reply == 0) {
1386                 taper_ev_read = event_register(taper_fd, EV_READFD,
1387                                                handle_taper_result, NULL);
1388             }
1389
1390             taper_nb_wait_reply++;
1391             taper_cmd(PORT_WRITE, diskp, NULL, sched(diskp)->level,
1392                       sched(diskp)->datestamp);
1393             diskp->host->start_t = now + 15;
1394
1395             state_changed = TRUE;
1396         }
1397     }
1398     if (state_changed) {
1399         short_dump_state();
1400     }
1401 }
1402
1403 /*
1404  * This gets called when a dumper is delayed for some reason.  It may
1405  * be because a disk has a delayed start, or amanda is constrained
1406  * by network or disk limits.
1407  */
1408
1409 static void
1410 handle_dumpers_time(
1411     void *      cookie)
1412 {
1413     disklist_t *runq = cookie;
1414     event_release(dumpers_ev_time);
1415     dumpers_ev_time = NULL; 
1416     start_some_dumps(runq);
1417 }
1418
1419 static void
1420 dump_schedule(
1421     disklist_t *qp,
1422     char *      str)
1423 {
1424     disk_t *dp;
1425     char *qname;
1426
1427     g_printf(_("dump of driver schedule %s:\n--------\n"), str);
1428
1429     for(dp = qp->head; dp != NULL; dp = dp->next) {
1430         qname = quote_string(dp->name);
1431         g_printf("  %-20s %-25s lv %d t %5lu s %lld p %d\n",
1432                dp->host->hostname, qname, sched(dp)->level,
1433                sched(dp)->est_time,
1434                (long long)sched(dp)->est_size, sched(dp)->priority);
1435         amfree(qname);
1436     }
1437     g_printf("--------\n");
1438 }
1439
1440 static void
1441 start_degraded_mode(
1442     /*@keep@*/ disklist_t *queuep)
1443 {
1444     disk_t *dp;
1445     disklist_t newq;
1446     off_t est_full_size;
1447     char *qname;
1448
1449     newq.head = newq.tail = 0;
1450
1451     dump_schedule(queuep, _("before start degraded mode"));
1452
1453     est_full_size = (off_t)0;
1454     while(!empty(*queuep)) {
1455         dp = dequeue_disk(queuep);
1456
1457         qname = quote_string(dp->name);
1458         if(sched(dp)->level != 0)
1459             /* go ahead and do the disk as-is */
1460             enqueue_disk(&newq, dp);
1461         else {
1462             if (reserved_space + est_full_size + sched(dp)->est_size
1463                 <= total_disksize) {
1464                 enqueue_disk(&newq, dp);
1465                 est_full_size += sched(dp)->est_size;
1466             }
1467             else if(sched(dp)->degr_level != -1) {
1468                 sched(dp)->level = sched(dp)->degr_level;
1469                 sched(dp)->dumpdate = sched(dp)->degr_dumpdate;
1470                 sched(dp)->est_nsize = sched(dp)->degr_nsize;
1471                 sched(dp)->est_csize = sched(dp)->degr_csize;
1472                 sched(dp)->est_time = sched(dp)->degr_time;
1473                 sched(dp)->est_kps  = sched(dp)->degr_kps;
1474                 enqueue_disk(&newq, dp);
1475             }
1476             else {
1477                 log_add(L_FAIL, "%s %s %s %d [%s]",
1478                         dp->host->hostname, qname, sched(dp)->datestamp,
1479                         sched(dp)->level, sched(dp)->degr_mesg);
1480             }
1481         }
1482         amfree(qname);
1483     }
1484
1485     /*@i@*/ *queuep = newq;
1486     degraded_mode = 1;
1487
1488     dump_schedule(queuep, _("after start degraded mode"));
1489 }
1490
1491
1492 static void
1493 continue_port_dumps(void)
1494 {
1495     disk_t *dp, *ndp;
1496     assignedhd_t **h;
1497     int active_dumpers=0, busy_dumpers=0, i;
1498     dumper_t *dumper;
1499
1500     /* First we try to grant diskspace to some dumps waiting for it. */
1501     for( dp = roomq.head; dp; dp = ndp ) {
1502         ndp = dp->next;
1503         /* find last holdingdisk used by this dump */
1504         for( i = 0, h = sched(dp)->holdp; h[i+1]; i++ ) {
1505             (void)h; /* Quiet lint */
1506         }
1507         /* find more space */
1508         h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size,
1509                             &active_dumpers, h[i] );
1510         if( h ) {
1511             for(dumper = dmptable; dumper < dmptable + inparallel &&
1512                                    dumper->dp != dp; dumper++) {
1513                 (void)dp; /* Quiet lint */
1514             }
1515             assert( dumper < dmptable + inparallel );
1516             sched(dp)->activehd = assign_holdingdisk( h, dp );
1517             chunker_cmd( dumper->chunker, CONTINUE, dp, NULL );
1518             amfree(h);
1519             remove_disk( &roomq, dp );
1520         }
1521     }
1522
1523     /* So for some disks there is less holding diskspace available than
1524      * was asked for. Possible reasons are
1525      * a) diskspace has been allocated for other dumps which are
1526      *    still running or already being written to tape
1527      * b) all other dumps have been suspended due to lack of diskspace
1528      * Case a) is not a problem. We just wait for the diskspace to
1529      * be freed by moving the current disk to a queue.
1530      * If case b) occurs, we have a deadlock situation. We select
1531      * a dump from the queue to be aborted and abort it. It will
1532      * be retried directly to tape.
1533      */
1534     for(dp=NULL, dumper = dmptable; dumper < (dmptable+inparallel); dumper++) {
1535         if( dumper->busy ) {
1536             busy_dumpers++;
1537             if( !find_disk(&roomq, dumper->dp) ) {
1538                 if (dumper->chunker) {
1539                     active_dumpers++;
1540                 }
1541             } else if( !dp ||
1542                        sched(dp)->est_size > sched(dumper->dp)->est_size ) {
1543                 dp = dumper->dp;
1544             }
1545         }
1546     }
1547     if((dp != NULL) && (active_dumpers == 0) && (busy_dumpers > 0) &&
1548         ((no_taper_flushing() && empty(tapeq)) || degraded_mode) &&
1549         pending_aborts == 0 ) { /* case b */
1550         sched(dp)->no_space = 1;
1551         /* At this time, dp points to the dump with the smallest est_size.
1552          * We abort that dump, hopefully not wasting too much time retrying it.
1553          */
1554         remove_disk( &roomq, dp );
1555         chunker_cmd(sched(dp)->dumper->chunker, ABORT, NULL, _("Not enough holding disk space"));
1556         dumper_cmd( sched(dp)->dumper, ABORT, NULL, _("Not enough holding disk space"));
1557         pending_aborts++;
1558     }
1559 }
1560
1561
1562 static void
1563 handle_taper_result(
1564         void *cookie G_GNUC_UNUSED)
1565 {
1566     disk_t *dp = NULL;
1567     dumper_t *dumper;
1568     cmd_t cmd;
1569     int result_argc;
1570     char **result_argv;
1571     char *qname, *q;
1572     char *s;
1573     taper_t *taper = NULL;
1574     taper_t *taper1;
1575     int      i;
1576     off_t    partsize;
1577
1578     assert(cookie == NULL);
1579
1580     do {
1581
1582         short_dump_state();
1583         taper = NULL;
1584
1585         cmd = getresult(taper_fd, 1, &result_argc, &result_argv);
1586
1587         switch(cmd) {
1588
1589         case TAPER_OK:
1590             if(result_argc != 2) {
1591                 error(_("error: [taper FAILED result_argc != 2: %d"), result_argc);
1592                 /*NOTREACHED*/
1593             }
1594
1595             taper = NULL;
1596             taper_started = 1;
1597             for (i=0; i < conf_taper_parallel_write; i++) {
1598                 if (strcmp(tapetable[i].name, result_argv[1]) == 0) {
1599                     taper= &tapetable[i];
1600                 }
1601             }
1602             assert(taper != NULL);
1603             taper->left = 0;
1604             taper->nb_dle = 0;
1605             taper->state &= ~TAPER_STATE_INIT;
1606             taper->state |= TAPER_STATE_RESERVATION;
1607             taper->state |= TAPER_STATE_IDLE;
1608             amfree(taper->first_label);
1609             taper_nb_wait_reply--;
1610             taper_nb_scan_volume--;
1611             last_started_taper = taper;
1612             if (taper_nb_wait_reply == 0) {
1613                 event_release(taper_ev_read);
1614                 taper_ev_read = NULL;
1615             }
1616             start_some_dumps(&runq);
1617             startaflush();
1618             break;
1619
1620         case FAILED:    /* FAILED <handle> INPUT-* TAPE-* <input err mesg> <tape err mesg> */
1621             if(result_argc != 6) {
1622                 error(_("error: [taper FAILED result_argc != 6: %d"), result_argc);
1623                 /*NOTREACHED*/
1624             }
1625
1626             dp = serial2disk(result_argv[1]);
1627             taper = sched(dp)->taper;
1628             assert(dp == taper->disk);
1629             if (!taper->dumper)
1630                 free_serial(result_argv[1]);
1631
1632             qname = quote_string(dp->name);
1633             g_printf(_("driver: finished-cmd time %s taper wrote %s:%s\n"),
1634                    walltime_str(curclock()), dp->host->hostname, qname);
1635             fflush(stdout);
1636
1637             if (strcmp(result_argv[2], "INPUT-ERROR") == 0) {
1638                 taper->input_error = newstralloc(taper->input_error, result_argv[4]);
1639                 taper->result = FAILED;
1640                 amfree(qname);
1641                 break;
1642             } else if (strcmp(result_argv[2], "INPUT-GOOD") != 0) {
1643                 taper->tape_error = newstralloc(taper->tape_error,
1644                                                _("Taper protocol error"));
1645                 taper->result = FAILED;
1646                 log_add(L_FAIL, _("%s %s %s %d [%s]"),
1647                         dp->host->hostname, qname, sched(dp)->datestamp,
1648                         sched(dp)->level, taper->tape_error);
1649                 amfree(qname);
1650                 break;
1651             }
1652             if (strcmp(result_argv[3], "TAPE-ERROR") == 0) {
1653                 taper->state &= ~TAPER_STATE_TAPE_STARTED;
1654                 taper->tape_error = newstralloc(taper->tape_error, result_argv[5]);
1655                 taper->result = FAILED;
1656                 amfree(qname);
1657                 break;
1658             } else if (strcmp(result_argv[3], "TAPE-GOOD") != 0) {
1659                 taper->state &= ~TAPER_STATE_TAPE_STARTED;
1660                 taper->tape_error = newstralloc(taper->tape_error,
1661                                                _("Taper protocol error"));
1662                 taper->result = FAILED;
1663                 log_add(L_FAIL, _("%s %s %s %d [%s]"),
1664                         dp->host->hostname, qname, sched(dp)->datestamp,
1665                         sched(dp)->level, taper->tape_error);
1666                 amfree(qname);
1667                 break;
1668             }
1669
1670             amfree(qname);
1671             taper->result = cmd;
1672
1673             break;
1674
1675         case PARTIAL:   /* PARTIAL <handle> INPUT-* TAPE-* <stat mess> <input err mesg> <tape err mesg>*/
1676         case DONE:      /* DONE <handle> INPUT-GOOD TAPE-GOOD <stat mess> <input err mesg> <tape err mesg> */
1677             if(result_argc != 7) {
1678                 error(_("error: [taper PARTIAL result_argc != 7: %d"), result_argc);
1679                 /*NOTREACHED*/
1680             }
1681
1682             dp = serial2disk(result_argv[1]);
1683             taper = sched(dp)->taper;
1684             assert(dp == taper->disk);
1685             if (!taper->dumper)
1686                 free_serial(result_argv[1]);
1687
1688             qname = quote_string(dp->name);
1689             g_printf(_("driver: finished-cmd time %s taper wrote %s:%s\n"),
1690                    walltime_str(curclock()), dp->host->hostname, qname);
1691             fflush(stdout);
1692
1693             if (strcmp(result_argv[2], "INPUT-ERROR") == 0) {
1694                 taper->input_error = newstralloc(taper->input_error, result_argv[5]);
1695                 taper->result = FAILED;
1696                 amfree(qname);
1697                 break;
1698             } else if (strcmp(result_argv[2], "INPUT-GOOD") != 0) {
1699                 taper->tape_error = newstralloc(taper->tape_error,
1700                                                _("Taper protocol error"));
1701                 taper->result = FAILED;
1702                 log_add(L_FAIL, _("%s %s %s %d [%s]"),
1703                         dp->host->hostname, qname, sched(dp)->datestamp,
1704                         sched(dp)->level, taper->tape_error);
1705                 amfree(qname);
1706                 break;
1707             }
1708             if (strcmp(result_argv[3], "TAPE-ERROR") == 0) {
1709                 taper->state &= ~TAPER_STATE_TAPE_STARTED;
1710                 taper->tape_error = newstralloc(taper->tape_error, result_argv[6]);
1711                 taper->result = FAILED;
1712                 amfree(qname);
1713                 break;
1714             } else if (strcmp(result_argv[3], "TAPE-GOOD") != 0) {
1715                 taper->state &= ~TAPER_STATE_TAPE_STARTED;
1716                 taper->tape_error = newstralloc(taper->tape_error,
1717                                                _("Taper protocol error"));
1718                 taper->result = FAILED;
1719                 log_add(L_FAIL, _("%s %s %s %d [%s]"),
1720                         dp->host->hostname, qname, sched(dp)->datestamp,
1721                         sched(dp)->level, taper->tape_error);
1722                 amfree(qname);
1723                 break;
1724             }
1725
1726             s = strstr(result_argv[4], " kb ");
1727             if (s) {
1728                 s += 4;
1729                 sched(dp)->dumpsize = atol(s);
1730             } else {
1731                 s = strstr(result_argv[4], " bytes ");
1732                 if (s) {
1733                     s += 7;
1734                     sched(dp)->dumpsize = atol(s)/1024;
1735                 }
1736             }
1737
1738             taper->result = cmd;
1739             amfree(qname);
1740
1741             break;
1742
1743         case PARTDONE:  /* PARTDONE <handle> <label> <fileno> <kbytes> <stat> */
1744             dp = serial2disk(result_argv[1]);
1745             taper = sched(dp)->taper;
1746             assert(dp == taper->disk);
1747             if (result_argc != 6) {
1748                 error(_("error [taper PARTDONE result_argc != 6: %d]"),
1749                       result_argc);
1750                 /*NOTREACHED*/
1751             }
1752             if (!taper->first_label) {
1753                 amfree(taper->first_label);
1754                 taper->first_label = stralloc(result_argv[2]);
1755                 taper->first_fileno = OFF_T_ATOI(result_argv[3]);
1756             }
1757             taper->written += OFF_T_ATOI(result_argv[4]);
1758             if (taper->written > sched(taper->disk)->act_size)
1759                 sched(taper->disk)->act_size = taper->written;
1760
1761             partsize = 0;
1762             s = strstr(result_argv[5], " kb ");
1763             if (s) {
1764                 s += 4;
1765                 partsize = atol(s);
1766             } else {
1767                 s = strstr(result_argv[5], " bytes ");
1768                 if (s) {
1769                     s += 7;
1770                     partsize = atol(s)/1024;
1771                 }
1772             }
1773             taper->left -= partsize;
1774
1775             break;
1776
1777         case REQUEST_NEW_TAPE:  /* REQUEST-NEW-TAPE <handle> */
1778             if (result_argc != 2) {
1779                 error(_("error [taper REQUEST_NEW_TAPE result_argc != 2: %d]"),
1780                       result_argc);
1781                 /*NOTREACHED*/
1782             }
1783
1784             dp = serial2disk(result_argv[1]);
1785             taper = sched(dp)->taper;
1786             if (taper->state & TAPER_STATE_DONE) {
1787                 taper_cmd(NO_NEW_TAPE, taper->disk, "taper found no tape", 0, NULL);
1788             } else {
1789                 taper->state &= ~TAPER_STATE_TAPE_STARTED;
1790                 taper->state |= TAPER_STATE_TAPE_REQUESTED;
1791
1792                 start_some_dumps(&runq);
1793                 startaflush();
1794             }
1795             break;
1796
1797         case NEW_TAPE: /* NEW-TAPE <handle> <label> */
1798             if (result_argc != 3) {
1799                 error(_("error [taper NEW_TAPE result_argc != 3: %d]"),
1800                       result_argc);
1801                 /*NOTREACHED*/
1802             }
1803
1804             nb_sent_new_tape--;
1805             taper_nb_scan_volume--;
1806             dp = serial2disk(result_argv[1]);
1807             taper = sched(dp)->taper;
1808             /* Update our tape counter and reset taper->left */
1809             current_tape++;
1810             taper->nb_dle = 1;
1811             taper->left = tape_length;
1812             taper->state &= ~TAPER_STATE_WAIT_NEW_TAPE;
1813             taper->state |= TAPER_STATE_TAPE_STARTED;
1814             last_started_taper = NULL;
1815
1816             /* start a new worker */
1817             for (i = 0; i < conf_taper_parallel_write ; i++) {
1818                 taper1 = &tapetable[i];
1819                 if (need_degraded == 0 &&
1820                     taper1->state == TAPER_STATE_DEFAULT) {
1821                     taper1->state = TAPER_STATE_INIT;
1822                     if (taper_nb_wait_reply == 0) {
1823                         taper_ev_read = event_register(taper_fd, EV_READFD,
1824                                                 handle_taper_result, NULL);
1825                     }
1826                     taper_nb_wait_reply++;
1827                     taper_nb_scan_volume++;
1828                     taper_cmd(START_TAPER, NULL, taper1->name, 0,
1829                               driver_timestamp);
1830                     break;
1831                 }
1832             }
1833             break;
1834
1835         case NO_NEW_TAPE:  /* NO-NEW-TAPE <handle> */
1836             if (result_argc != 2) {
1837                 error(_("error [taper NO_NEW_TAPE result_argc != 2: %d]"),
1838                       result_argc);
1839                 /*NOTREACHED*/
1840             }
1841             nb_sent_new_tape--;
1842             taper_nb_scan_volume--;
1843             dp = serial2disk(result_argv[1]);
1844             taper = sched(dp)->taper;
1845             taper->state |= TAPER_STATE_DONE;
1846             last_started_taper = NULL;
1847             start_degraded_mode(&runq);
1848             break;
1849
1850         case DUMPER_STATUS:  /* DUMPER-STATUS <handle> */
1851             if (result_argc != 2) {
1852                 error(_("error [taper DUMPER_STATUS result_argc != 2: %d]"),
1853                       result_argc);
1854                 /*NOTREACHED*/
1855             }
1856             dp = serial2disk(result_argv[1]);
1857             taper = sched(dp)->taper;
1858             if (taper->dumper->result == LAST_TOK) {
1859                 taper->sendresult = 1;
1860             } else {
1861                 if( taper->dumper->result == DONE) {
1862                     taper_cmd(DONE, dp, NULL, 0, NULL);
1863                 } else {
1864                     taper_cmd(FAILED, dp, NULL, 0, NULL);
1865                 }
1866             }
1867             break;
1868
1869         case TAPE_ERROR: /* TAPE-ERROR <name> <err mess> */
1870             taper_started = 1;
1871             if (strcmp(result_argv[1], "SETUP") == 0) {
1872                 taper_nb_wait_reply = 0;
1873                 taper_nb_scan_volume = 0;
1874             } else {
1875                 taper = taper_from_name(result_argv[1]);
1876                 taper->state = TAPER_STATE_DONE;
1877                 fflush(stdout);
1878                 q = quote_string(result_argv[2]);
1879                 log_add(L_WARNING, _("Taper error: %s"), q);
1880                 amfree(q);
1881                 if (taper) {
1882                     taper->tape_error = newstralloc(taper->tape_error,
1883                                                     result_argv[2]);
1884                 }
1885
1886                 taper_nb_wait_reply--;
1887                 taper_nb_scan_volume--;
1888             }
1889             if (taper_nb_wait_reply == 0) {
1890                 event_release(taper_ev_read);
1891                 taper_ev_read = NULL;
1892             }
1893             need_degraded = 1;
1894             if (schedule_done && !degraded_mode) {
1895                 start_degraded_mode(&runq);
1896             }
1897             start_some_dumps(&runq);
1898             break;
1899
1900         case PORT: /* PORT <name> <handle> <port> <dataport_list> */
1901             dp = serial2disk(result_argv[2]);
1902             taper = sched(dp)->taper;
1903             dumper = sched(dp)->dumper;
1904             dumper->output_port = atoi(result_argv[3]);
1905             amfree(dp->dataport_list);
1906             dp->dataport_list = stralloc(result_argv[4]);
1907
1908             amfree(taper->input_error);
1909             amfree(taper->tape_error);
1910             amfree(taper->first_label);
1911             taper->written = 0;
1912             taper->state |= TAPER_STATE_DUMP_TO_TAPE;
1913
1914             if (dp->host->pre_script == 0) {
1915                 run_server_host_scripts(EXECUTE_ON_PRE_HOST_BACKUP,
1916                                         get_config_name(), dp->host);
1917                 dp->host->pre_script = 1;
1918             }
1919             run_server_dle_scripts(EXECUTE_ON_PRE_DLE_BACKUP,
1920                                get_config_name(), dp,
1921                                sched(dp)->level);
1922             /* tell the dumper to dump to a port */
1923             dumper_cmd(dumper, PORT_DUMP, dp, NULL);
1924             dp->host->start_t = time(NULL) + 15;
1925             amfree(dp->dataport_list);
1926
1927             taper->state |= TAPER_STATE_DUMP_TO_TAPE;
1928
1929             dumper->ev_read = event_register(dumper->fd, EV_READFD,
1930                                              handle_dumper_result, dumper);
1931             break;
1932
1933         case BOGUS:
1934             log_add(L_WARNING, _("Taper protocol error"));
1935             /*
1936              * Since we received a taper error, we can't send anything more
1937              * to the taper.  Go into degraded mode to try to get everthing
1938              * onto disk.  Later, these dumps can be flushed to a new tape.
1939              * The tape queue is zapped so that it appears empty in future
1940              * checks. If there are dumps waiting for diskspace to be freed,
1941              * cancel one.
1942              */
1943             taper_started = 1;
1944             if(!nodump) {
1945                 log_add(L_WARNING,
1946                         _("going into degraded mode because of taper component error."));
1947             }
1948
1949             for (taper = tapetable;
1950                  taper < tapetable + conf_taper_parallel_write;
1951                  taper++) {
1952                 if (taper && taper->disk) {
1953                     taper->tape_error = newstralloc(taper->tape_error,"BOGUS");
1954                     taper->result = cmd;
1955                     if (taper->dumper) {
1956                         if (taper->dumper->result != LAST_TOK) {
1957                             // Dumper already returned it's result
1958                             dumper_taper_result(taper->disk);
1959                         }
1960                     } else {
1961                         file_taper_result(taper->disk);
1962                     }
1963                 }
1964
1965             }
1966             taper = NULL;
1967
1968             if(taper_ev_read != NULL) {
1969                 event_release(taper_ev_read);
1970                 taper_ev_read = NULL;
1971                 taper_nb_wait_reply = 0;
1972             }
1973             start_degraded_mode(&runq);
1974             tapeq.head = tapeq.tail = NULL;
1975             aclose(taper_fd);
1976
1977             break;
1978
1979         default:
1980             error(_("driver received unexpected token (%s) from taper"),
1981                   cmdstr[cmd]);
1982             /*NOTREACHED*/
1983         }
1984
1985         g_strfreev(result_argv);
1986
1987         if (taper && taper->disk && taper->result != LAST_TOK) {
1988             if (taper->nb_dle >= conf_max_dle_by_volume) {
1989                 taper_cmd(CLOSE_VOLUME, dp, NULL, 0, NULL);
1990             }
1991             if(taper->dumper) {
1992                 if (taper->dumper->result != LAST_TOK) {
1993                     // Dumper already returned it's result
1994                     dumper_taper_result(taper->disk);
1995                 }
1996             } else {
1997                 file_taper_result(taper->disk);
1998             }
1999         }
2000
2001     } while(areads_dataready(taper_fd));
2002     start_some_dumps(&runq);
2003     startaflush();
2004 }
2005
2006
2007 static void
2008 file_taper_result(
2009     disk_t *dp)
2010 {
2011     taper_t *taper;
2012     char *qname = quote_string(dp->name);
2013
2014     taper = sched(dp)->taper;
2015     if (taper->result == DONE) {
2016         update_info_taper(dp, taper->first_label, taper->first_fileno,
2017                           sched(dp)->level);
2018     }
2019
2020     sched(dp)->taper_attempted += 1;
2021
2022     if (taper->input_error) {
2023         g_printf("driver: taper failed %s %s: %s\n",
2024                    dp->host->hostname, qname, taper->input_error);
2025         if (strcmp(sched(dp)->datestamp, driver_timestamp) == 0) {
2026             if(sched(dp)->taper_attempted >= 2) {
2027                 log_add(L_FAIL, _("%s %s %s %d [too many taper retries after holding disk error: %s]"),
2028                     dp->host->hostname, qname, sched(dp)->datestamp,
2029                     sched(dp)->level, taper->input_error);
2030                 g_printf("driver: taper failed %s %s, too many taper retry after holding disk error\n",
2031                    dp->host->hostname, qname);
2032                 amfree(sched(dp)->destname);
2033                 amfree(sched(dp)->dumpdate);
2034                 amfree(sched(dp)->degr_dumpdate);
2035                 amfree(sched(dp)->degr_mesg);
2036                 amfree(sched(dp)->datestamp);
2037                 amfree(dp->up);
2038             } else {
2039                 log_add(L_INFO, _("%s %s %s %d [Will retry dump because of holding disk error: %s]"),
2040                         dp->host->hostname, qname, sched(dp)->datestamp,
2041                         sched(dp)->level, taper->input_error);
2042                 g_printf("driver: taper will retry %s %s because of holding disk error\n",
2043                         dp->host->hostname, qname);
2044                 if (dp->to_holdingdisk != HOLD_REQUIRED) {
2045                     dp->to_holdingdisk = HOLD_NEVER;
2046                     sched(dp)->dump_attempted -= 1;
2047                     headqueue_disk(&directq, dp);
2048                 } else {
2049                     amfree(sched(dp)->destname);
2050                     amfree(sched(dp)->dumpdate);
2051                     amfree(sched(dp)->degr_dumpdate);
2052                     amfree(sched(dp)->degr_mesg);
2053                     amfree(sched(dp)->datestamp);
2054                     amfree(dp->up);
2055                 }
2056             }
2057         } else {
2058             amfree(sched(dp)->destname);
2059             amfree(sched(dp)->dumpdate);
2060             amfree(sched(dp)->degr_dumpdate);
2061             amfree(sched(dp)->degr_mesg);
2062             amfree(sched(dp)->datestamp);
2063             amfree(dp->up);
2064         }
2065     } else if (taper->tape_error) {
2066         g_printf("driver: taper failed %s %s with tape error: %s\n",
2067                    dp->host->hostname, qname, taper->tape_error);
2068         if(sched(dp)->taper_attempted >= 2) {
2069             log_add(L_FAIL, _("%s %s %s %d [too many taper retries]"),
2070                     dp->host->hostname, qname, sched(dp)->datestamp,
2071                     sched(dp)->level);
2072             g_printf("driver: taper failed %s %s, too many taper retry\n",
2073                    dp->host->hostname, qname);
2074             amfree(sched(dp)->destname);
2075             amfree(sched(dp)->dumpdate);
2076             amfree(sched(dp)->degr_dumpdate);
2077             amfree(sched(dp)->degr_mesg);
2078             amfree(sched(dp)->datestamp);
2079             amfree(dp->up);
2080         } else {
2081             g_printf("driver: taper will retry %s %s\n",
2082                    dp->host->hostname, qname);
2083             /* Re-insert into taper queue. */
2084             headqueue_disk(&tapeq, dp);
2085         }
2086     } else if (taper->result != DONE) {
2087         g_printf("driver: taper failed %s %s without error\n",
2088                    dp->host->hostname, qname);
2089     } else {
2090         delete_diskspace(dp);
2091         amfree(sched(dp)->destname);
2092         amfree(sched(dp)->dumpdate);
2093         amfree(sched(dp)->degr_dumpdate);
2094         amfree(sched(dp)->degr_mesg);
2095         amfree(sched(dp)->datestamp);
2096         amfree(dp->up);
2097     }
2098
2099     amfree(qname);
2100
2101     taper->state &= ~TAPER_STATE_FILE_TO_TAPE;
2102     taper->state |= TAPER_STATE_IDLE;
2103     amfree(taper->input_error);
2104     amfree(taper->tape_error);
2105     taper->disk = NULL;
2106     taper_nb_wait_reply--;
2107     if (taper_nb_wait_reply == 0) {
2108         event_release(taper_ev_read);
2109         taper_ev_read = NULL;
2110     }
2111
2112     /* continue with those dumps waiting for diskspace */
2113     continue_port_dumps();
2114     start_some_dumps(&runq);
2115     startaflush();
2116 }
2117
2118 static void
2119 dumper_taper_result(
2120     disk_t *dp)
2121 {
2122     dumper_t *dumper;
2123     taper_t  *taper;
2124     char *qname;
2125
2126     dumper = sched(dp)->dumper;
2127     taper  = sched(dp)->taper;
2128
2129     free_serial_dp(dp);
2130     if(dumper->result == DONE && taper->result == DONE) {
2131         update_info_dumper(dp, sched(dp)->origsize,
2132                            sched(dp)->dumpsize, sched(dp)->dumptime);
2133         update_info_taper(dp, taper->first_label, taper->first_fileno,
2134                           sched(dp)->level);
2135         qname = quote_string(dp->name); /*quote to take care of spaces*/
2136
2137         log_add(L_STATS, _("estimate %s %s %s %d [sec %ld nkb %lld ckb %lld kps %lu]"),
2138                 dp->host->hostname, qname, sched(dp)->datestamp,
2139                 sched(dp)->level,
2140                 sched(dp)->est_time, (long long)sched(dp)->est_nsize,
2141                 (long long)sched(dp)->est_csize,
2142                 sched(dp)->est_kps);
2143         amfree(qname);
2144     } else {
2145         update_failed_dump(dp);
2146     }
2147
2148     sched(dp)->dump_attempted += 1;
2149     sched(dp)->taper_attempted += 1;
2150
2151     if((dumper->result != DONE || taper->result != DONE) &&
2152         sched(dp)->dump_attempted <= 1 &&
2153         sched(dp)->taper_attempted <= 1) {
2154         enqueue_disk(&directq, dp);
2155     }
2156
2157     if(dumper->ev_read != NULL) {
2158         event_release(dumper->ev_read);
2159         dumper->ev_read = NULL;
2160     }
2161     taper_nb_wait_reply--;
2162     if (taper_nb_wait_reply == 0 && taper_ev_read != NULL) {
2163         event_release(taper_ev_read);
2164         taper_ev_read = NULL;
2165     }
2166     taper->state &= ~TAPER_STATE_DUMP_TO_TAPE;
2167     taper->state |= TAPER_STATE_IDLE;
2168     amfree(taper->input_error);
2169     amfree(taper->tape_error);
2170     dumper->busy = 0;
2171     dp->host->inprogress -= 1;
2172     dp->inprogress = 0;
2173     deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
2174     taper->dumper = NULL;
2175     taper->disk = NULL;
2176     sched(dp)->dumper = NULL;
2177     sched(dp)->taper = NULL;
2178     start_some_dumps(&runq);
2179 }
2180
2181
2182 static taper_t *
2183 idle_taper(void)
2184 {
2185     taper_t *taper;
2186
2187     /* Use an already started taper first */
2188     for (taper = tapetable; taper < tapetable + conf_taper_parallel_write;
2189                             taper++) {
2190         if ((taper->state & TAPER_STATE_IDLE) &&
2191             (taper->state & TAPER_STATE_TAPE_STARTED) &&
2192             !(taper->state & TAPER_STATE_DONE) &&
2193             !(taper->state & TAPER_STATE_FILE_TO_TAPE) &&
2194             !(taper->state & TAPER_STATE_FILE_TO_TAPE))
2195             return taper;
2196     }
2197     for (taper = tapetable; taper < tapetable + conf_taper_parallel_write;
2198                             taper++) {
2199         if ((taper->state & TAPER_STATE_IDLE) &&
2200             (taper->state & TAPER_STATE_RESERVATION) &&
2201             !(taper->state & TAPER_STATE_DONE) &&
2202             !(taper->state & TAPER_STATE_FILE_TO_TAPE) &&
2203             !(taper->state & TAPER_STATE_FILE_TO_TAPE))
2204             return taper;
2205     }
2206     return NULL;
2207 }
2208
2209 static taper_t *
2210 taper_from_name(
2211     char *name)
2212 {
2213     taper_t *taper;
2214
2215     for (taper = tapetable; taper < tapetable+conf_taper_parallel_write;
2216                             taper++)
2217         if (strcmp(taper->name, name) == 0) return taper;
2218
2219     return NULL;
2220 }
2221
2222 static void
2223 dumper_chunker_result(
2224     disk_t *    dp)
2225 {
2226     dumper_t *dumper;
2227     chunker_t *chunker;
2228     assignedhd_t **h=NULL;
2229     int activehd, i;
2230     off_t dummy;
2231     off_t size;
2232     int is_partial;
2233     char *qname;
2234
2235     dumper = sched(dp)->dumper;
2236     chunker = dumper->chunker;
2237
2238     free_serial_dp(dp);
2239
2240     h = sched(dp)->holdp;
2241     activehd = sched(dp)->activehd;
2242
2243     if(dumper->result == DONE && chunker->result == DONE) {
2244         update_info_dumper(dp, sched(dp)->origsize,
2245                            sched(dp)->dumpsize, sched(dp)->dumptime);
2246         qname = quote_string(dp->name);/*quote to take care of spaces*/
2247
2248         log_add(L_STATS, _("estimate %s %s %s %d [sec %ld nkb %lld ckb %lld kps %lu]"),
2249                 dp->host->hostname, qname, sched(dp)->datestamp,
2250                 sched(dp)->level,
2251                 sched(dp)->est_time, (long long)sched(dp)->est_nsize, 
2252                 (long long)sched(dp)->est_csize,
2253                 sched(dp)->est_kps);
2254         amfree(qname);
2255     } else {
2256         update_failed_dump(dp);
2257     }
2258
2259     deallocate_bandwidth(dp->host->netif, sched(dp)->est_kps);
2260
2261     is_partial = dumper->result != DONE || chunker->result != DONE;
2262     rename_tmp_holding(sched(dp)->destname, !is_partial);
2263     holding_set_origsize(sched(dp)->destname, sched(dp)->origsize);
2264
2265     dummy = (off_t)0;
2266     for( i = 0, h = sched(dp)->holdp; i < activehd; i++ ) {
2267         dummy += h[i]->used;
2268     }
2269
2270     size = holding_file_size(sched(dp)->destname, 0);
2271     h[activehd]->used = size - dummy;
2272     h[activehd]->disk->allocated_dumpers--;
2273     adjust_diskspace(dp, DONE);
2274
2275     sched(dp)->dump_attempted += 1;
2276
2277     if((dumper->result != DONE || chunker->result != DONE) &&
2278        sched(dp)->dump_attempted <= 1) {
2279         delete_diskspace(dp);
2280         if (sched(dp)->no_space) {
2281             enqueue_disk(&directq, dp);
2282         } else {
2283             enqueue_disk(&runq, dp);
2284         }
2285     }
2286     else if(size > (off_t)DISK_BLOCK_KB) {
2287         enqueue_disk(&tapeq, dp);
2288     }
2289     else {
2290         delete_diskspace(dp);
2291     }
2292
2293     dumper->busy = 0;
2294     dp->host->inprogress -= 1;
2295     dp->inprogress = 0;
2296
2297     waitpid(chunker->pid, NULL, 0 );
2298     aclose(chunker->fd);
2299     chunker->fd = -1;
2300     chunker->down = 1;
2301
2302     dp = NULL;
2303     if (chunker->result == ABORT_FINISHED)
2304         pending_aborts--;
2305     continue_port_dumps();
2306     /*
2307      * Wakeup any dumpers that are sleeping because of network
2308      * or disk constraints.
2309      */
2310     start_some_dumps(&runq);
2311     startaflush();
2312 }
2313
2314
2315 static void
2316 handle_dumper_result(
2317         void * cookie)
2318 {
2319     /* uses global pending_aborts */
2320     dumper_t *dumper = cookie;
2321     taper_t  *taper;
2322     disk_t *dp, *sdp, *dp1;
2323     cmd_t cmd;
2324     int result_argc;
2325     char *qname;
2326     char **result_argv;
2327
2328     assert(dumper != NULL);
2329     dp = dumper->dp;
2330     assert(dp != NULL);
2331     assert(sched(dp) != NULL);
2332     do {
2333
2334         short_dump_state();
2335
2336         cmd = getresult(dumper->fd, 1, &result_argc, &result_argv);
2337
2338         if(cmd != BOGUS) {
2339             /* result_argv[1] always contains the serial number */
2340             sdp = serial2disk(result_argv[1]);
2341             if (sdp != dp) {
2342                 error(_("Invalid serial number %s"), result_argv[1]);
2343                 g_assert_not_reached();
2344             }
2345         }
2346
2347         qname = quote_string(dp->name);
2348         switch(cmd) {
2349
2350         case DONE: /* DONE <handle> <origsize> <dumpsize> <dumptime> <errstr> */
2351             if(result_argc != 6) {
2352                 error(_("error [dumper DONE result_argc != 6: %d]"), result_argc);
2353                 /*NOTREACHED*/
2354             }
2355
2356             sched(dp)->origsize = OFF_T_ATOI(result_argv[2]);
2357             sched(dp)->dumptime = TIME_T_ATOI(result_argv[4]);
2358
2359             g_printf(_("driver: finished-cmd time %s %s dumped %s:%s\n"),
2360                    walltime_str(curclock()), dumper->name,
2361                    dp->host->hostname, qname);
2362             fflush(stdout);
2363
2364             dumper->result = cmd;
2365
2366             break;
2367
2368         case TRYAGAIN: /* TRY-AGAIN <handle> <errstr> */
2369             /*
2370              * Requeue this disk, and fall through to the FAILED
2371              * case for cleanup.
2372              */
2373             if(sched(dp)->dump_attempted) {
2374                 char *qname = quote_string(dp->name);
2375                 char *qerr = quote_string(result_argv[2]);
2376                 log_add(L_FAIL, _("%s %s %s %d [too many dumper retry: %s]"),
2377                     dp->host->hostname, qname, sched(dp)->datestamp,
2378                     sched(dp)->level, qerr);
2379                 g_printf(_("driver: dump failed %s %s %s, too many dumper retry: %s\n"),
2380                         result_argv[1], dp->host->hostname, qname, qerr);
2381                 amfree(qname);
2382                 amfree(qerr);
2383             }
2384             /* FALLTHROUGH */
2385         case FAILED: /* FAILED <handle> <errstr> */
2386             /*free_serial(result_argv[1]);*/
2387             dumper->result = cmd;
2388             break;
2389
2390         case ABORT_FINISHED: /* ABORT-FINISHED <handle> */
2391             /*
2392              * We sent an ABORT from the NO-ROOM case because this dump
2393              * wasn't going to fit onto the holding disk.  We now need to
2394              * clean up the remains of this image, and try to finish
2395              * other dumps that are waiting on disk space.
2396              */
2397             assert(pending_aborts);
2398             /*free_serial(result_argv[1]);*/
2399             dumper->result = cmd;
2400             break;
2401
2402         case BOGUS:
2403             /* either EOF or garbage from dumper.  Turn it off */
2404             log_add(L_WARNING, _("%s pid %ld is messed up, ignoring it.\n"),
2405                     dumper->name, (long)dumper->pid);
2406             if (dumper->ev_read) {
2407                 event_release(dumper->ev_read);
2408                 dumper->ev_read = NULL;
2409             }
2410             aclose(dumper->fd);
2411             dumper->busy = 0;
2412             dumper->down = 1;   /* mark it down so it isn't used again */
2413
2414             /* if it was dumping something, zap it and try again */
2415             if(sched(dp)->dump_attempted) {
2416                 log_add(L_FAIL, _("%s %s %s %d [%s died]"),
2417                         dp->host->hostname, qname, sched(dp)->datestamp,
2418                         sched(dp)->level, dumper->name);
2419             } else {
2420                 log_add(L_WARNING, _("%s died while dumping %s:%s lev %d."),
2421                         dumper->name, dp->host->hostname, qname,
2422                         sched(dp)->level);
2423             }
2424             dumper->result = cmd;
2425             break;
2426
2427         default:
2428             assert(0);
2429         }
2430         amfree(qname);
2431         g_strfreev(result_argv);
2432
2433         if (cmd != BOGUS) {
2434             int last_dump = 1;
2435             dumper_t *dumper;
2436
2437             run_server_dle_scripts(EXECUTE_ON_POST_DLE_BACKUP,
2438                                get_config_name(), dp, sched(dp)->level);
2439             /* check dump not yet started */
2440             for (dp1=runq.head; dp1 != NULL; dp1 = dp1->next) {
2441                 if (dp1->host == dp->host)
2442                     last_dump = 0;
2443             }
2444             /* check direct to tape dump */
2445             for (dp1=directq.head; dp1 != NULL; dp1 = dp1->next) {
2446                 if (dp1->host == dp->host)
2447                     last_dump = 0;
2448             }
2449             /* check dumping dle */
2450             for (dumper = dmptable; dumper < dmptable + inparallel; dumper++) {
2451                 if (dumper->busy && dumper->dp != dp &&
2452                     dumper->dp->host == dp->host)
2453                  last_dump = 0;
2454             }
2455             if (last_dump && dp->host->post_script == 0) {
2456                 if (dp->host->post_script == 0) {
2457                     run_server_host_scripts(EXECUTE_ON_POST_HOST_BACKUP,
2458                                             get_config_name(), dp->host);
2459                     dp->host->post_script = 1;
2460                 }
2461             }
2462         }
2463
2464         taper = sched(dp)->taper;
2465         /* send the dumper result to the chunker */
2466         if (dumper->chunker) {
2467             if (dumper->chunker->down == 0 && dumper->chunker->fd != -1 &&
2468                 dumper->chunker->result == LAST_TOK) {
2469                 if (cmd == DONE) {
2470                     chunker_cmd(dumper->chunker, DONE, dp, NULL);
2471                 }
2472                 else {
2473                     chunker_cmd(dumper->chunker, FAILED, dp, NULL);
2474                 }
2475             }
2476             if( dumper->result != LAST_TOK &&
2477                 dumper->chunker->result != LAST_TOK)
2478                 dumper_chunker_result(dp);
2479         } else { /* send the dumper result to the taper */
2480             if (cmd == DONE) {
2481                 taper_cmd(DONE, dp, NULL, 0, NULL);
2482             } else {
2483                 taper_cmd(FAILED, dp, NULL, 0, NULL);
2484             }
2485             taper->sendresult = 0;
2486             if (taper->dumper && taper->result != LAST_TOK) {
2487                 dumper_taper_result(dp);
2488             }
2489         }
2490     } while(areads_dataready(dumper->fd));
2491 }
2492
2493
2494 static void
2495 handle_chunker_result(
2496     void *      cookie)
2497 {
2498     chunker_t *chunker = cookie;
2499     assignedhd_t **h=NULL;
2500     dumper_t *dumper;
2501     disk_t *dp, *sdp;
2502     cmd_t cmd;
2503     int result_argc;
2504     char **result_argv;
2505     int dummy;
2506     int activehd = -1;
2507     char *qname;
2508
2509     assert(chunker != NULL);
2510     dumper = chunker->dumper;
2511     assert(dumper != NULL);
2512     dp = dumper->dp;
2513     assert(dp != NULL);
2514     assert(sched(dp) != NULL);
2515     assert(sched(dp)->destname != NULL);
2516     assert(dp != NULL && sched(dp) != NULL && sched(dp)->destname);
2517
2518     if(sched(dp)->holdp) {
2519         h = sched(dp)->holdp;
2520         activehd = sched(dp)->activehd;
2521     }
2522
2523     do {
2524         short_dump_state();
2525
2526         cmd = getresult(chunker->fd, 1, &result_argc, &result_argv);
2527
2528         if(cmd != BOGUS) {
2529             /* result_argv[1] always contains the serial number */
2530             sdp = serial2disk(result_argv[1]);
2531             if (sdp != dp) {
2532                 error(_("Invalid serial number %s"), result_argv[1]);
2533                 g_assert_not_reached();
2534             }
2535         }
2536
2537         switch(cmd) {
2538
2539         case PARTIAL: /* PARTIAL <handle> <dumpsize> <errstr> */
2540         case DONE: /* DONE <handle> <dumpsize> <errstr> */
2541             if(result_argc != 4) {
2542                 error(_("error [chunker %s result_argc != 4: %d]"), cmdstr[cmd],
2543                       result_argc);
2544                 /*NOTREACHED*/
2545             }
2546             /*free_serial(result_argv[1]);*/
2547
2548             sched(dp)->dumpsize = (off_t)atof(result_argv[2]);
2549
2550             qname = quote_string(dp->name);
2551             g_printf(_("driver: finished-cmd time %s %s chunked %s:%s\n"),
2552                    walltime_str(curclock()), chunker->name,
2553                    dp->host->hostname, qname);
2554             fflush(stdout);
2555             amfree(qname);
2556
2557             event_release(chunker->ev_read);
2558
2559             chunker->result = cmd;
2560
2561             break;
2562
2563         case TRYAGAIN: /* TRY-AGAIN <handle> <errstr> */
2564             event_release(chunker->ev_read);
2565
2566             chunker->result = cmd;
2567
2568             break;
2569         case FAILED: /* FAILED <handle> <errstr> */
2570             /*free_serial(result_argv[1]);*/
2571
2572             event_release(chunker->ev_read);
2573
2574             chunker->result = cmd;
2575
2576             break;
2577
2578         case NO_ROOM: /* NO-ROOM <handle> <missing_size> */
2579             if (!h || activehd < 0) { /* should never happen */
2580                 error(_("!h || activehd < 0"));
2581                 /*NOTREACHED*/
2582             }
2583             h[activehd]->used -= OFF_T_ATOI(result_argv[2]);
2584             h[activehd]->reserved -= OFF_T_ATOI(result_argv[2]);
2585             h[activehd]->disk->allocated_space -= OFF_T_ATOI(result_argv[2]);
2586             h[activehd]->disk->disksize -= OFF_T_ATOI(result_argv[2]);
2587             break;
2588
2589         case RQ_MORE_DISK: /* RQ-MORE-DISK <handle> */
2590             if (!h || activehd < 0) { /* should never happen */
2591                 error(_("!h || activehd < 0"));
2592                 /*NOTREACHED*/
2593             }
2594             h[activehd]->disk->allocated_dumpers--;
2595             h[activehd]->used = h[activehd]->reserved;
2596             if( h[++activehd] ) { /* There's still some allocated space left.
2597                                    * Tell the dumper about it. */
2598                 sched(dp)->activehd++;
2599                 chunker_cmd( chunker, CONTINUE, dp, NULL );
2600             } else { /* !h[++activehd] - must allocate more space */
2601                 sched(dp)->act_size = sched(dp)->est_size; /* not quite true */
2602                 sched(dp)->est_size = (sched(dp)->act_size/(off_t)20) * (off_t)21; /* +5% */
2603                 sched(dp)->est_size = am_round(sched(dp)->est_size, (off_t)DISK_BLOCK_KB);
2604                 if (sched(dp)->est_size < sched(dp)->act_size + 2*DISK_BLOCK_KB)
2605                     sched(dp)->est_size += 2 * DISK_BLOCK_KB;
2606                 h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size,
2607                                     &dummy,
2608                                     h[activehd-1] );
2609                 if( !h ) {
2610                     /* No diskspace available. The reason for this will be
2611                      * determined in continue_port_dumps(). */
2612                     enqueue_disk( &roomq, dp );
2613                     continue_port_dumps();
2614                     /* continue flush waiting for new tape */
2615                     startaflush();
2616                 } else {
2617                     /* OK, allocate space for disk and have chunker continue */
2618                     sched(dp)->activehd = assign_holdingdisk( h, dp );
2619                     chunker_cmd( chunker, CONTINUE, dp, NULL );
2620                     amfree(h);
2621                 }
2622             }
2623             break;
2624
2625         case ABORT_FINISHED: /* ABORT-FINISHED <handle> */
2626             /*
2627              * We sent an ABORT from the NO-ROOM case because this dump
2628              * wasn't going to fit onto the holding disk.  We now need to
2629              * clean up the remains of this image, and try to finish
2630              * other dumps that are waiting on disk space.
2631              */
2632             /*assert(pending_aborts);*/
2633
2634             /*free_serial(result_argv[1]);*/
2635
2636             event_release(chunker->ev_read);
2637
2638             chunker->result = cmd;
2639
2640             break;
2641
2642         case BOGUS:
2643             /* either EOF or garbage from chunker.  Turn it off */
2644             log_add(L_WARNING, _("%s pid %ld is messed up, ignoring it.\n"),
2645                     chunker->name, (long)chunker->pid);
2646
2647             /* if it was dumping something, zap it and try again */
2648             g_assert(h && activehd >= 0);
2649             qname = quote_string(dp->name);
2650             if(sched(dp)->dump_attempted) {
2651                 log_add(L_FAIL, _("%s %s %s %d [%s died]"),
2652                         dp->host->hostname, qname, sched(dp)->datestamp,
2653                         sched(dp)->level, chunker->name);
2654             } else {
2655                 log_add(L_WARNING, _("%s died while dumping %s:%s lev %d."),
2656                         chunker->name, dp->host->hostname, qname,
2657                         sched(dp)->level);
2658             }
2659             amfree(qname);
2660             dp = NULL;
2661
2662             event_release(chunker->ev_read);
2663
2664             chunker->result = cmd;
2665
2666             break;
2667
2668         default:
2669             assert(0);
2670         }
2671         g_strfreev(result_argv);
2672
2673         if(chunker->result != LAST_TOK && chunker->dumper->result != LAST_TOK)
2674             dumper_chunker_result(dp);
2675
2676     } while(areads_dataready(chunker->fd));
2677 }
2678
2679
2680 static void
2681 read_flush(
2682     void *      cookie)
2683 {
2684     sched_t *sp;
2685     disk_t *dp;
2686     int line;
2687     char *hostname, *diskname, *datestamp;
2688     int level;
2689     char *destname;
2690     disk_t *dp1;
2691     char *inpline = NULL;
2692     char *command;
2693     char *s;
2694     int ch;
2695     char *qname = NULL;
2696     char *qdestname = NULL;
2697     char *conf_infofile;
2698
2699     (void)cookie;       /* Quiet unused parameter warning */
2700
2701     event_release(flush_ev_read);
2702     flush_ev_read = NULL;
2703
2704     /* read schedule from stdin */
2705     conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));
2706     if (open_infofile(conf_infofile)) {
2707         error(_("could not open info db \"%s\""), conf_infofile);
2708         /*NOTREACHED*/
2709     }
2710     amfree(conf_infofile);
2711
2712     for(line = 0; (inpline = agets(stdin)) != NULL; free(inpline)) {
2713         dumpfile_t file;
2714
2715         line++;
2716         if (inpline[0] == '\0')
2717             continue;
2718
2719         s = inpline;
2720         ch = *s++;
2721
2722         skip_whitespace(s, ch);                 /* find the command */
2723         if(ch == '\0') {
2724             error(_("flush line %d: syntax error (no command)"), line);
2725             /*NOTREACHED*/
2726         }
2727         command = s - 1;
2728         skip_non_whitespace(s, ch);
2729         s[-1] = '\0';
2730
2731         if(strcmp(command,"ENDFLUSH") == 0) {
2732             break;
2733         }
2734
2735         if(strcmp(command,"FLUSH") != 0) {
2736             error(_("flush line %d: syntax error (%s != FLUSH)"), line, command);
2737             /*NOTREACHED*/
2738         }
2739
2740         skip_whitespace(s, ch);                 /* find the hostname */
2741         if(ch == '\0') {
2742             error(_("flush line %d: syntax error (no hostname)"), line);
2743             /*NOTREACHED*/
2744         }
2745         hostname = s - 1;
2746         skip_non_whitespace(s, ch);
2747         s[-1] = '\0';
2748
2749         skip_whitespace(s, ch);                 /* find the diskname */
2750         if(ch == '\0') {
2751             error(_("flush line %d: syntax error (no diskname)"), line);
2752             /*NOTREACHED*/
2753         }
2754         qname = s - 1;
2755         skip_quoted_string(s, ch);
2756         s[-1] = '\0';                           /* terminate the disk name */
2757         diskname = unquote_string(qname);
2758
2759         skip_whitespace(s, ch);                 /* find the datestamp */
2760         if(ch == '\0') {
2761             error(_("flush line %d: syntax error (no datestamp)"), line);
2762             /*NOTREACHED*/
2763         }
2764         datestamp = s - 1;
2765         skip_non_whitespace(s, ch);
2766         s[-1] = '\0';
2767
2768         skip_whitespace(s, ch);                 /* find the level number */
2769         if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
2770             error(_("flush line %d: syntax error (bad level)"), line);
2771             /*NOTREACHED*/
2772         }
2773         skip_integer(s, ch);
2774
2775         skip_whitespace(s, ch);                 /* find the filename */
2776         if(ch == '\0') {
2777             error(_("flush line %d: syntax error (no filename)"), line);
2778             /*NOTREACHED*/
2779         }
2780         qdestname = s - 1;
2781         skip_quoted_string(s, ch);
2782         s[-1] = '\0';
2783         destname = unquote_string(qdestname);
2784
2785         holding_file_get_dumpfile(destname, &file);
2786         if( file.type != F_DUMPFILE) {
2787             if( file.type != F_CONT_DUMPFILE )
2788                 log_add(L_INFO, _("%s: ignoring cruft file."), destname);
2789             amfree(diskname);
2790             amfree(destname);
2791             dumpfile_free_data(&file);
2792             continue;
2793         }
2794
2795         if(strcmp(hostname, file.name) != 0 ||
2796            strcmp(diskname, file.disk) != 0 ||
2797            strcmp(datestamp, file.datestamp) != 0) {
2798             log_add(L_INFO, _("disk %s:%s not consistent with file %s"),
2799                     hostname, diskname, destname);
2800             amfree(diskname);
2801             amfree(destname);
2802             dumpfile_free_data(&file);
2803             continue;
2804         }
2805         amfree(diskname);
2806
2807         dp = lookup_disk(file.name, file.disk);
2808
2809         if (dp == NULL) {
2810             log_add(L_INFO, _("%s: disk %s:%s not in database, skipping it."),
2811                     destname, file.name, file.disk);
2812             amfree(destname);
2813             dumpfile_free_data(&file);
2814             continue;
2815         }
2816
2817         if (file.dumplevel < 0 || file.dumplevel > 399) {
2818             log_add(L_INFO, _("%s: ignoring file with bogus dump level %d."),
2819                     destname, file.dumplevel);
2820             amfree(destname);
2821             dumpfile_free_data(&file);
2822             continue;
2823         }
2824
2825         if (holding_file_size(destname,1) <= 0) {
2826             log_add(L_INFO, "%s: removing file with no data.", destname);
2827             holding_file_unlink(destname);
2828             amfree(destname);
2829             dumpfile_free_data(&file);
2830             continue;
2831         }
2832
2833         dp1 = (disk_t *)alloc(SIZEOF(disk_t));
2834         *dp1 = *dp;
2835         dp1->next = dp1->prev = NULL;
2836
2837         /* add it to the flushhost list */
2838         if(!flushhost) {
2839             flushhost = alloc(SIZEOF(am_host_t));
2840             flushhost->next = NULL;
2841             flushhost->hostname = stralloc("FLUSHHOST");
2842             flushhost->up = NULL;
2843             flushhost->features = NULL;
2844         }
2845         dp1->hostnext = flushhost->disks;
2846         flushhost->disks = dp1;
2847
2848         sp = (sched_t *) alloc(SIZEOF(sched_t));
2849         sp->destname = destname;
2850         sp->level = file.dumplevel;
2851         sp->dumpdate = NULL;
2852         sp->degr_dumpdate = NULL;
2853         sp->degr_mesg = NULL;
2854         sp->datestamp = stralloc(file.datestamp);
2855         sp->est_nsize = (off_t)0;
2856         sp->est_csize = (off_t)0;
2857         sp->est_time = 0;
2858         sp->est_kps = 10;
2859         sp->origsize = file.orig_size;
2860         sp->priority = 0;
2861         sp->degr_level = -1;
2862         sp->dump_attempted = 0;
2863         sp->taper_attempted = 0;
2864         sp->act_size = holding_file_size(destname, 0);
2865         sp->holdp = build_diskspace(destname);
2866         if(sp->holdp == NULL) continue;
2867         sp->dumper = NULL;
2868         sp->taper = NULL;
2869         sp->timestamp = (time_t)0;
2870
2871         dp1->up = (char *)sp;
2872
2873         enqueue_disk(&tapeq, dp1);
2874         dumpfile_free_data(&file);
2875     }
2876     amfree(inpline);
2877     close_infofile();
2878
2879     startaflush();
2880     if (!nodump) {
2881         schedule_ev_read = event_register((event_id_t)0, EV_READFD,
2882                                           read_schedule, NULL);
2883     } else {
2884         force_flush = 1;
2885     }
2886 }
2887
2888 static void
2889 read_schedule(
2890     void *      cookie)
2891 {
2892     sched_t *sp;
2893     disk_t *dp;
2894     int level, line, priority;
2895     char *dumpdate, *degr_dumpdate, *degr_mesg;
2896     int degr_level;
2897     time_t time, degr_time;
2898     time_t *time_p = &time;
2899     time_t *degr_time_p = &degr_time;
2900     off_t nsize, csize, degr_nsize, degr_csize;
2901     unsigned long kps, degr_kps;
2902     char *hostname, *features, *diskname, *datestamp, *inpline = NULL;
2903     char *command;
2904     char *s;
2905     int ch;
2906     off_t flush_size = (off_t)0;
2907     char *qname = NULL;
2908     long long time_;
2909     long long nsize_;
2910     long long csize_;
2911     long long degr_nsize_;
2912     long long degr_csize_;
2913     GPtrArray *errarray;
2914
2915     (void)cookie;       /* Quiet unused parameter warning */
2916
2917     event_release(schedule_ev_read);
2918     schedule_ev_read = NULL;
2919
2920     /* read schedule from stdin */
2921
2922     for(line = 0; (inpline = agets(stdin)) != NULL; free(inpline)) {
2923         if (inpline[0] == '\0')
2924             continue;
2925         line++;
2926
2927         s = inpline;
2928         ch = *s++;
2929
2930         skip_whitespace(s, ch);                 /* find the command */
2931         if(ch == '\0') {
2932             error(_("schedule line %d: syntax error (no command)"), line);
2933             /*NOTREACHED*/
2934         }
2935         command = s - 1;
2936         skip_non_whitespace(s, ch);
2937         s[-1] = '\0';
2938
2939         if(strcmp(command,"DUMP") != 0) {
2940             error(_("schedule line %d: syntax error (%s != DUMP)"), line, command);
2941             /*NOTREACHED*/
2942         }
2943
2944         skip_whitespace(s, ch);                 /* find the host name */
2945         if(ch == '\0') {
2946             error(_("schedule line %d: syntax error (no host name)"), line);
2947             /*NOTREACHED*/
2948         }
2949         hostname = s - 1;
2950         skip_non_whitespace(s, ch);
2951         s[-1] = '\0';
2952
2953         skip_whitespace(s, ch);                 /* find the feature list */
2954         if(ch == '\0') {
2955             error(_("schedule line %d: syntax error (no feature list)"), line);
2956             /*NOTREACHED*/
2957         }
2958         features = s - 1;
2959         skip_non_whitespace(s, ch);
2960         s[-1] = '\0';
2961
2962         skip_whitespace(s, ch);                 /* find the disk name */
2963         if(ch == '\0') {
2964             error(_("schedule line %d: syntax error (no disk name)"), line);
2965             /*NOTREACHED*/
2966         }
2967         qname = s - 1;
2968         skip_quoted_string(s, ch);
2969         s[-1] = '\0';                           /* terminate the disk name */
2970         diskname = unquote_string(qname);
2971
2972         skip_whitespace(s, ch);                 /* find the datestamp */
2973         if(ch == '\0') {
2974             error(_("schedule line %d: syntax error (no datestamp)"), line);
2975             /*NOTREACHED*/
2976         }
2977         datestamp = s - 1;
2978         skip_non_whitespace(s, ch);
2979         s[-1] = '\0';
2980
2981         skip_whitespace(s, ch);                 /* find the priority number */
2982         if(ch == '\0' || sscanf(s - 1, "%d", &priority) != 1) {
2983             error(_("schedule line %d: syntax error (bad priority)"), line);
2984             /*NOTREACHED*/
2985         }
2986         skip_integer(s, ch);
2987
2988         skip_whitespace(s, ch);                 /* find the level number */
2989         if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
2990             error(_("schedule line %d: syntax error (bad level)"), line);
2991             /*NOTREACHED*/
2992         }
2993         skip_integer(s, ch);
2994
2995         skip_whitespace(s, ch);                 /* find the dump date */
2996         if(ch == '\0') {
2997             error(_("schedule line %d: syntax error (bad dump date)"), line);
2998             /*NOTREACHED*/
2999         }
3000         dumpdate = s - 1;
3001         skip_non_whitespace(s, ch);
3002         s[-1] = '\0';
3003
3004         skip_whitespace(s, ch);                 /* find the native size */
3005         nsize_ = (off_t)0;
3006         if(ch == '\0' || sscanf(s - 1, "%lld", &nsize_) != 1) {
3007             error(_("schedule line %d: syntax error (bad nsize)"), line);
3008             /*NOTREACHED*/
3009         }
3010         nsize = (off_t)nsize_;
3011         skip_integer(s, ch);
3012
3013         skip_whitespace(s, ch);                 /* find the compressed size */
3014         csize_ = (off_t)0;
3015         if(ch == '\0' || sscanf(s - 1, "%lld", &csize_) != 1) {
3016             error(_("schedule line %d: syntax error (bad csize)"), line);
3017             /*NOTREACHED*/
3018         }
3019         csize = (off_t)csize_;
3020         skip_integer(s, ch);
3021
3022         skip_whitespace(s, ch);                 /* find the time number */
3023         if(ch == '\0' || sscanf(s - 1, "%lld", &time_) != 1) {
3024             error(_("schedule line %d: syntax error (bad estimated time)"), line);
3025             /*NOTREACHED*/
3026         }
3027         *time_p = (time_t)time_;
3028         skip_integer(s, ch);
3029
3030         skip_whitespace(s, ch);                 /* find the kps number */
3031         if(ch == '\0' || sscanf(s - 1, "%lu", &kps) != 1) {
3032             error(_("schedule line %d: syntax error (bad kps)"), line);
3033             continue;
3034         }
3035         skip_integer(s, ch);
3036
3037         degr_dumpdate = NULL;                   /* flag if degr fields found */
3038         skip_whitespace(s, ch);                 /* find the degr level number */
3039         degr_mesg = NULL;
3040         if (ch == '"') {
3041             qname = s - 1;
3042             skip_quoted_string(s, ch);
3043             s[-1] = '\0';                       /* terminate degr mesg */
3044             degr_mesg = unquote_string(qname);
3045             degr_level = -1;
3046             degr_nsize = (off_t)0;
3047             degr_csize = (off_t)0;
3048             degr_time = (time_t)0;
3049             degr_kps = 0;
3050         } else if (ch != '\0') {
3051             if(sscanf(s - 1, "%d", &degr_level) != 1) {
3052                 error(_("schedule line %d: syntax error (bad degr level)"), line);
3053                 /*NOTREACHED*/
3054             }
3055             skip_integer(s, ch);
3056
3057             skip_whitespace(s, ch);             /* find the degr dump date */
3058             if(ch == '\0') {
3059                 error(_("schedule line %d: syntax error (bad degr dump date)"), line);
3060                 /*NOTREACHED*/
3061             }
3062             degr_dumpdate = s - 1;
3063             skip_non_whitespace(s, ch);
3064             s[-1] = '\0';
3065
3066             skip_whitespace(s, ch);             /* find the degr native size */
3067             degr_nsize_ = (off_t)0;
3068             if(ch == '\0'  || sscanf(s - 1, "%lld", &degr_nsize_) != 1) {
3069                 error(_("schedule line %d: syntax error (bad degr nsize)"), line);
3070                 /*NOTREACHED*/
3071             }
3072             degr_nsize = (off_t)degr_nsize_;
3073             skip_integer(s, ch);
3074
3075             skip_whitespace(s, ch);             /* find the degr compressed size */
3076             degr_csize_ = (off_t)0;
3077             if(ch == '\0'  || sscanf(s - 1, "%lld", &degr_csize_) != 1) {
3078                 error(_("schedule line %d: syntax error (bad degr csize)"), line);
3079                 /*NOTREACHED*/
3080             }
3081             degr_csize = (off_t)degr_csize_;
3082             skip_integer(s, ch);
3083
3084             skip_whitespace(s, ch);             /* find the degr time number */
3085             if(ch == '\0' || sscanf(s - 1, "%lld", &time_) != 1) {
3086                 error(_("schedule line %d: syntax error (bad degr estimated time)"), line);
3087                 /*NOTREACHED*/
3088             }
3089             *degr_time_p = (time_t)time_;
3090             skip_integer(s, ch);
3091
3092             skip_whitespace(s, ch);             /* find the degr kps number */
3093             if(ch == '\0' || sscanf(s - 1, "%lu", &degr_kps) != 1) {
3094                 error(_("schedule line %d: syntax error (bad degr kps)"), line);
3095                 /*NOTREACHED*/
3096             }
3097             skip_integer(s, ch);
3098         } else {
3099             error(_("schedule line %d: no degraded estimate or message"), line);
3100         }
3101
3102         dp = lookup_disk(hostname, diskname);
3103         if(dp == NULL) {
3104             log_add(L_WARNING,
3105                     _("schedule line %d: %s:'%s' not in disklist, ignored"),
3106                     line, hostname, qname);
3107             amfree(diskname);
3108             continue;
3109         }
3110
3111         sp = (sched_t *) alloc(SIZEOF(sched_t));
3112         /*@ignore@*/
3113         sp->level = level;
3114         sp->dumpdate = stralloc(dumpdate);
3115         sp->est_nsize = DISK_BLOCK_KB + nsize; /* include header */
3116         sp->est_csize = DISK_BLOCK_KB + csize; /* include header */
3117         /* round estimate to next multiple of DISK_BLOCK_KB */
3118         sp->est_csize = am_round(sp->est_csize, DISK_BLOCK_KB);
3119         sp->est_size = sp->est_csize;
3120         sp->est_time = time;
3121         sp->est_kps = kps;
3122         sp->priority = priority;
3123         sp->datestamp = stralloc(datestamp);
3124
3125         if(degr_dumpdate) {
3126             sp->degr_level = degr_level;
3127             sp->degr_dumpdate = stralloc(degr_dumpdate);
3128             sp->degr_nsize = DISK_BLOCK_KB + degr_nsize;
3129             sp->degr_csize = DISK_BLOCK_KB + degr_csize;
3130             /* round estimate to next multiple of DISK_BLOCK_KB */
3131             sp->degr_csize = am_round(sp->degr_csize, DISK_BLOCK_KB);
3132             sp->degr_time = degr_time;
3133             sp->degr_kps = degr_kps;
3134             sp->degr_mesg = NULL;
3135         } else {
3136             sp->degr_level = -1;
3137             sp->degr_dumpdate = NULL;
3138             sp->degr_mesg = degr_mesg;
3139         }
3140         /*@end@*/
3141
3142         sp->dump_attempted = 0;
3143         sp->taper_attempted = 0;
3144         sp->act_size = 0;
3145         sp->holdp = NULL;
3146         sp->activehd = -1;
3147         sp->dumper = NULL;
3148         sp->taper = NULL;
3149         sp->timestamp = (time_t)0;
3150         sp->destname = NULL;
3151         sp->no_space = 0;
3152
3153         dp->up = (char *) sp;
3154         if(dp->host->features == NULL) {
3155             dp->host->features = am_string_to_feature(features);
3156             if (!dp->host->features) {
3157                 log_add(L_WARNING,
3158                     _("Invalid feature string from client '%s'"),
3159                     features);
3160                 dp->host->features = am_set_default_feature_set();
3161             }
3162         }
3163         remove_disk(&waitq, dp);
3164
3165         errarray = validate_optionstr(dp);
3166         if (errarray->len > 0) {
3167             guint i;
3168             for (i=0; i < errarray->len; i++) {
3169                 log_add(L_FAIL, _("%s %s %s 0 [%s]"),
3170                         dp->host->hostname, qname,
3171                         sp->datestamp,
3172                         (char *)g_ptr_array_index(errarray, i));
3173             }
3174             amfree(qname);
3175         } else {
3176
3177             if (dp->data_path == DATA_PATH_DIRECTTCP &&
3178                 dp->to_holdingdisk == HOLD_AUTO) {
3179                 dp->to_holdingdisk = HOLD_NEVER;
3180             }
3181
3182             if (dp->to_holdingdisk == HOLD_NEVER) {
3183                 enqueue_disk(&directq, dp);
3184             } else {
3185                 enqueue_disk(&runq, dp);
3186             }
3187             flush_size += sp->act_size;
3188         }
3189         amfree(diskname);
3190     }
3191     g_printf(_("driver: flush size %lld\n"), (long long)flush_size);
3192     amfree(inpline);
3193     if(line == 0)
3194         log_add(L_WARNING, _("WARNING: got empty schedule from planner"));
3195     if(need_degraded==1) start_degraded_mode(&runq);
3196     schedule_done = 1;
3197     run_server_global_scripts(EXECUTE_ON_PRE_BACKUP, get_config_name());
3198     if (empty(runq)) force_flush = 1;
3199     start_some_dumps(&runq);
3200     startaflush();
3201 }
3202
3203 static unsigned long
3204 free_kps(
3205     netif_t *ip)
3206 {
3207     unsigned long res;
3208
3209     if (ip == NULL) {
3210         netif_t *p;
3211         unsigned long maxusage=0;
3212         unsigned long curusage=0;
3213         for(p = disklist_netifs(); p != NULL; p = p->next) {
3214             maxusage += interface_get_maxusage(p->config);
3215             curusage += p->curusage;
3216         }
3217         if (maxusage >= curusage)
3218             res = maxusage - curusage;
3219         else
3220             res = 0;
3221 #ifndef __lint
3222     } else {
3223         if ((unsigned long)interface_get_maxusage(ip->config) >= ip->curusage)
3224             res = interface_get_maxusage(ip->config) - ip->curusage;
3225         else
3226             res = 0;
3227 #endif
3228     }
3229
3230     return res;
3231 }
3232
3233 static void
3234 interface_state(
3235     char *time_str)
3236 {
3237     netif_t *ip;
3238
3239     g_printf(_("driver: interface-state time %s"), time_str);
3240
3241     for(ip = disklist_netifs(); ip != NULL; ip = ip->next) {
3242         g_printf(_(" if %s: free %lu"), interface_name(ip->config), free_kps(ip));
3243     }
3244     g_printf("\n");
3245 }
3246
3247 static void
3248 allocate_bandwidth(
3249     netif_t *           ip,
3250     unsigned long       kps)
3251 {
3252     ip->curusage += kps;
3253 }
3254
3255 static void
3256 deallocate_bandwidth(
3257     netif_t *           ip,
3258     unsigned long       kps)
3259 {
3260     assert(kps <= ip->curusage);
3261     ip->curusage -= kps;
3262 }
3263
3264 /* ------------ */
3265 static off_t
3266 free_space(void)
3267 {
3268     holdalloc_t *ha;
3269     off_t total_free;
3270     off_t diff;
3271
3272     total_free = (off_t)0;
3273     for(ha = holdalloc; ha != NULL; ha = ha->next) {
3274         diff = ha->disksize - ha->allocated_space;
3275         if(diff > (off_t)0)
3276             total_free += diff;
3277     }
3278     return total_free;
3279 }
3280
3281 /*
3282  * We return an array of pointers to assignedhd_t. The array contains at
3283  * most one entry per holding disk. The list of pointers is terminated by
3284  * a NULL pointer. Each entry contains a pointer to a holdingdisk and
3285  * how much diskspace to use on that disk. Later on, assign_holdingdisk
3286  * will allocate the given amount of space.
3287  * If there is not enough room on the holdingdisks, NULL is returned.
3288  */
3289
3290 static assignedhd_t **
3291 find_diskspace(
3292     off_t               size,
3293     int *               cur_idle,
3294     assignedhd_t *      pref)
3295 {
3296     assignedhd_t **result = NULL;
3297     holdalloc_t *ha, *minp;
3298     int i=0;
3299     int j, minj;
3300     char *used;
3301     off_t halloc, dalloc, hfree, dfree;
3302
3303     (void)cur_idle;     /* Quiet unused parameter warning */
3304
3305     if (size < 2*DISK_BLOCK_KB)
3306         size = 2*DISK_BLOCK_KB;
3307     size = am_round(size, (off_t)DISK_BLOCK_KB);
3308
3309     hold_debug(1, _("find_diskspace: want %lld K\n"),
3310                    (long long)size);
3311
3312     used = alloc(SIZEOF(*used) * num_holdalloc);/*disks used during this run*/
3313     memset( used, 0, (size_t)num_holdalloc );
3314     result = alloc(SIZEOF(assignedhd_t *) * (num_holdalloc + 1));
3315     result[0] = NULL;
3316
3317     while( i < num_holdalloc && size > (off_t)0 ) {
3318         /* find the holdingdisk with the fewest active dumpers and among
3319          * those the one with the biggest free space
3320          */
3321         minp = NULL; minj = -1;
3322         for(j = 0, ha = holdalloc; ha != NULL; ha = ha->next, j++ ) {
3323             if( pref && pref->disk == ha && !used[j] &&
3324                 ha->allocated_space <= ha->disksize - (off_t)DISK_BLOCK_KB) {
3325                 minp = ha;
3326                 minj = j;
3327                 break;
3328             }
3329             else if( ha->allocated_space <= ha->disksize - (off_t)(2*DISK_BLOCK_KB) &&
3330                 !used[j] &&
3331                 (!minp ||
3332                  ha->allocated_dumpers < minp->allocated_dumpers ||
3333                  (ha->allocated_dumpers == minp->allocated_dumpers &&
3334                   ha->disksize-ha->allocated_space > minp->disksize-minp->allocated_space)) ) {
3335                 minp = ha;
3336                 minj = j;
3337             }
3338         }
3339
3340         pref = NULL;
3341         if( !minp ) { break; } /* all holding disks are full */
3342         used[minj] = 1;
3343
3344         /* hfree = free space on the disk */
3345         hfree = minp->disksize - minp->allocated_space;
3346
3347         /* dfree = free space for data, remove 1 header for each chunksize */
3348         dfree = hfree - (((hfree-(off_t)1)/holdingdisk_get_chunksize(minp->hdisk))+(off_t)1) * (off_t)DISK_BLOCK_KB;
3349
3350         /* dalloc = space I can allocate for data */
3351         dalloc = ( dfree < size ) ? dfree : size;
3352
3353         /* halloc = space to allocate, including 1 header for each chunksize */
3354         halloc = dalloc + (((dalloc-(off_t)1)/holdingdisk_get_chunksize(minp->hdisk))+(off_t)1) * (off_t)DISK_BLOCK_KB;
3355
3356         hold_debug(1, _("find_diskspace: find diskspace: size %lld hf %lld df %lld da %lld ha %lld\n"),
3357                        (long long)size,
3358                        (long long)hfree,
3359                        (long long)dfree,
3360                        (long long)dalloc,
3361                        (long long)halloc);
3362         size -= dalloc;
3363         result[i] = alloc(SIZEOF(assignedhd_t));
3364         result[i]->disk = minp;
3365         result[i]->reserved = halloc;
3366         result[i]->used = (off_t)0;
3367         result[i]->destname = NULL;
3368         result[i+1] = NULL;
3369         i++;
3370     }
3371     amfree(used);
3372
3373     if(size != (off_t)0) { /* not enough space available */
3374         g_printf(_("find diskspace: not enough diskspace. Left with %lld K\n"), (long long)size);
3375         fflush(stdout);
3376         free_assignedhd(result);
3377         result = NULL;
3378     }
3379
3380     if (debug_holding > 1) {
3381         for( i = 0; result && result[i]; i++ ) {
3382             hold_debug(1, _("find_diskspace: find diskspace: selected %s free %lld reserved %lld dumpers %d\n"),
3383                            holdingdisk_get_diskdir(result[i]->disk->hdisk),
3384                            (long long)(result[i]->disk->disksize -
3385                              result[i]->disk->allocated_space),
3386                            (long long)result[i]->reserved,
3387                            result[i]->disk->allocated_dumpers);
3388         }
3389     }
3390
3391     return result;
3392 }
3393
3394 static int
3395 assign_holdingdisk(
3396     assignedhd_t **     holdp,
3397     disk_t *            diskp)
3398 {
3399     int i, j, c, l=0;
3400     off_t size;
3401     char *sfn = sanitise_filename(diskp->name);
3402     char lvl[64];
3403     assignedhd_t **new_holdp;
3404     char *qname;
3405
3406     g_snprintf( lvl, SIZEOF(lvl), "%d", sched(diskp)->level );
3407
3408     size = am_round(sched(diskp)->est_size - sched(diskp)->act_size,
3409                     (off_t)DISK_BLOCK_KB);
3410
3411     for( c = 0; holdp[c]; c++ )
3412         (void)c; /* count number of disks */
3413
3414     /* allocate memory for sched(diskp)->holdp */
3415     for(j = 0; sched(diskp)->holdp && sched(diskp)->holdp[j]; j++)
3416         (void)j;        /* Quiet lint */
3417     new_holdp = (assignedhd_t **)alloc(SIZEOF(assignedhd_t*)*(j+c+1));
3418     if (sched(diskp)->holdp) {
3419         memcpy(new_holdp, sched(diskp)->holdp, j * SIZEOF(*new_holdp));
3420         amfree(sched(diskp)->holdp);
3421     }
3422     sched(diskp)->holdp = new_holdp;
3423     new_holdp = NULL;
3424
3425     i = 0;
3426     if( j > 0 ) { /* This is a request for additional diskspace. See if we can
3427                    * merge assignedhd_t's */
3428         l=j;
3429         if( sched(diskp)->holdp[j-1]->disk == holdp[0]->disk ) { /* Yes! */
3430             sched(diskp)->holdp[j-1]->reserved += holdp[0]->reserved;
3431             holdp[0]->disk->allocated_space += holdp[0]->reserved;
3432             size = (holdp[0]->reserved>size) ? (off_t)0 : size-holdp[0]->reserved;
3433             qname = quote_string(diskp->name);
3434             hold_debug(1, _("assign_holdingdisk: merging holding disk %s to disk %s:%s, add %lld for reserved %lld, left %lld\n"),
3435                            holdingdisk_get_diskdir(
3436                                                sched(diskp)->holdp[j-1]->disk->hdisk),
3437                            diskp->host->hostname, qname,
3438                            (long long)holdp[0]->reserved,
3439                            (long long)sched(diskp)->holdp[j-1]->reserved,
3440                            (long long)size);
3441             i++;
3442             amfree(qname);
3443             amfree(holdp[0]);
3444             l=j-1;
3445         }
3446     }
3447
3448     /* copy assignedhd_s to sched(diskp), adjust allocated_space */
3449     for( ; holdp[i]; i++ ) {
3450         holdp[i]->destname = newvstralloc( holdp[i]->destname,
3451                                            holdingdisk_get_diskdir(holdp[i]->disk->hdisk), "/",
3452                                            hd_driver_timestamp, "/",
3453                                            diskp->host->hostname, ".",
3454                                            sfn, ".",
3455                                            lvl, NULL );
3456         sched(diskp)->holdp[j++] = holdp[i];
3457         holdp[i]->disk->allocated_space += holdp[i]->reserved;
3458         size = (holdp[i]->reserved > size) ? (off_t)0 :
3459                   (size - holdp[i]->reserved);
3460         qname = quote_string(diskp->name);
3461         hold_debug(1,
3462                    _("assign_holdingdisk: %d assigning holding disk %s to disk %s:%s, reserved %lld, left %lld\n"),
3463                     i, holdingdisk_get_diskdir(holdp[i]->disk->hdisk),
3464                     diskp->host->hostname, qname,
3465                     (long long)holdp[i]->reserved,
3466                     (long long)size);
3467         amfree(qname);
3468         holdp[i] = NULL; /* so it doesn't get free()d... */
3469     }
3470     sched(diskp)->holdp[j] = NULL;
3471     amfree(sfn);
3472
3473     return l;
3474 }
3475
3476 static void
3477 adjust_diskspace(
3478     disk_t *    diskp,
3479     cmd_t       cmd)
3480 {
3481     assignedhd_t **holdp;
3482     off_t total = (off_t)0;
3483     off_t diff;
3484     int i;
3485     char *qname, *hqname, *qdest;
3486
3487     (void)cmd;  /* Quiet unused parameter warning */
3488
3489     qname = quote_string(diskp->name);
3490     qdest = quote_string(sched(diskp)->destname);
3491     hold_debug(1, _("adjust_diskspace: %s:%s %s\n"),
3492                    diskp->host->hostname, qname, qdest);
3493
3494     holdp = sched(diskp)->holdp;
3495
3496     assert(holdp != NULL);
3497
3498     for( i = 0; holdp[i]; i++ ) { /* for each allocated disk */
3499         diff = holdp[i]->used - holdp[i]->reserved;
3500         total += holdp[i]->used;
3501         holdp[i]->disk->allocated_space += diff;
3502         hqname = quote_string(holdingdisk_name(holdp[i]->disk->hdisk));
3503         hold_debug(1, _("adjust_diskspace: hdisk %s done, reserved %lld used %lld diff %lld alloc %lld dumpers %d\n"),
3504                        holdingdisk_name(holdp[i]->disk->hdisk),
3505                        (long long)holdp[i]->reserved,
3506                        (long long)holdp[i]->used,
3507                        (long long)diff,
3508                        (long long)holdp[i]->disk->allocated_space,
3509                        holdp[i]->disk->allocated_dumpers );
3510         holdp[i]->reserved += diff;
3511         amfree(hqname);
3512     }
3513
3514     sched(diskp)->act_size = total;
3515
3516     hold_debug(1, _("adjust_diskspace: after: disk %s:%s used %lld\n"),
3517                    diskp->host->hostname, qname,
3518                    (long long)sched(diskp)->act_size);
3519     amfree(qdest);
3520     amfree(qname);
3521 }
3522
3523 static void
3524 delete_diskspace(
3525     disk_t *diskp)
3526 {
3527     assignedhd_t **holdp;
3528     int i;
3529
3530     holdp = sched(diskp)->holdp;
3531
3532     assert(holdp != NULL);
3533
3534     for( i = 0; holdp[i]; i++ ) { /* for each disk */
3535         /* find all files of this dump on that disk, and subtract their
3536          * reserved sizes from the disk's allocated space
3537          */
3538         holdp[i]->disk->allocated_space -= holdp[i]->used;
3539     }
3540
3541     holding_file_unlink(holdp[0]->destname);    /* no need for the entire list,
3542                                                  * because holding_file_unlink
3543                                                  * will walk through all files
3544                                                  * using cont_filename */
3545     free_assignedhd(sched(diskp)->holdp);
3546     sched(diskp)->holdp = NULL;
3547     sched(diskp)->act_size = (off_t)0;
3548 }
3549
3550 static assignedhd_t **
3551 build_diskspace(
3552     char *      destname)
3553 {
3554     int i, j;
3555     int fd;
3556     size_t buflen;
3557     char buffer[DISK_BLOCK_BYTES];
3558     dumpfile_t file;
3559     assignedhd_t **result;
3560     holdalloc_t *ha;
3561     off_t *used;
3562     char dirname[1000], *ch;
3563     struct stat finfo;
3564     char *filename = destname;
3565
3566     memset(buffer, 0, sizeof(buffer));
3567     used = alloc(SIZEOF(off_t) * num_holdalloc);
3568     for(i=0;i<num_holdalloc;i++)
3569         used[i] = (off_t)0;
3570     result = alloc(SIZEOF(assignedhd_t *) * (num_holdalloc + 1));
3571     result[0] = NULL;
3572     while(filename != NULL && filename[0] != '\0') {
3573         strncpy(dirname, filename, 999);
3574         dirname[999]='\0';
3575         ch = strrchr(dirname,'/');
3576         if (ch) {
3577             *ch = '\0';
3578             ch = strrchr(dirname,'/');
3579             if (ch) {
3580                 *ch = '\0';
3581             }
3582         }
3583
3584         if (!ch) {
3585             g_fprintf(stderr,_("build_diskspace: bogus filename '%s'\n"), filename);
3586             amfree(used);
3587             amfree(result);
3588             return NULL;
3589         }
3590
3591         for(j = 0, ha = holdalloc; ha != NULL; ha = ha->next, j++ ) {
3592             if(strcmp(dirname, holdingdisk_get_diskdir(ha->hdisk))==0) {
3593                 break;
3594             }
3595         }
3596         if (!ha || j >= num_holdalloc) {
3597             fprintf(stderr,_("build_diskspace: holding disk file '%s' is not in a holding disk directory.\n"), filename);
3598             amfree(used);
3599             amfree(result);
3600             return NULL;
3601         }
3602         if(stat(filename, &finfo) == -1) {
3603             g_fprintf(stderr, _("build_diskspace: can't stat %s: %s\n"),
3604                       filename, strerror(errno));
3605             amfree(used);
3606             amfree(result);
3607             return NULL;
3608         }
3609         used[j] += ((off_t)finfo.st_size+(off_t)1023)/(off_t)1024;
3610         if((fd = open(filename,O_RDONLY)) == -1) {
3611             g_fprintf(stderr,_("build_diskspace: open of %s failed: %s\n"),
3612                     filename, strerror(errno));
3613             amfree(used);
3614             amfree(result);
3615             return NULL;
3616         }
3617         if ((buflen = full_read(fd, buffer, SIZEOF(buffer))) > 0) {;
3618                 parse_file_header(buffer, &file, buflen);
3619         }
3620         close(fd);
3621         filename = file.cont_filename;
3622     }
3623
3624     for(j = 0, i=0, ha = holdalloc; ha != NULL; ha = ha->next, j++ ) {
3625         if(used[j] != (off_t)0) {
3626             result[i] = alloc(SIZEOF(assignedhd_t));
3627             result[i]->disk = ha;
3628             result[i]->reserved = used[j];
3629             result[i]->used = used[j];
3630             result[i]->destname = stralloc(destname);
3631             result[i+1] = NULL;
3632             i++;
3633         }
3634     }
3635
3636     amfree(used);
3637     return result;
3638 }
3639
3640 static void
3641 holdingdisk_state(
3642     char *      time_str)
3643 {
3644     holdalloc_t *ha;
3645     int dsk;
3646     off_t diff;
3647
3648     g_printf(_("driver: hdisk-state time %s"), time_str);
3649
3650     for(ha = holdalloc, dsk = 0; ha != NULL; ha = ha->next, dsk++) {
3651         diff = ha->disksize - ha->allocated_space;
3652         g_printf(_(" hdisk %d: free %lld dumpers %d"), dsk,
3653                (long long)diff, ha->allocated_dumpers);
3654     }
3655     g_printf("\n");
3656 }
3657
3658 static void
3659 update_failed_dump(
3660     disk_t *    dp)
3661 {
3662     time_t save_timestamp = sched(dp)->timestamp;
3663     /* setting timestamp to 0 removes the current level from the
3664      * database, so that we ensure that it will not be bumped to the
3665      * next level on the next run.  If we didn't do this, dumpdates or
3666      * gnutar-lists might have been updated already, and a bumped
3667      * incremental might be created.  */
3668     sched(dp)->timestamp = 0;
3669     update_info_dumper(dp, (off_t)-1, (off_t)-1, (time_t)-1);
3670     sched(dp)->timestamp = save_timestamp;
3671 }
3672
3673 /* ------------------- */
3674
3675 static int
3676 queue_length(
3677     disklist_t  q)
3678 {
3679     disk_t *p;
3680     int len;
3681
3682     for(len = 0, p = q.head; p != NULL; len++, p = p->next)
3683         (void)len;      /* Quiet lint */
3684     return len;
3685 }
3686
3687 static void
3688 short_dump_state(void)
3689 {
3690     int i, nidle;
3691     char *wall_time;
3692
3693     wall_time = walltime_str(curclock());
3694
3695     g_printf(_("driver: state time %s "), wall_time);
3696     g_printf(_("free kps: %lu space: %lld taper: "),
3697            free_kps(NULL),
3698            (long long)free_space());
3699     if(degraded_mode) g_printf(_("DOWN"));
3700     else {
3701         taper_t *taper;
3702         int writing = 0;
3703         for(taper = tapetable; taper < tapetable+conf_taper_parallel_write;
3704                                taper++) {
3705             if (taper->state & TAPER_STATE_DUMP_TO_TAPE ||
3706                 taper->state & TAPER_STATE_FILE_TO_TAPE)
3707                 writing = 1;
3708         }
3709         if(writing)
3710             g_printf(_("writing"));
3711         else
3712             g_printf(_("idle"));
3713     }
3714     nidle = 0;
3715     for(i = 0; i < inparallel; i++) if(!dmptable[i].busy) nidle++;
3716     g_printf(_(" idle-dumpers: %d"), nidle);
3717     g_printf(_(" qlen tapeq: %d"), queue_length(tapeq));
3718     g_printf(_(" runq: %d"), queue_length(runq));
3719     g_printf(_(" roomq: %d"), queue_length(roomq));
3720     g_printf(_(" wakeup: %d"), (int)sleep_time);
3721     g_printf(_(" driver-idle: %s\n"), _(idle_strings[idle_reason]));
3722     interface_state(wall_time);
3723     holdingdisk_state(wall_time);
3724     fflush(stdout);
3725 }
3726
3727 static TapeAction
3728 tape_action(
3729     taper_t  *taper,
3730     char    **why_no_new_tape)
3731 {
3732     TapeAction result = TAPE_ACTION_NO_ACTION;
3733     dumper_t *dumper;
3734     taper_t  *taper1;
3735     disk_t   *dp;
3736     off_t dumpers_size;
3737     off_t runq_size;
3738     off_t directq_size;
3739     off_t tapeq_size;
3740     off_t sched_size;
3741     off_t dump_to_disk_size;
3742     int   dump_to_disk_terminated;
3743     int   nb_taper_active = nb_sent_new_tape;
3744     int   nb_taper_flushing = 0;
3745     int   dle_free = 0;
3746     off_t data_next_tape = 0;
3747     off_t data_free = 0;
3748     off_t data_lost = 0;
3749     off_t data_lost_next_tape = 0;
3750     gboolean allow_size_or_number;
3751
3752     dumpers_size = 0;
3753     for(dumper = dmptable; dumper < (dmptable+inparallel); dumper++) {
3754         if (dumper->busy && !sched(dumper->dp)->taper)
3755             dumpers_size += sched(dumper->dp)->est_size;
3756     }
3757     driver_debug(2, _("dumpers_size: %lld\n"), (long long)dumpers_size);
3758
3759     runq_size = 0;
3760     for(dp = runq.head; dp != NULL; dp = dp->next) {
3761         runq_size += sched(dp)->est_size;
3762     }
3763     driver_debug(2, _("runq_size: %lld\n"), (long long)runq_size);
3764
3765     directq_size = 0;
3766     for(dp = directq.head; dp != NULL; dp = dp->next) {
3767         directq_size += sched(dp)->est_size;
3768     }
3769     driver_debug(2, _("directq_size: %lld\n"), (long long)directq_size);
3770
3771     tapeq_size = directq_size;
3772     for(dp = tapeq.head; dp != NULL; dp = dp->next) {
3773         tapeq_size += sched(dp)->act_size;
3774     }
3775
3776     for (taper1 = tapetable; taper1 < tapetable+conf_taper_parallel_write;
3777          taper1++) {
3778         if (taper1->state & TAPER_STATE_FILE_TO_TAPE ||
3779             taper1->state & TAPER_STATE_DUMP_TO_TAPE) {
3780             nb_taper_flushing++;
3781         }
3782     }
3783
3784     /* Add what is currently written to tape and in the go. */
3785     for (taper1 = tapetable; taper1 < tapetable+conf_taper_parallel_write;
3786          taper1++) {
3787         if (taper1->state & TAPER_STATE_TAPE_STARTED) {
3788             tapeq_size -= taper1->left;
3789             dle_free += (conf_max_dle_by_volume - taper1->nb_dle);
3790         }
3791         if (taper1->disk) {
3792             off_t data_to_go;
3793             if (taper1->dumper) {
3794                 data_to_go = sched(taper1->disk)->est_size - taper1->written;
3795             } else {
3796                 data_to_go = sched(taper1->disk)->act_size - taper1->written;
3797             }
3798             if (data_to_go > taper1->left) {
3799                 data_next_tape += data_to_go - taper1->left;
3800                 data_lost += taper1->written + taper1->left;
3801                 if (taper1->state & TAPER_STATE_TAPE_STARTED) {
3802                     dle_free--;
3803                 } else {
3804                     dle_free += conf_max_dle_by_volume - 2;
3805                 }
3806             } else {
3807                 data_free += taper1->left - data_to_go;
3808             }
3809             tapeq_size += data_to_go;
3810         }
3811     }
3812     data_lost_next_tape = tape_length + data_free - data_next_tape - runq_size - directq_size - tapeq_size;
3813     driver_debug(2, _("dle_free: %d\n"), dle_free);
3814     driver_debug(2, _("data_lost: %lld\n"), (long long)data_lost);
3815     driver_debug(2, _("data_free: %lld\n"), (long long)data_free);
3816     driver_debug(2, _("data_next_tape: %lld\n"), (long long)data_next_tape);
3817     driver_debug(2, _("data_lost_next_tape: %lld\n"), (long long)data_lost_next_tape);
3818 ;
3819     driver_debug(2, _("tapeq_size: %lld\n"), (long long)tapeq_size);
3820
3821     sched_size = runq_size + directq_size + tapeq_size + dumpers_size;
3822     driver_debug(2, _("sched_size: %lld\n"), (long long)sched_size);
3823
3824     dump_to_disk_size = dumpers_size + runq_size + directq_size;
3825     driver_debug(2, _("dump_to_disk_size: %lld\n"), (long long)dump_to_disk_size);
3826
3827     dump_to_disk_terminated = schedule_done && dump_to_disk_size == 0;
3828
3829     for (taper1 = tapetable; taper1 < tapetable + conf_taper_parallel_write;
3830                              taper1++) {
3831         if (taper1->state & TAPER_STATE_TAPE_STARTED) {
3832             nb_taper_active++;
3833         }
3834     }
3835
3836     allow_size_or_number = (flush_threshold_dumped < tapeq_size &&
3837                             flush_threshold_scheduled < sched_size) ||
3838                            (dle_free < (queue_length(runq) +
3839                                         queue_length(directq) +
3840                                         queue_length(tapeq)));
3841     driver_debug(2, "queue_length(runq) %d\n", queue_length(runq));
3842     driver_debug(2, "queue_length(directq) %d\n", queue_length(directq));
3843     driver_debug(2, "queue_length(tapeq) %d\n", queue_length(tapeq));
3844     driver_debug(2, "allow_size_or_number %d\n", allow_size_or_number);
3845
3846     // Changing conditionals can produce a driver hang, take care.
3847     // 
3848     // when to start writting to a new tape
3849     if (taper->state & TAPER_STATE_TAPE_REQUESTED) {
3850         driver_debug(2, "tape_action: TAPER_STATE_TAPE_REQUESTED\n");
3851         if (current_tape >= conf_runtapes && taper_nb_scan_volume == 0 &&
3852             nb_taper_active == 0) {
3853             *why_no_new_tape = g_strdup_printf(_("%d tapes filled; runtapes=%d "
3854                 "does not allow additional tapes"), current_tape, conf_runtapes);
3855             result |= TAPE_ACTION_NO_NEW_TAPE;
3856         } else if (current_tape < conf_runtapes &&
3857                    taper_nb_scan_volume == 0 &&
3858                    (allow_size_or_number ||
3859                     (data_lost > data_lost_next_tape) ||
3860                     nb_taper_active == 0) &&
3861                    (last_started_taper == NULL ||
3862                     last_started_taper == taper)) {
3863             result |= TAPE_ACTION_SCAN;
3864         } else {
3865             result |= TAPE_ACTION_MOVE;
3866         }
3867     } else if ((taper->state & TAPER_STATE_WAIT_FOR_TAPE) &&
3868         ((taper->state & TAPER_STATE_DUMP_TO_TAPE) ||   // for dump to tape
3869          !empty(directq) ||                             // if a dle is waiting for a dump to tape
3870          !empty(roomq) ||                               // holding disk constraint
3871          idle_reason == IDLE_NO_DISKSPACE ||            // holding disk constraint
3872          allow_size_or_number ||
3873          (data_lost > data_lost_next_tape) ||
3874          (taperflush < tapeq_size &&                    // taperflush
3875           (force_flush == 1 ||                          //  if force_flush
3876            dump_to_disk_terminated))                    //  or all dump to disk terminated
3877         )) {
3878         driver_debug(2, "tape_action: TAPER_STATE_WAIT_FOR_TAPE return TAPE_ACTION_NEW_TAPE\n");
3879         result |= TAPE_ACTION_NEW_TAPE;
3880     // when to stop using new tape
3881     } else if ((taper->state & TAPER_STATE_WAIT_FOR_TAPE) &&
3882                (taperflush >= tapeq_size &&             // taperflush criteria
3883                (force_flush == 1 ||                     //  if force_flush
3884                 dump_to_disk_terminated))               //  or all dump to disk
3885               ) {
3886         driver_debug(2, "tape_action: TAPER_STATE_WAIT_FOR_TAPE B\n");
3887         if (nb_taper_active <= 0) {
3888             if (current_tape >= conf_runtapes) {
3889                 *why_no_new_tape = g_strdup_printf(_("%d tapes filled; runtapes=%d "
3890                       "does not allow additional tapes"), current_tape, conf_runtapes);
3891                 driver_debug(2, "tape_action: TAPER_STATE_WAIT_FOR_TAPE return TAPE_ACTION_NO_NEW_TAPE\n");
3892                 result |= TAPE_ACTION_NO_NEW_TAPE;
3893             } else if (dumpers_size <= 0) {
3894                 *why_no_new_tape = _("taperflush criteria not met");
3895                 driver_debug(2, "tape_action: TAPER_STATE_WAIT_FOR_TAPE return TAPE_ACTION_NO_NEW_TAPE\n");
3896                 result |= TAPE_ACTION_NO_NEW_TAPE;
3897             }
3898         }
3899     }
3900
3901     // when to start a flush
3902     if (taper->state & TAPER_STATE_IDLE) {
3903         driver_debug(2, "tape_action: TAPER_STATE_IDLE\n");
3904         if (!degraded_mode && (!empty(tapeq) || !empty(directq)) &&
3905             (taper->state & TAPER_STATE_TAPE_STARTED ||         // tape already started 
3906              !empty(roomq) ||                                   // holding disk constraint
3907              idle_reason == IDLE_NO_DISKSPACE ||                // holding disk constraint
3908              allow_size_or_number ||
3909              (force_flush == 1 && taperflush < tapeq_size))) {  // taperflush if force_flush
3910
3911             if (nb_taper_flushing == 0) {
3912                 result |= TAPE_ACTION_START_A_FLUSH;
3913             } else {
3914                 result |= TAPE_ACTION_START_A_FLUSH_FIT;
3915             }
3916         }
3917     }
3918     return result;
3919 }
3920
3921 static int
3922 no_taper_flushing(void)
3923 {
3924     taper_t *taper;
3925
3926     for (taper = tapetable; taper < tapetable + conf_taper_parallel_write;
3927          taper++) {
3928         if (taper->state & TAPER_STATE_FILE_TO_TAPE)
3929             return 0;
3930     }
3931     return 1;
3932 }
3933
3934 #if 0
3935 static void
3936 dump_state(
3937     const char *str)
3938 {
3939     int i;
3940     disk_t *dp;
3941     char *qname;
3942
3943     g_printf("================\n");
3944     g_printf(_("driver state at time %s: %s\n"), walltime_str(curclock()), str);
3945     g_printf(_("free kps: %lu, space: %lld\n"),
3946            free_kps(NULL),
3947            (long long)free_space());
3948     if(degraded_mode) g_printf(_("taper: DOWN\n"));
3949     else if(taper->status == TAPER_IDLE) g_printf(_("taper: idle\n"));
3950     else g_printf(_("taper: writing %s:%s.%d est size %lld\n"),
3951                 taper->disk->host->hostname, taper->disk->name,
3952                 sched(taper->disk)->level,
3953                 (long long)sched(taper->disk)->est_size);
3954     for(i = 0; i < inparallel; i++) {
3955         dp = dmptable[i].dp;
3956         if(!dmptable[i].busy)
3957           g_printf(_("%s: idle\n"), dmptable[i].name);
3958         else
3959           qname = quote_string(dp->name);
3960           g_printf(_("%s: dumping %s:%s.%d est kps %d size %lld time %lu\n"),
3961                 dmptable[i].name, dp->host->hostname, qname, sched(dp)->level,
3962                 sched(dp)->est_kps, (long long)sched(dp)->est_size, sched(dp)->est_time);
3963           amfree(qname);
3964     }
3965     dump_queue("TAPE", tapeq, 5, stdout);
3966     dump_queue("ROOM", roomq, 5, stdout);
3967     dump_queue("RUN ", runq, 5, stdout);
3968     g_printf("================\n");
3969     fflush(stdout);
3970 }
3971 #endif