root/morphix/trunk/mini_fo/sca_aux.c

Revision 2, 7.4 kB (checked in by nextime, 2 years ago)

Initial import, branching from morphix svn

Line 
1 /*
2  * Copyright (c) 1997-2004 Erez Zadok <ezk@cs.stonybrook.edu>
3  * Copyright (c) 2001-2004 Stony Brook University
4  *
5  * For specific licensing information, see the COPYING file distributed with
6  * this package, or get one from ftp://ftp.filesystems.org/pub/fistgen/COPYING.
7  *
8  * This Copyright notice must be kept intact and distributed with all
9  * fistgen sources INCLUDING sources generated by fistgen.
10  */
11 /*
12  *  $Id: sca_aux.c 1364 2004-12-04 10:18:10Z alextreme $
13  */
14 #include "sca_aux.h"
15
16 int chunksize = DEFAULT_CHUNK_SZ;  /* Size of an encoded chunk */
17 int do_fast_tails = 0;             /* Use fast tail algorithm */
18
19 int encode_counter = 0;         /* Usage counters */
20 int decode_counter = 0;
21 int write_counter = 0;
22
23
24 int
25 get_page(int gzfd, struct fistfs_header *hdr, int pageno,
26          unsigned char **out, int *outlen)
27 {
28         unsigned char *data = NULL;     /* mmap gzfd */
29         struct stat sb;
30         unsigned char *ptr;
31         int len, rc=0, back;
32
33         if (pageno < 0)
34                 return(-1);
35         if (pageno > hdr->num_pages)
36                 return(-1);
37         if (!(do_fast_tails) && (pageno == hdr->num_pages))
38                 return(-1);
39
40         if ((fstat(gzfd,&sb)) < 0)
41                 return(-1);
42         if ((data = mmap((void *)data,sb.st_size,PROT_READ,
43                          MAP_PRIVATE,gzfd,0)) == NULL) {
44                 return(-1);
45         }
46
47         if (pageno == 0) {
48                 ptr = data;
49                 if (hdr->num_pages == 0) {
50                         len = sb.st_size;       /* Fast-tail append */
51                         rc = 1;
52                 } else {
53                         len = hdr->offsets[0];
54                 }
55         } else {
56                 ptr = &(data[hdr->offsets[pageno-1]]);
57                 if (do_fast_tails && (pageno == hdr->num_pages)) { /* Possible fast tail */
58                         len = sb.st_size - hdr->offsets[pageno - 1];
59                         rc = 1;
60                 } else {
61                         len = hdr->offsets[pageno] - hdr->offsets[pageno-1];
62                 }
63         }
64
65         if (rc) {                         /* Fast tail, already done */
66                 (*out) = (unsigned char *) malloc (len * sizeof(unsigned char));
67                 if ((*out) == NULL) {
68                         perror("malloc");
69                         return(-1);
70                 }
71                 memcpy(*out, ptr, len);
72                 *outlen = len;
73         } else {
74                 if ((rc = sca_decode_page(ptr, len, out, &back)) < 0) {
75                         fprintf(stderr, "sca_decode_page returns %d\n", rc);
76                         return(-1);
77                 }
78                 *outlen = rc;
79         }
80         munmap(data, sb.st_size);
81         return(*outlen);
82 }
83
84
85 int
86 put_page(int gzfd, struct fistfs_header *hdr, int pageno,
87          unsigned char *data, int datalen)
88 {
89         unsigned char *encdata = NULL;  /* The new data to write */
90         unsigned char *tmppage = NULL;  /* Temp page for shifting */
91         int rc, curlen, delta, cnt, enclen, tmp;
92         struct stat sb;
93
94         write_counter++;
95
96         if (fstat(gzfd, &sb) < 0) {
97                 return(-1);
98         }
99
100         if ((datalen < chunksize) &&
101             (pageno == hdr->num_pages) &&
102             (do_fast_tails)) {
103                 /* A fast tail, just write it at the end */
104                 if (pageno > 0) {
105                         cnt = hdr->offsets[hdr->num_pages-1];
106                         hdr->real_size -= (sb.st_size - cnt);
107                         hdr->real_size += datalen;
108                 } else {
109                         hdr->real_size = datalen;
110                         cnt = 0;
111                 }
112                 lseek(gzfd, cnt, SEEK_SET);     /* The beginning is the end */
113                 rc = 0; tmp = 0;
114                 while (tmp < datalen) {
115                         rc = write(gzfd, data, datalen);
116                         if (rc < 0) {
117                                 return(-1);
118                         } else {
119                                 tmp += rc;
120                         }
121                 }
122                 ftruncate(gzfd, cnt+datalen);
123                 return(0);
124         }
125
126         if ((enclen = sca_encode_page(data, datalen, &encdata, &enclen)) < 0) {
127                 return(enclen);
128         }
129
130         if (pageno < hdr->num_pages) { /* Replace an existing page */
131                 if ((tmppage = (unsigned char *) malloc(sizeof(unsigned char) * chunksize))
132                     == NULL) {
133                         return(-1);
134                 }
135
136                 if (pageno == 0) {  /* replace first page */
137                         curlen = hdr->offsets[0];
138                 } else {
139                         curlen = hdr->offsets[pageno] - hdr->offsets[pageno-1];
140                 }
141                 delta = curlen - enclen; /* Positive, it got smaller, shift in from
142                                             here to end by delta bytes.  Negative,
143                                             it got bigger, shift out from end to
144                                             here by delta bytes */
145
146                 /* Update size  */
147                 hdr->real_size -= delta;
148
149                 /* Do shifting as appropriate */
150                 if (delta > 0) {
151                         tmp = lseek(gzfd, hdr->offsets[pageno], SEEK_SET);
152                         while (tmp<sb.st_size) {
153                                 rc = read(gzfd, tmppage, chunksize);
154                                 lseek(gzfd, tmp-delta, SEEK_SET);
155                                 write(gzfd, tmppage, rc);
156                                 tmp += rc;
157                                 lseek(gzfd, tmp, SEEK_SET);
158                         }
159                         ftruncate(gzfd, sb.st_size-delta);
160                 } else if (delta < 0) {
161                         tmp = sb.st_size - hdr->offsets[pageno];
162                         while (tmp > 0) {
163                                 if (tmp > chunksize) {
164                                         lseek(gzfd, hdr->offsets[pageno] + tmp - chunksize, SEEK_SET);
165                                         rc = read(gzfd, tmppage, chunksize);
166                                         lseek(gzfd,hdr->offsets[pageno] + tmp + - chunksize +(-delta),
167                                               SEEK_SET);
168                                         write(gzfd, tmppage, rc);
169                                 } else {
170                                         lseek(gzfd, hdr->offsets[pageno], SEEK_SET);
171                                         rc = read(gzfd, tmppage, tmp);
172                                         lseek(gzfd, hdr->offsets[pageno] + (-delta), SEEK_SET);
173                                         write(gzfd, tmppage, tmp);
174                                 }
175                                 tmp -= chunksize;
176                         }
177                 } /* Else it happens to fit exactly! no shifting necessary! */
178
179                 /* Update index table */
180                 for (tmp=pageno; tmp<hdr->num_pages; tmp++) {
181                         hdr->offsets[tmp] -= delta;
182                 }
183
184                 lseek(gzfd, hdr->offsets[pageno-1], SEEK_SET); /* move to correct offset */
185                 free(tmppage);
186         } else {                        /* Add a new page somewhere later in the file */
187                 delta = pageno - hdr->num_pages;
188
189                 hdr->real_size += datalen;
190
191                 hdr->num_pages += (delta + 1);
192                 if ((hdr->offsets = realloc(hdr->offsets, (hdr->num_pages * sizeof(off_t))))
193                     == NULL) {
194                         return(-1);
195                 }
196
197                 for (; delta>0; delta--) {
198                         /* Insert an empty page and an index entry for same */
199                         fprintf(stderr, "Should insert an empty page here\n");
200                         return(-1);             /* For now */
201                 }
202
203                 if (hdr->num_pages == 1) {
204                         hdr->offsets[pageno] = enclen;
205                         lseek(gzfd, 0, SEEK_SET);
206                 } else {
207                         hdr->offsets[pageno] = enclen + hdr->offsets[pageno-1];
208                         lseek(gzfd, hdr->offsets[pageno-1], SEEK_SET);
209                 }
210         }
211
212         cnt = 0;
213         while (cnt < enclen) {
214                 rc = write(gzfd, encdata, enclen);
215                 if (rc > 0) {
216                         cnt+=rc;
217                 } else {
218                         /* Write error */
219                         return(-1);
220                 }
221         }
222
223         free(encdata);          /* This was malloc'ed for us */
224         return(0);
225 }
226
227
228 int
229 read_idx(char *filename, struct fistfs_header *hdr)
230 {
231         int fd, i;
232
233         if (filename == NULL)
234                 return(-1);
235         if ((fd = open(filename, O_RDONLY)) < 0) {
236                 return(-1);
237         }
238
239         if ((read(fd, &(hdr->num_pages), sizeof(off_t))) < (sizeof(off_t))) {
240                 fprintf(stderr, "Short read from index file!\n");
241                 return(-1);
242         }
243
244         hdr->flags = hdr->num_pages & 0xfff00000;
245         hdr->num_pages &= 0xfffff;
246
247         if ((read(fd, &(hdr->real_size), sizeof(off_t))) < (sizeof(off_t))) {
248                 fprintf(stderr, "Short read from index file!\n");
249                 return(-1);
250         }
251
252         hdr->offsets = (off_t *) malloc(sizeof(off_t) * hdr->num_pages);
253         if (hdr->offsets == NULL) {
254                 return(-1);
255         }
256
257         for (i = 0; i < hdr->num_pages; i++) {
258                 if ((read(fd, &(hdr->offsets[i]), sizeof(off_t))) != (sizeof(off_t))) {
259                         fprintf(stderr, "Short read from index file!\n");
260                         return(-1);
261                 }
262         }
263         close(fd);
264         return(hdr->num_pages);
265 }
266
267
268 int
269 write_idx(char *filename, struct fistfs_header *hdr)
270 {
271         int fd, i;
272
273         if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0)
274                 return(-1);
275
276         if (write(fd, &(hdr->num_pages), sizeof(int)) != (sizeof(int))) {
277                 fprintf(stderr, "Short write to index file!\n");
278                 return(-1);
279         }
280
281         if (write(fd, &(hdr->real_size), sizeof(int)) != (sizeof(int))) {
282                 fprintf(stderr, "Short write to index file!\n");
283                 return(-1);
284         }
285
286         for (i = 0; i < hdr->num_pages; i++) {
287                 if (write(fd, &(hdr->offsets[i]), sizeof(off_t)) != (sizeof(off_t))) {
288                         fprintf(stderr, "Short write to index file!\n");
289                         return(-1);
290                 }
291         }
292
293         close(fd);
294         return(hdr->num_pages);
295 }
296
297 /*
298  * Local variables:
299  * c-basic-offset: 4
300  * End:
301  */
Note: See TracBrowser for help on using the browser.