source: branches/stable/mondo/mondo/common/libmondo-fifo.c @ 681

Last change on this file since 681 was 681, checked in by andree, 14 years ago

Replaced all occurrences of egrep with 'grep -E' and of fgrep with
'grep -F' in mondo.
egrep and fgrep are usually just script wrappers around grep these
days which means additional overhead compared to calling grep with the
relevant option. Also, it appears that egrep and fgrep have been
deprecated by POSIX some time ago.

  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/* libmondo-fifo.c
2   $Id: libmondo-fifo.c 681 2006-06-25 02:41:57Z andree $
3
4
504/17
6- replaced INTERNAL_TAPE_BLK_SIZE with bkpinfo->internal_tape_block_size
7
804/04/2004
9- ps wax is now ps wwax
10
1109/10/2003
12- p75 is now p80 in outopening tape call
13- negotiate largest buffer possible when opening tape drive
14- fall back to dd if buffer fails
15
1609/09
17- better logging for tape users
18- working on try_hard_to_fwrite(), try_hard_to_fread()
19- replaced internal w/ EXTERNAL 'buffer' exe.
20
2108/30
22- tweaked error msgs in try_hard_to_fwrite()
23
2408/02
25- updated is_incoming_block_valid() to make it
26  return end-of-tape if >300 flotsam blocks
27
2805/02
29- when logging tape errors, don't repeat self
30
3104/24
32- added lots of log_OS_error()'s and assert()'s
33
3404/22
35- copy_file_from_here_to_there() --- added a bit of fault tolerance;
36  if write fails, retry a few times before reporting error
37
3804/07/2003
39- line 866 --- set block_size used by internal buffer to 32768;
40  was INTERNAL_TAPE_BLK_SIZE/2
41
4210/01 - 11/30/2002
43- is_incoming_block_valid() --- always make
44  checksums %65536, just in case int size is
45  odd (GRRR, ArkLinux)
46- disabled rotor-related superfluous warnings
47- added INTERNAL_TAPE_BLK_SIZE
48- do_sem() now returns int explicitly
49- changed internal_block_size
50- some irregularities (e.g. bad 'type'-ing) found by Kylix; fixed by Hugo
51
5209/01 - 09/30
53- change 64k to TAPE_BLOCK_SIZE
54- added internal_block_size; set it to TAPE_BLOCK_SIZE*2
55- if data is flowing FROM tape TO hard disk then set the threshold to 10 (not 75)
56- lots of multitape-related fixes
57- finally caught & fixed the 'won't finish unzipping last bigfile' bug
58- added WIFEXITED() after waitpid(), to improve multi-tape support
59
6008/01 - 08/31
61- trying to catch & stop 'won't finish unzipping last bigfile' bug by
62  changing the copy_file_rom_here_to_there code
63- changed % threshold from 95 back to 75
64- don't insist on full 256K write of last block to tape
65- if >25 secs go by & all data (AFAIK) has been copied thru by FIFO wrapper
66  and g_tape_stream is _still_ not closed then shrug shoulders & pthread_exit
67  anyway...
68- change fprintf()'s to log_it()'s
69- added a header+footer to each block as it is read/written to/from tape
70  by copy_file_from_here_to_there
71- wrote workaround to allow >2GB of archives w/buffering
72- changed % threshold from 75 to 95
73- added calls to set_signals(); 'buffer' was killing mondoarchive as
74  it terminated
75- cleaned up struct-passing, to improve reliability and eliminate
76  some race conditions
77- changed some forks to pthreads
78- added some comments
79- created libfifo{.c,.h,-EXT.h}
80- copied core of 'buffer' here
81- added some other, Mondo-specific functions
82- hacked 'buffer' into user-friendliness
83*/
84
85/**
86 * @file
87 * Functions to handle buffering of tape archives as they are read/written.
88 * This used the external program @c buffer mostly.
89 */
90
91#include <unistd.h>
92#include <stdio.h>
93#include <signal.h>
94#include <fcntl.h>
95#include <stdio.h>
96
97#include <errno.h>
98#include <sys/types.h>
99#include <sys/stat.h>
100#include <sys/ipc.h>
101#include <sys/shm.h>
102#include <sys/sem.h>
103#include <sys/wait.h>
104#include <pthread.h>
105
106#include "my-stuff.h"
107#include "mondostructures.h"
108#include "libmondo.h"
109
110/**
111 * @addtogroup globalGroup
112 * @{
113 */
114/**
115 * The SIGPIPE handler sets this to TRUE.
116 */
117bool g_sigpipe = FALSE;
118
119/**
120 * PID of the "main" process.
121 */
122pid_t g_mastermind_pid = 0;
123
124
125
126/**
127 * Command line with which @c buffer was invoked.
128 */
129char g_sz_call_to_buffer[MAX_STR_LEN];
130
131/**
132 * Size of the buffer used with @c buffer.
133 */
134int g_tape_buffer_size_MB = 0;
135
136/* @} - end of globalGroup */
137
138
139/**
140 * @addtogroup fifoGroup
141 * @{
142 */
143/**
144 * Open a pipe to/from @c buffer.
145 * If buffer does not work at all, we use `dd'.
146 * @param device The device to read from/write to.
147 * @param direction @c 'r' (reading) or @c 'w' (writing).
148 * @return A file pointer to/from the @c buffer process.
149 */
150FILE *open_device_via_buffer(char *device, char direction,
151                             long internal_tape_block_size)
152{
153    char sz_dir[32];
154    char keych;
155    char *tmp;
156    char *command;
157    FILE *fres;
158    int bufsize;                // in megabytes
159    int res;
160    int wise_upper_limit;
161    int wise_lower_limit;
162
163    malloc_string(tmp);
164    malloc_string(command);
165    assert_string_is_neither_NULL_nor_zerolength(device);
166    assert(direction == 'w' || direction == 'r');
167    sprintf(sz_dir, "%c", direction);
168    wise_upper_limit = (am_I_in_disaster_recovery_mode()? 8 : 32);
169    wise_lower_limit = 1;       // wise_upper_limit/2 + 1;
170    paranoid_system("sync");
171    for (bufsize = wise_upper_limit, res = -1;
172         res != 0 && bufsize >= wise_lower_limit; bufsize--) {
173        sprintf(tmp,
174                "dd if=/dev/zero bs=1024 count=16k 2> /dev/null | buffer -o /dev/null -s %ld -m %d%c",
175                internal_tape_block_size, bufsize, 'm');
176        res = run_program_and_log_output(tmp, 2);
177    }
178    if (!res) {
179        bufsize++;
180        sprintf(tmp, "Negotiated max buffer of %d MB ", bufsize);
181        log_to_screen(tmp);
182    } else {
183        bufsize = 0;
184        res = 0;
185        log_to_screen
186            ("Cannot negotiate a buffer of ANY size. Using dd instead.");
187    }
188    if (direction == 'r') {
189        keych = 'i';
190    } else {
191        keych = 'o';
192    }
193    if (bufsize) {
194        sprintf(g_sz_call_to_buffer,
195                "buffer -m %d%c -p%d -B -s%ld -%c %s 2>> %s", bufsize, 'm',
196                (direction == 'r') ? 20 : 75, internal_tape_block_size,
197                keych, device, MONDO_LOGFILE);
198    } else {
199        sprintf(g_sz_call_to_buffer, "dd bs=%ld %cf=%s",
200                internal_tape_block_size, keych, device);
201    }
202    log_msg(2, "Calling buffer --- command = '%s'", g_sz_call_to_buffer);
203    fres = popen(g_sz_call_to_buffer, sz_dir);
204    if (fres) {
205        log_msg(2, "Successfully opened ('%c') tape device %s", direction,
206                device);
207    } else {
208        log_msg(2, "Failed to open ('%c') tape device %s", direction,
209                device);
210    }
211    sleep(2);
212    sprintf(tmp, "ps wwax | grep \"%s\"", g_sz_call_to_buffer);
213    if (run_program_and_log_output(tmp, 2)) {
214        log_msg(2, "Warning - I think I failed to open tape, actually.");
215    }
216    g_tape_buffer_size_MB = bufsize;
217    tmp[30] = '\0';
218    sprintf(command, "ps wwax | grep buffer | grep -v grep");
219    if (run_program_and_log_output(command, 1)) {
220        fres = NULL;
221        log_to_screen("Failed to open tape streamer. Buffer error.");
222    } else {
223        log_to_screen("Buffer successfully started.");
224    }
225
226    paranoid_free(command);
227    paranoid_free(tmp);
228    return (fres);
229}
230
231
232/**
233 * Kill @c buffer processes.
234 */
235void kill_buffer()
236{
237    char *tmp;
238    char *command;
239
240    malloc_string(tmp);
241    malloc_string(command);
242    paranoid_system("sync");
243    sprintf(command,
244            "ps wwax | grep -F \"%s\" | grep -Fv grep | awk '{print $1;}' | grep -v PID | tr -s '\n' ' ' | awk '{ print $1; }'",
245            g_sz_call_to_buffer);
246    log_msg(2, "kill_buffer() --- command = %s", command);
247    strcpy(tmp, call_program_and_get_last_line_of_output(command));
248    sprintf(command, "kill %s", tmp);
249    log_msg(2, "kill_buffer() --- command = %s", command);
250    if (strlen(tmp) > 0) {
251        run_program_and_log_output(command, TRUE);
252    }
253    paranoid_free(tmp);
254    paranoid_free(command);
255}
256
257
258
259
260
261/**
262 * Handler for SIGPIPE.
263 * @param sig The signal that occurred (hopefully SIGPIPE).
264 */
265void sigpipe_occurred(int sig)
266{
267    g_sigpipe = TRUE;
268}
269
270/* @} - end of fifoGroup */
271
272int
273extract_config_file_from_ramdisk(struct s_bkpinfo *bkpinfo,
274                                 char *ramdisk_fname,
275                                 char *output_cfg_file,
276                                 char *output_mountlist_file);
Note: See TracBrowser for help on using the repository browser.