X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Ffb-file.c;h=30f8eac52e9fcff0751a14326ba024cdfba90e2c;hb=ab3b3f178718c0ae7b5738e987e350537574d2e6;hp=bf5684aff0aeaf284f3166c6c539b7f427de4e07;hpb=53e3a446f4ec3ecdde06c5efc47c633c8c33418a;p=libucw.git diff --git a/lib/fb-file.c b/lib/fb-file.c index bf5684af..30f8eac5 100644 --- a/lib/fb-file.c +++ b/lib/fb-file.c @@ -1,7 +1,7 @@ /* * UCW Library -- Fast Buffered I/O on Files * - * (c) 1997--2004 Martin Mares + * (c) 1997--2007 Martin Mares * (c) 2007 Pavel Charvat * * This software may be freely distributed and used according to the terms @@ -20,7 +20,7 @@ struct fb_file { struct fastbuf fb; int fd; /* File descriptor */ - int is_temp_file; /* 0=normal file, 1=temporary file, delete on close, -1=shared FD */ + int is_temp_file; int keep_back_buf; /* Optimize for backwards reading */ sh_off_t wpos; /* Real file position */ uns wlen; /* Window size */ @@ -38,24 +38,16 @@ bfd_refill(struct fastbuf *f) if (F->wpos <= f->pos) { sh_off_t diff = f->pos - F->wpos; - if (diff > ((sh_off_t)blen << 2)) /* FIXME: Formula for long forward seeks */ + /* Formula for long forward seeks (prefer lseek()) */ + if (diff > ((sh_off_t)blen << 2)) { long_seek: f->bptr = f->buffer + back; f->bstop = f->buffer + blen; goto seek; } - if ((uns)diff < back) /* Reuse part of previous window (also F->wpos == f->pos) */ - { - uns keep = back - (uns)diff; - if (keep >= F->wlen) - back = diff + (keep = F->wlen); - else - memmove(f->buffer, f->buffer + F->wlen - keep, keep); - read_len -= keep; - read_ptr += keep; - } - else /* Short forward seek */ + /* Short forward seek (prefer read() to skip data )*/ + else if ((uns)diff >= back) { uns skip = diff - back; F->wpos += skip; @@ -73,6 +65,17 @@ long_seek: skip -= l; } } + /* Reuse part of the previous window and append new data (also F->wpos == f->pos) */ + else + { + uns keep = back - (uns)diff; + if (keep >= F->wlen) + back = diff + (keep = F->wlen); + else + memmove(f->buffer, f->buffer + F->wlen - keep, keep); + read_len -= keep; + read_ptr += keep; + } f->bptr = f->buffer + back; f->bstop = f->buffer + blen; } @@ -80,13 +83,15 @@ long_seek: else { sh_off_t diff = F->wpos - f->pos; - if (diff > ((sh_off_t)blen << 1)) /* FIXME: Formula for long backwards seeks */ + /* Formula for long backwards seeks (keep smaller backbuffer than for shorter seeks ) */ + if (diff > ((sh_off_t)blen << 1)) { if ((sh_off_t)back > f->pos) back = f->pos; goto long_seek; } - if ((uns)diff <= F->wlen) /* Seek into previous window (for example brewind) */ + /* Seek into previous window (do nothing... for example brewind) */ + else if ((uns)diff <= F->wlen) { f->bstop = f->buffer + F->wlen; f->bptr = f->bstop - diff; @@ -97,20 +102,21 @@ long_seek: if ((sh_off_t)back > f->pos) back = f->pos; f->bptr = f->buffer + back; - read_len = back + diff - F->wlen; - if (F->wlen && read_len < blen) /* Reuse part of previous window */ + read_len = blen; + f->bstop = f->buffer + read_len; + /* Reuse part of previous window */ + if (F->wlen && read_len <= back + diff && read_len > back + diff - F->wlen) { - uns keep = MIN(F->wlen, blen - read_len); - memmove(f->buffer + read_len, f->buffer, keep); - f->bstop = f->buffer + read_len + keep; + uns keep = read_len + F->wlen - back - diff; + memmove(f->buffer + read_len - keep, f->buffer, keep); } - else - f->bstop = f->buffer + (read_len = blen); seek: + /* Do lseek() */ F->wpos = f->pos + (f->buffer - f->bptr); if (sh_seek(F->fd, F->wpos, SEEK_SET) < 0) die("Error seeking %s: %m", f->name); } + /* Read (part of) buffer */ do { int l = read(F->fd, read_ptr, read_len); @@ -141,12 +147,14 @@ eof: static void bfd_spout(struct fastbuf *f) { + /* Do delayed lseek() if needed */ if (FB_FILE(f)->wpos != f->pos && sh_seek(FB_FILE(f)->fd, f->pos, SEEK_SET) < 0) die("Error seeking %s: %m", f->name); int l = f->bptr - f->buffer; byte *c = f->buffer; + /* Write the buffer */ FB_FILE(f)->wpos = (f->pos += l); FB_FILE(f)->wlen = 0; while (l) @@ -163,6 +171,7 @@ bfd_spout(struct fastbuf *f) static int bfd_seek(struct fastbuf *f, sh_off_t pos, int whence) { + /* Delay the seek for the next refill() or spout() call (if whence != SEEK_END). */ sh_off_t l; switch (whence) { @@ -190,35 +199,32 @@ bfd_seek(struct fastbuf *f, sh_off_t pos, int whence) static void bfd_close(struct fastbuf *f) { - switch (FB_FILE(f)->is_temp_file) - { - case 1: - if (unlink(f->name) < 0) - log(L_ERROR, "unlink(%s): %m", f->name); - case 0: - close(FB_FILE(f)->fd); - } + bclose_file_helper(f, FB_FILE(f)->fd, FB_FILE(f)->is_temp_file); xfree(f); } static int bfd_config(struct fastbuf *f, uns item, int value) { + int orig; + switch (item) { case BCONFIG_IS_TEMP_FILE: + orig = FB_FILE(f)->is_temp_file; FB_FILE(f)->is_temp_file = value; - return 0; + return orig; case BCONFIG_KEEP_BACK_BUF: + orig = FB_FILE(f)->keep_back_buf; FB_FILE(f)->keep_back_buf = value; - return 0; + return orig; default: return -1; } } struct fastbuf * -bfdopen_internal(int fd, byte *name, uns buflen) +bfdopen_internal(int fd, const char *name, uns buflen) { ASSERT(buflen); int namelen = strlen(name) + 1; @@ -241,50 +247,27 @@ bfdopen_internal(int fd, byte *name, uns buflen) return f; } -struct fastbuf * -bopen_try(byte *name, uns mode, uns buflen) -{ - return bopen_file_try(name, mode, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen }); -} - -struct fastbuf * -bopen(byte *name, uns mode, uns buflen) -{ - return bopen_file(name, mode, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen }); -} - -struct fastbuf * -bfdopen(int fd, uns buflen) -{ - return bopen_fd(fd, &(struct fb_params){ .type = FB_STD, .buffer_size = buflen }); -} - -struct fastbuf * -bfdopen_shared(int fd, uns buflen) -{ - struct fastbuf *f = bfdopen(fd, buflen); - FB_FILE(f)->is_temp_file = -1; - return f; -} - void bfilesync(struct fastbuf *b) { bflush(b); if (fsync(FB_FILE(b)->fd) < 0) - log(L_ERROR, "fsync(%s) failed: %m", b->name); + msg(L_ERROR, "fsync(%s) failed: %m", b->name); } #ifdef TEST -int main(int argc UNUSED, char **argv UNUSED) +int main(void) { struct fastbuf *f, *t; - - f = bopen("/etc/profile", O_RDONLY, 16); - t = bfdopen(1, 13); - bbcopy(f, t, 100); - printf("%d %d\n", (int)btell(f), (int)btell(t)); + f = bopen_tmp(16); + t = bfdopen_shared(1, 13); + for (uns i = 0; i < 16; i++) + bwrite(f, "", 7); + bprintf(t, "%d\n", (int)btell(f)); + brewind(f); + bbcopy(f, t, ~0U); + bprintf(t, "\n%d %d\n", (int)btell(f), (int)btell(t)); bclose(f); bclose(t); return 0;