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

Last change on this file since 928 was 928, checked in by Bruno Cornec, 17 years ago

ps (busybox) and ps (system) do not give PID in the same column. Adapted with a global variable.

  • Property svn:keywords set to Id
File size: 7.1 KB
Line 
1/* libmondo-fifo.c
2 $Id: libmondo-fifo.c 928 2006-11-13 09:17:07Z bruno $
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
138extern char *ps_options;
139extern char *ps_proc_id;
140
141/**
142 * @addtogroup fifoGroup
143 * @{
144 */
145/**
146 * Open a pipe to/from @c buffer.
147 * If buffer does not work at all, we use `dd'.
148 * @param device The device to read from/write to.
149 * @param direction @c 'r' (reading) or @c 'w' (writing).
150 * @return A file pointer to/from the @c buffer process.
151 */
152FILE *open_device_via_buffer(char *device, char direction,
153 long internal_tape_block_size)
154{
155 char sz_dir[32];
156 char keych;
157 char *tmp;
158 char *command;
159 FILE *fres;
160 int bufsize; // in megabytes
161 int res;
162 int wise_upper_limit;
163 int wise_lower_limit;
164
165 malloc_string(tmp);
166 malloc_string(command);
167 assert_string_is_neither_NULL_nor_zerolength(device);
168 assert(direction == 'w' || direction == 'r');
169 sprintf(sz_dir, "%c", direction);
170 wise_upper_limit = (am_I_in_disaster_recovery_mode()? 8 : 32);
171 wise_lower_limit = 1; // wise_upper_limit/2 + 1;
172 paranoid_system("sync");
173 for (bufsize = wise_upper_limit, res = -1;
174 res != 0 && bufsize >= wise_lower_limit; bufsize--) {
175 sprintf(tmp,
176 "dd if=/dev/zero bs=1024 count=16k 2> /dev/null | buffer -o /dev/null -s %ld -m %d%c",
177 internal_tape_block_size, bufsize, 'm');
178 res = run_program_and_log_output(tmp, 2);
179 }
180 if (!res) {
181 bufsize++;
182 sprintf(tmp, "Negotiated max buffer of %d MB ", bufsize);
183 log_to_screen(tmp);
184 } else {
185 bufsize = 0;
186 res = 0;
187 log_to_screen
188 ("Cannot negotiate a buffer of ANY size. Using dd instead.");
189 }
190 if (direction == 'r') {
191 keych = 'i';
192 } else {
193 keych = 'o';
194 }
195 if (bufsize) {
196 sprintf(g_sz_call_to_buffer,
197 "buffer -m %d%c -p%d -B -s%ld -%c %s 2>> %s", bufsize, 'm',
198 (direction == 'r') ? 20 : 75, internal_tape_block_size,
199 keych, device, MONDO_LOGFILE);
200 } else {
201 sprintf(g_sz_call_to_buffer, "dd bs=%ld %cf=%s",
202 internal_tape_block_size, keych, device);
203 }
204 log_msg(2, "Calling buffer --- command = '%s'", g_sz_call_to_buffer);
205 fres = popen(g_sz_call_to_buffer, sz_dir);
206 if (fres) {
207 log_msg(2, "Successfully opened ('%c') tape device %s", direction,
208 device);
209 } else {
210 log_msg(2, "Failed to open ('%c') tape device %s", direction,
211 device);
212 }
213 sleep(2);
214 sprintf(tmp, "ps %s | grep \"%s\"", ps_options, g_sz_call_to_buffer);
215 if (run_program_and_log_output(tmp, 2)) {
216 log_msg(2, "Warning - I think I failed to open tape, actually.");
217 }
218 g_tape_buffer_size_MB = bufsize;
219 tmp[30] = '\0';
220 sprintf(command, "ps %s | grep buffer | grep -v grep", ps_options);
221 if (run_program_and_log_output(command, 1)) {
222 fres = NULL;
223 log_to_screen("Failed to open tape streamer. Buffer error.");
224 } else {
225 log_to_screen("Buffer successfully started.");
226 }
227
228 paranoid_free(command);
229 paranoid_free(tmp);
230 return (fres);
231}
232
233
234/**
235 * Kill @c buffer processes.
236 * Only called in mondoarchive
237 */
238void kill_buffer()
239{
240 char *tmp;
241 char *command;
242
243 malloc_string(tmp);
244 malloc_string(command);
245 paranoid_system("sync");
246 sprintf(command,
247 "ps %s | grep -F \"%s\" | grep -Fv grep | awk '{print $2;}' | grep -v PID | head -1", ps_options,
248 g_sz_call_to_buffer);
249 log_msg(2, "kill_buffer() --- command = %s", command);
250 strcpy(tmp, call_program_and_get_last_line_of_output(command));
251 sprintf(command, "kill %s", tmp);
252 log_msg(2, "kill_buffer() --- command = %s", command);
253 if (strlen(tmp) > 0) {
254 run_program_and_log_output(command, TRUE);
255 }
256 paranoid_free(tmp);
257 paranoid_free(command);
258}
259
260
261
262
263
264/**
265 * Handler for SIGPIPE.
266 * @param sig The signal that occurred (hopefully SIGPIPE).
267 */
268void sigpipe_occurred(int sig)
269{
270 g_sigpipe = TRUE;
271}
272
273/* @} - end of fifoGroup */
274
275int
276extract_config_file_from_ramdisk(struct s_bkpinfo *bkpinfo,
277 char *ramdisk_fname,
278 char *output_cfg_file,
279 char *output_mountlist_file);
Note: See TracBrowser for help on using the repository browser.