root/trunk/client/revimage/compress.c

Revision 197, 8.1 kB (checked in by ludo, 2 years ago)

new client/server protocol for the UI (from r3948)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
Line 
1 /*
2  *  $Id$
3  */
4 /*
5  *  Linbox Rescue Server
6  *  Copyright (C) 2002-2005 Linbox FAS, Free & Alter Soft
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <sys/ioctl.h>
30 #include <linux/fs.h>
31 #include <string.h>
32 #include <time.h>
33
34 #include "compress.h"
35 #include "client.h"
36
37 #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))                 
38 #define UI_READ_ERROR ui_read_error(__FILE__,__LINE__, errno, fi)
39
40 /* Check that off_t can represent 2**63 - 1 correctly.
41      We can't simply define LARGE_OFF_T to be 9223372036854775807,
42      since some C++ compilers masquerading as C compilers
43      incorrectly reject 9223372036854775807.  */
44 /*           
45 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
46                 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];
47 */
48
49 #define BLOCKFLUSH 10
50
51 unsigned long long done, todo;
52  
53 #if 0
54 void setblocksize(FILE *f)
55 {
56     int bs=0, fd;
57    
58     fd = fileno(f);
59     ioctl(fd, BLKBSZGET, &bs);
60     bs = 512;
61     if (ioctl(fd, BLKBSZSET, &bs)) {
62         perror("Could not set block size to 512");
63     }
64     /* ioctl(fd, BLKBSZGET, &bs);
65     printf("Block size= %d\n", bs); */
66
67 }
68
69 #else
70 void setblocksize(int fd)
71 {
72     int bs=0;
73    
74     ioctl(fd, BLKBSZGET, &bs);
75     bs = 512;
76     if (ioctl(fd, BLKBSZSET, &bs)) {
77         perror("Could not set block size to 512");
78     }
79     /* bs = 0;
80     ioctl(fd, BLKBSZGET, &bs);
81     printf("Block size= %d\n", bs); */
82
83 }
84 #endif
85
86
87 /* Fatal error, notify the server about it */
88 void fatal(void)
89 {
90     system("/bin/revosendlog 8");
91 }
92
93 /*
94  * backup read error: disk dead ? out of bounds read ?
95  */
96 void ui_read_error(char *file, int line, int err, int fd)
97 {
98     char sline[32], serrno[32], soffset[32], tmp[256];
99     off64_t offset;
100        
101     sprintf(sline, "%d", line);
102     sprintf(serrno, "%d", err);
103     offset = lseek64(fd, 0, SEEK_CUR);
104     sprintf(soffset, "%llu", (unsigned long long)offset);
105
106     snprintf(tmp, 255,
107              "Hard Disk Read Error ! Bad hard disk or filesystem !\n"
108              "errno %d (%s)\n" " file %s, line %d \n"
109              "offset=%08lx%08lx ", err, strerror(err), file, line,
110              (long) ((long long) offset >> 32), (long) offset);
111     fprintf(stderr, "ERROR: %s\n", tmp);
112        
113     fatal();
114     ui_send("misc_error", 2, "Hard Disc read error", tmp);
115 }
116
117 /*
118  * prints the number of total/used sectors
119  */
120 void print_sect_info(long long unsigned tot_sec, long long unsigned used_sec)
121 {
122     debug("- Total sectors : %llu = %llu MiB\n", tot_sec,  (tot_sec / 2048));
123     debug("- Used sectors  : %llu = %llu MiB (%3.2f%%)\n", used_sec,
124             (used_sec / 2048), 100.0 * (float) used_sec / tot_sec);
125 }
126
127 /*
128  * Compression initialization
129  */
130 void
131 compress_init (COMPRESS ** c, int block, unsigned long long bytes,
132                FILE * index)
133 {
134   FILE *f; 
135  
136   *c = (COMPRESS *) malloc (sizeof (COMPRESS));
137   (*c)->zptr = (z_streamp) malloc (sizeof (z_stream));
138   (*c)->zptr->zalloc = Z_NULL;
139   (*c)->zptr->zfree = Z_NULL;
140
141 //      deflateInit((*c)->zptr,Z_BEST_SPEED);
142   if ((f = fopen("/etc/complevel", "r")) != NULL) {
143     int complevel = 3;
144    
145     fscanf(f, "%d", &complevel);
146     fclose(f);
147     deflateInit ((*c)->zptr, complevel);
148   } else {
149     deflateInit ((*c)->zptr, 3); 
150   }
151
152   (*c)->crc = adler32 (0L, Z_NULL, 0);
153   (*c)->end = 0;
154   (*c)->state = Z_NO_FLUSH;
155
156   (*c)->header = 1;
157   (*c)->block = block;
158   (*c)->offset = 0;
159   (*c)->f = index;
160   (*c)->cbytes = bytes;
161   (*c)->compressed_blocks = BLOCKFLUSH;
162
163   (*c)->zptr->avail_out = OUTBUFF;
164   (*c)->zptr->next_out = (*c)->outbuff;
165 }
166
167 void
168 compress_data (COMPRESS * c, unsigned char *data, int lg, FILE * out,
169                char end)
170 {
171   int ret, lout = c->outbuff - c->zptr->next_out;
172   size_t w;
173   //static int nocomp = 0, slg = 0, sout = 0;
174
175   c->zptr->next_in = data;
176   c->zptr->avail_in = lg;
177
178   c->compressed_blocks++;
179
180   if (c->compressed_blocks >= BLOCKFLUSH)
181     {
182       c->compressed_blocks = 0;
183       c->state = Z_FULL_FLUSH;
184     }
185
186   if (end)
187     c->end = 1;
188
189   if (!c->header)
190     {
191       c->cbytes += lg;
192       done += lg;
193     }
194   c->header = 0;
195
196   do
197     {
198     deflate_again:
199       //printf("Debug : IN : %ld / OUT : %ld\n",c->zptr->avail_in,c->zptr->avail_out);
200       ret = deflate (c->zptr, (end == 0) ? c->state : Z_FINISH);
201
202       if (c->zptr->avail_out == 0)
203         {
204           w = fwrite (c->outbuff, OUTBUFF, 1, out);
205           lout += OUTBUFF;
206           if (w != 1)
207             compress_write_error ();
208           c->crc = adler32 (c->crc, c->outbuff, OUTBUFF);
209           c->zptr->avail_out = OUTBUFF;
210           c->zptr->next_out = c->outbuff;
211           c->offset += OUTBUFF;
212           goto deflate_again;
213         }
214
215       if (c->state != Z_NO_FLUSH)
216         {                       //printf("Debug : %d %d (%d)\n",c->zptr->avail_in,c->zptr->avail_out,ret);
217           if ((c->zptr->avail_in == 0) && (c->zptr->avail_out != 0))
218             {
219               // DEBUG code
220               //fprintf (c->f, "%lld:%d-%ld\n", c->cbytes, c->block,
221               //       c->offset + OUTBUFF - c->zptr->avail_out);
222               c->state = Z_NO_FLUSH;
223             }
224         }
225
226       if (ret == Z_STREAM_END)
227         {
228           w = fwrite (c->outbuff, OUTBUFF - c->zptr->avail_out, 1, out);
229           lout += OUTBUFF - c->zptr->avail_out;
230           if ((w != 1) && (OUTBUFF - c->zptr->avail_out != 0))
231             compress_write_error ();
232           c->crc = adler32 (c->crc, c->outbuff, OUTBUFF - c->zptr->avail_out);
233           c->zptr->avail_out = OUTBUFF;
234           c->zptr->next_out = c->outbuff;
235           //printf("e");
236           break;
237         }
238
239       if (ret != Z_OK)
240         {
241           printf ("ZLIB error in deflate : %d\n", ret);
242           exit (1);
243         }
244
245     }
246   while ((c->zptr->avail_in) || (end));
247 #if 0
248   lout += c->zptr->next_out - c->outbuff;
249   debug("%d:%d %d %d\n", lg, lout, nocomp, c->zptr->next_out - c->outbuff);
250   if (nocomp <= 0) {
251         debug("comp\n");
252         deflateParams(c->zptr, 3, Z_DEFAULT_STRATEGY);
253         nocomp = 6;
254         slg = sout = 0;
255   } else {
256         if (sout > slg && nocomp != 5) {
257                 debug("no comp\n");
258                 deflateParams(c->zptr, 0, Z_DEFAULT_STRATEGY);
259         }
260   }
261   nocomp--;
262   slg += lg;
263   sout += lout;
264 #endif
265 }
266
267 unsigned long long
268 compress_end (COMPRESS * c, FILE * out)
269 {
270   unsigned long long ret;
271
272   if ((c->zptr->avail_out != OUTBUFF) || (!c->end))
273     {                           //printf("-");
274       compress_data (c, NULL, 0, out, 1);
275     }
276
277   deflateEnd (c->zptr);
278   free (c->zptr);
279 //  {
280 //    FILE *flog;
281 //    flog = fopen ("/tmp/crc", "a+");
282 //    fprintf (flog, "%d:%lx", c->block, c->crc);
283 //    fclose (flog);
284 //  }
285   ret = c->cbytes;
286   free (c);
287
288   return ret;
289 }
290
291 /* Write error */
292 void
293 compress_write_error (void)
294 {
295   fatal();
296   fprintf(stderr, "ERROR: Write error ! Server's disk might be full.\n");
297   ui_send("backup_write_error", 0);
298   exit(EXIT_FAILURE);
299 }
300
301 /*
302  * main compression loop
303  */
304 void
305 compress_volume (int fi, unsigned char *nameprefix, PARAMS * p, char *info)
306 {
307   int i, j, k, nb;
308   IMAGE_HEADER header;
309   COMPRESS *c;
310   unsigned char buffer[TOTALLG], *ptr, *dataptr;
311   unsigned long remaining, used, skip;
312   unsigned long long bytes = 0;
313   unsigned short lg, datalg;
314   FILE *fo, *fs, *index;
315   char filename[128], firststring[200], *filestring, *sec,
316     line[400], empty[] = "", numline[8];
317   time_t start, now;
318  
319   setblocksize(fi);
320
321   //debug("- Bitmap lg    : %ld\n",p->bitmaplg);
322   nb = ((p->bitmaplg + ALLOCLG - 1) / ALLOCLG);
323   //debug("- Nb of blocks : %d\n",nb);
324
325   remaining = p->bitmaplg;
326   ptr = p->bitmap;
327
328   skip = 0;
329
330   sprintf (firststring, "SECTORS=%llu|BLOCKS=%d|%s", p->nb_sect, nb, info);
331
332   sprintf (filename, "%sidx", nameprefix);
333   index = fopen (filename, "w");
334
335   start = time(NULL);
336  
337 #include "compress-loop.h"
338
339   now = time(NULL);
340   fclose (index);
341    
342   sec = ui_send("close", 0);
343   debug("- saved in %d seconds\n", (int)difftime(now, start));
344 }
Note: See TracBrowser for help on using the browser.