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

Last change on this file since 684 was 681, checked in by andree, 18 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.