source: MondoRescue/trunk/mondo/src/common/libmondo-fifo.c @ 900

Last change on this file since 900 was 900, checked in by Bruno Cornec, 14 years ago

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1/* $Id: libmondo-fifo.c 900 2006-10-24 06:49:18Z bruno $ */
2
3/**
4 * @file
5 * Functions to handle buffering of tape archives as they are read/written.
6 * This used the external program @c buffer mostly.
7 */
8
9#include <unistd.h>
10#include <stdio.h>
11#ifndef S_SPLINT_S
12#include <signal.h>
13#endif
14#include <fcntl.h>
15
16#include <errno.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/ipc.h>
20#include <sys/shm.h>
21#include <sys/sem.h>
22#include <sys/wait.h>
23#ifndef S_SPLINT_S
24#include <pthread.h>
25#endif
26
27#include "my-stuff.h"
28#include "mondostructures.h"
29#include "libmondo.h"
30#include "mr_mem.h"
31
32/**
33 * @addtogroup globalGroup
34 * @{
35 */
36/**
37 * The SIGPIPE handler sets this to TRUE.
38 */
39bool g_sigpipe = FALSE;
40
41/**
42 * PID of the "main" process.
43 */
44pid_t g_mastermind_pid = 0;
45
46/**
47 * Command line with which @c buffer was invoked.
48 */
49char *g_sz_call_to_buffer;
50
51/**
52 * Size of the buffer used with @c buffer.
53 */
54int g_tape_buffer_size_MB = 0;
55
56/* @} - end of globalGroup */
57
58extern char *ps_options;
59
60/**
61 * @addtogroup fifoGroup
62 * @{
63 */
64/**
65 * Open a pipe to/from @c buffer.
66 * If buffer does not work at all, we use `dd'.
67 * @param device The device to read from/write to.
68 * @param direction @c 'r' (reading) or @c 'w' (writing).
69 * @return A file pointer to/from the @c buffer process.
70 */
71FILE *open_device_via_buffer(char *device, char direction,
72                             long internal_tape_block_size)
73{
74    char *sz_dir;
75    char keych;
76    char *tmp;
77    FILE *fres;
78    int bufsize;                // in megabytes
79    int res;
80    int wise_upper_limit;
81    int wise_lower_limit;
82
83    assert_string_is_neither_NULL_nor_zerolength(device);
84    assert(direction == 'w' || direction == 'r');
85    mr_asprintf(&sz_dir, "%c", direction);
86    wise_upper_limit = (am_I_in_disaster_recovery_mode()? 8 : 32);
87    wise_lower_limit = 1;       // wise_upper_limit/2 + 1;
88    sync();
89    for (bufsize = wise_upper_limit, res = -1;
90         res != 0 && bufsize >= wise_lower_limit; bufsize--) {
91        mr_asprintf(&tmp,
92                 "dd if=/dev/zero bs=1024 count=16k 2> /dev/null | buffer -o /dev/null -s %ld -m %d%c",
93                 internal_tape_block_size, bufsize, 'm');
94        res = run_program_and_log_output(tmp, 2);
95        mr_free(tmp);
96    }
97    if (!res) {
98        bufsize++;
99        mr_asprintf(&tmp, _("Negotiated max buffer of %d MB "), bufsize);
100        log_to_screen(tmp);
101        mr_free(tmp);
102    } else {
103        bufsize = 0;
104        res = 0;
105        log_to_screen
106            (_("Cannot negotiate a buffer of ANY size. Using dd instead."));
107    }
108    if (direction == 'r') {
109        keych = 'i';
110    } else {
111        keych = 'o';
112    }
113    if (bufsize) {
114        mr_asprintf(&g_sz_call_to_buffer,
115                 "buffer -m %d%c -p%d -B -s%ld -%c %s 2>> %s", bufsize,
116                 'm', (direction == 'r') ? 20 : 75,
117                 internal_tape_block_size, keych, device, MONDO_LOGFILE);
118    } else {
119        mr_asprintf(&g_sz_call_to_buffer, "dd bs=%ld %cf=%s",
120                 internal_tape_block_size, keych, device);
121    }
122    log_msg(2, "Calling buffer --- command = '%s'", g_sz_call_to_buffer);
123    fres = popen(g_sz_call_to_buffer, sz_dir);
124    mr_free(sz_dir);
125    if (fres) {
126        log_msg(2, "Successfully opened ('%c') tape device %s", direction,
127                device);
128    } else {
129        log_msg(2, "Failed to open ('%c') tape device %s", direction,
130                device);
131    }
132    sleep(2);
133    mr_asprintf(&tmp, "ps %s | grep \"%s\"", ps_options, g_sz_call_to_buffer);
134    if (run_program_and_log_output(tmp, 2)) {
135        log_msg(2, "Warning - I think I failed to open tape, actually.");
136    }
137    mr_free(tmp);
138    g_tape_buffer_size_MB = bufsize;
139    mr_asprintf(&tmp, "ps %s | grep buffer | grep -v grep", ps_options);
140    if (run_program_and_log_output(tmp, 1)) {
141        fres = NULL;
142        log_to_screen(_("Failed to open tape streamer. Buffer error."));
143    } else {
144        log_to_screen(_("Buffer successfully started."));
145    }
146    mr_free(tmp);
147    return (fres);
148}
149
150
151/**
152 * Kill @c buffer processes.
153 */
154void kill_buffer()
155{
156    char *tmp;
157    char *command;
158
159    sync();
160    mr_asprintf(&command,
161            "ps %s | grep -F \"%s\" | grep -Fv grep | awk '{print $1;}' | grep -v PID | tr -s '\n' ' ' | awk '{ print $1; }'", ps_options,
162            g_sz_call_to_buffer);
163    mr_free(g_sz_call_to_buffer);
164    log_msg(2, "kill_buffer() --- command = %s", command);
165
166    tmp = call_program_and_get_last_line_of_output(command);
167    mr_free(command);
168
169    mr_asprintf(&command, "kill %s", tmp);
170    log_msg(2, "kill_buffer() --- command = %s", command);
171
172    if (strlen(tmp) > 0) {
173        run_program_and_log_output(command, TRUE);
174    }
175    mr_free(tmp);
176    mr_free(command);
177}
178
179
180/**
181 * Handler for SIGPIPE.
182 * @param sig The signal that occurred (hopefully SIGPIPE).
183 */
184void sigpipe_occurred(int sig)
185{
186    g_sigpipe = TRUE;
187}
188
189/* @} - end of fifoGroup */
190
191/* BERLIOS: useless ?
192int
193extract_config_file_from_ramdisk( struct s_bkpinfo *bkpinfo,
194                  char *ramdisk_fname,
195                  char *output_cfg_file,
196                  char *output_mountlist_file);
197*/
Note: See TracBrowser for help on using the repository browser.