ssize_t to;
ssize_t start; // starting position in concatenated file
int fd;
+ int dirty;
};
static struct {
size_t limit;
} overlay;
+static void usage();
+
#define FRAG(m) (overlay.table+m)
#define BEG(m) (FRAG(m)->pos)
#define END(m) (FRAG(m)->pos + FRAG(m)->size)
size -= n;
p += n;
}
+ if ( overlay.source.dirty++ > 1000 ) {
+ fsync( overlay.source.fd );
+ overlay.source.dirty = 0;
+ }
}
static void overlay_save_table(size_t lo,size_t hi) {
size -= n;
p += n;
}
+ if ( overlay.source.dirty++ > 1000 ) {
+ fsync( overlay.source.fd );
+ overlay.source.dirty = 0;
+ }
}
static void overlay_insert(size_t p,off_t pos,size_t size) {
}
static void overlay_mark(off_t pos,size_t size) {
+#if DEBUG
+ fprintf( stderr, "overlay_mark( %ld, %ld )\n", pos, size );
+#endif
+ int deleted = 0;
+ ssize_t q;
ssize_t p = overlay_prior_fragment( pos );
+ // p is the nearest region below pos (or -1)
if ( p >= 0 && pos <= END(p) ) {
- // Merge new marks with fragment p
+ // p overlaps mark region
+ if ( END(p) >= pos + size ) {
+#if DEBUG
+ fprintf( stderr, "overlay size 1( %ld )\n", FRAG(p)->size );
+#endif
+ return; // new mark within existing.
+ }
+ // new mark region extends existing
FRAG(p)->size = pos + size - BEG(p);
- if ( p+1 < overlay.count && BEG(p+1) <= END(p) ) {
- FRAG(p)->size = END(p+1) - BEG(p);
- overlay_delete( p+1 );
- overlay_save_table( p, overlay.count );
- } else {
- overlay_save_table( p, p+1 );
+ q = p+1;
+ while ( q < overlay.count && BEG(q) <= END(p) ) {
+ if ( END(q) > END(p) ) {
+ FRAG(p)->size = END(q) - BEG(p);
+ }
+ overlay_delete( q );
+ deleted++;
}
+ overlay_save_table( p, deleted? overlay.count : q );
+#if DEBUG
+ fprintf( stderr, "overlay size 2( %ld ) deleted %d\n",
+ FRAG(p)->size, deleted );
+#endif
return;
}
- p++; // index of subsequent fragment
- if ( p < overlay.count && BEG(p) < pos + size ) {
- // Merge new marks with pragment p+1
- FRAG(p)->size = END(p) - pos;
- FRAG(p)->pos = pos;
- overlay_save_table( p, p+1 );
- } else {
+ // The region p does not expand into new mark region
+ p++; // subsequent region
+ if ( p >= overlay.count || BEG(p) > pos + size ) {
+ // New mark is separate region at p
overlay_insert( p, pos, size);
+#if DEBUG
+ fprintf( stderr, "overlay size 4( %ld )\n", FRAG(p)->size );
+#endif
overlay_save_table( p, overlay.count );
+ return;
+ }
+ // New marks start before and overlap with the region
+ if ( BEG(p) + FRAG(p)->size < pos + size ) {
+ FRAG(p)->size = size; // new mark covers old region
+ } else {
+ FRAG(p)->size += BEG(p) - pos;
+ }
+ BEG(p) = pos;
+ q = p+1;
+ while ( q < overlay.count && BEG(q) <= END(p) ) {
+ if ( END(q) > END(p) ) {
+ FRAG(p)->size = END(q) - BEG(p);
+ }
+ overlay_delete( q );
+ deleted++;
+ }
+ overlay_save_table( p, deleted? overlay.count : q );
+#if DEBUG
+ fprintf( stderr, "overlay size 4( %ld ) deleted %d\n",
+ FRAG(p)->size, deleted );
+#endif
+}
+
+static void setup_overlay(char *filename) {
+ overlay.source.filename = filename;
+ overlay.source.fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
+ if ( overlay.source.fd < 0 ) {
+ perror( filename );
+ usage();
}
}
return ( s == n ) && *(range+c) == 0;
}
-static void usage();
-
-static void setup_overlay(char *filename) {
- overlay.source.filename = filename;
- overlay.source.fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
- if ( overlay.source.fd < 0 ) {
- perror( filename );
- usage();
- }
-}
-
static int setup_sources(char **argv,int i,int n) {
sources.array = calloc( n, sizeof( struct Source ) );
if ( sources.array == 0 ) {
if ( n > size ) {
n = size;
}
+ if ( sources.array[i].dirty ) {
+ fsync( sources.array[i].fd );
+ sources.array[i].dirty = 0;
+ }
#if DEBUG
fprintf( stderr, " seek fd=%d to %ld\n", sources.array[i].fd, b );
#endif
n, sources.array[i].fd );
#endif
ssize_t r = read( sources.array[i].fd, buf + rr, n );
- if ( overlay.source.filename ) {
- int x = overlay_merge( buf + rr, off + rr, r );
- if ( x ) {
- return x;
- }
- }
#if DEBUG
fprintf( stderr, " got %ld bytes\n", r );
#endif
if ( r == 0 ) {
break;
}
+ if ( overlay.source.filename ) {
+ if ( overlay.source.dirty ) {
+ fsync( overlay.source.fd );
+ overlay.source.dirty = 0;
+ }
+ int x = overlay_merge( buf + rr, off + rr, r );
+ if ( x ) {
+ return x;
+ }
+ }
rr += r;
off += r;
size -= r;
#if DEBUG
fprintf( stderr, "write_block( %ld, ?, %ld )\n", off, size );
#endif
+ if ( overlay.source.filename ) {
+ overlay_mark( off, size ); // Mark region as written
+ }
while ( size > 0 ) {
int index = find_source( off ); // index of source file
if ( index < 0 ) {
return -EIO; // past EOF
}
- struct Source *source;
- if ( overlay.source.filename ) {
- source = &overlay.source;
- overlay_mark( off, size ); // Mark region as written
- } else {
- source = &sources.array[ index ];
- }
+ struct Source *source = overlay.source.filename?
+ &overlay.source : &sources.array[ index ];
off_t from = off - source->start + source->from;
off_t max = source->to - from;
if ( lseek( source->fd, from, SEEK_SET ) < 0 ) {
size -= n;
off += n;
}
+ if ( source->dirty++ >= 1000 ) {
+ fsync( source->fd );
+ source->dirty = 0;
+ }
}
return 0;
}
}
}
+static void fsync_all_dirty() {
+ int i = 0;
+ for ( ; i < sources.count; i++ ) {
+ if ( sources.array[i].dirty ) {
+ fsync( sources.array[i].fd );
+ sources.array[i].dirty = 0;
+ }
+ }
+ if ( overlay.source.filename && overlay.source.dirty ) {
+ fsync( overlay.source.fd );
+ overlay.source.dirty = 0;
+ }
+}
+
static int fusefile_flush(const char *path, struct fuse_file_info *info) {
#if DEBUG
fprintf( stderr, "fusefile_flush( %s )\n", path );
if ( strcmp( path, "/" ) != 0 ) {
return -ENOENT;
}
+ fsync_all_dirty();
return 0;
}
if ( strcmp( path, "/" ) != 0 ) {
return -ENOENT;
}
+ fsync_all_dirty();
return 0;
}