AmendHub

Download:

jcs

/

subtext

/

amendments

/

46

bile: More work


jcs made amendment 46 over 2 years ago
--- bile.c Mon Jan 3 22:21:19 2022 +++ bile.c Tue Jan 4 16:30:53 2022 @@ -19,11 +19,12 @@ #include "util.h" void bile_write_map(struct bile *bile); -void bile_sort_objects(struct bile *bile); +void bile_sort_by_pos(struct bile *bile); void bile_free(struct bile *bile, unsigned long id); +size_t bile_xwriteat(struct bile *bile, size_t pos, size_t len, void *data); struct bile * -bile_create(Str255 filename, OSType creator) +bile_create(Str255 filename, OSType creator, OSType type) { struct bile *bile; size_t len; @@ -31,7 +32,7 @@ bile_create(Str255 filename, OSType creator) short error, fh; /* create file */ - error = Create(filename, 0, creator, BILE_FILE_TYPE); + error = Create(filename, 0, creator, type); if (error) panic("bile_create: failed to create %s: %d", PtoCstr(filename), error); @@ -159,22 +160,38 @@ bile_close(struct bile *bile) /* XXX: these become invalid once we re-sort, should we return a copy? */ struct bile_object * -bile_find(struct bile *bile, unsigned long id) +bile_find(struct bile *bile, OSType type, unsigned long id) { struct bile_object *o; unsigned long n; - for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n]; - if (o->id == id) + /* look backwards, optimizing for newer data */ + for (n = bile->nobjects; n > 0; n--) { + o = &bile->map[n - 1]; + if (o->type == type && o->id == id) return o; } return NULL; } +size_t +bile_next_id(struct bile *bile, OSType type) +{ + struct bile_object *o; + size_t n, id = 1; + + for (n = 0; n < bile->nobjects; n++) { + o = &bile->map[n - 1]; + if (o->type == type && o->id >= id) + id = o->id + 1; + } + + return id; +} + struct bile_object * -bile_alloc(struct bile *bile, size_t size) +bile_alloc(struct bile *bile, OSType type, unsigned long id, size_t size) { struct bile_object *new, *o; size_t last_pos = BILE_HEADER_LEN; @@ -194,13 +211,15 @@ bile_alloc(struct bile *bile, size_t size) bile->nobjects++; new->pos = last_pos; new->size = size; - - bile_sort_objects(bile); + new->type = type; + new->id = id; + bile_sort_by_pos(bile); + /* find our new object pointer after sorting */ - for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n]; - if (o->pos == last_pos) + for (n = bile->nobjects; n > 0; n--) { + o = &bile->map[n - 1]; + if (o->type == type && o->pos == last_pos) return o; } @@ -208,12 +227,11 @@ bile_alloc(struct bile *bile, size_t size) } void -bile_sort_objects(struct bile *bile) +bile_sort_by_pos(struct bile *bile) { short i, j; struct bile_object o; - /* sort maps by position */ for (i = 0; i < bile->nobjects; i++) { for (j = 0; j < bile->nobjects - i - 1; j++) { if (bile->map[j].pos > bile->map[j + 1].pos) { @@ -226,18 +244,52 @@ bile_sort_objects(struct bile *bile) } void -bile_free(struct bile *bile, unsigned long id) +bile_delete(struct bile *bile, OSType type, unsigned long id) { - /* TODO */ + struct bile_object *o; + size_t pos, size, wsize; + short error; + char *zero; + + o = bile_find(bile, type, id); + if (o == NULL) + return; + + o->type = BILE_PURGE_TYPE; + pos = o->pos; + size = o->size + BILE_OBJECT_SIZE; + + bile_write_map(bile); + + error = SetFPos(bile->vrefid, fsFromStart, pos); + if (error) + goto write_error; + + zero = xmalloczero(128); + while (size > 0) { + wsize = MIN(128, size); + size -= wsize; + + error = FSWrite(bile->vrefid, &wsize, zero); + if (error) + goto write_error; + } + + return; + +write_error: + panic("bile_delete: failed writing to %s: %d", PtoCstr(bile->filename), + error); } size_t -bile_read(struct bile *bile, unsigned long id, char **data) +bile_read(struct bile *bile, OSType type, unsigned long id, char **data) { - struct bile_object *o = bile_find(bile, id); + struct bile_object *o, verify; size_t rsize; short error; + o = bile_find(bile, type, id); if (o == NULL) return -1; @@ -252,8 +304,20 @@ bile_read(struct bile *bile, unsigned long id, char ** if (error) goto read_error; - /* TODO: read object header and verify size and id */ - + rsize = BILE_OBJECT_SIZE; + error = FSRead(bile->vrefid, &rsize, &verify); + if (error) + goto read_error; + if (verify.id != id) + panic("bile_read: object %ld pos %ld wrong id %ld, expected %ld", + id, o->pos, verify.id, id); + if (verify.type != type) + panic("bile_read: object %ld pos %ld wrong type %ld, expected %ld", + id, o->pos, verify.type, type); + if (verify.size != o->size) + panic("bile_read: object %ld pos %ld wrong size %ld, expected %ld", + id, o->pos, verify.size, o->size); + rsize = o->size; error = FSRead(bile->vrefid, &rsize, *data); if (error) @@ -269,51 +333,28 @@ read_error: } size_t -bile_write(struct bile *bile, unsigned long id, char *data, size_t size) +bile_write(struct bile *bile, OSType type, unsigned long id, char *data, + size_t size) { struct bile_object *old, *new_obj; - size_t ret, wsize; + size_t ret; short error; - new_obj = bile_alloc(bile, size); - /* we must find after alloc because it re-sorts */ - old = bile_find(bile, id); - new_obj->id = id; + old = bile_find(bile, type, id); + if (old) + old->type = BILE_PURGE_TYPE; + + new_obj = bile_alloc(bile, type, id, size); - if (new_obj->pos >= bile->file_size) - error = SetFPos(bile->vrefid, fsFromLEOF, 0); - else - error = SetFPos(bile->vrefid, fsFromStart, new_obj->pos); - if (error) - goto write_error; + bile_xwriteat(bile, new_obj->pos, BILE_OBJECT_SIZE, new_obj); + bile_xwriteat(bile, new_obj->pos + BILE_OBJECT_SIZE, size, data); - wsize = BILE_OBJECT_SIZE; - error = FSWrite(bile->vrefid, &wsize, new_obj); - if (error) - goto write_error; - - wsize = size; - error = FSWrite(bile->vrefid, &wsize, data); - if (error) - goto write_error; - if (wsize != size) - panic("bile_open: needed to write %ld, wrote %ld", size, wsize); - - error = SetFPos(bile->vrefid, fsFromLEOF, 0); - if (error) - goto write_error; + SetFPos(bile->vrefid, fsFromLEOF, 0); GetFPos(bile->vrefid, &bile->file_size); - if (old) - old->id = BILE_PURGE_ID; - bile_write_map(bile); return ret; - -write_error: - panic("bile_write: failed writing %ld to %s: %d", size, - PtoCstr(bile->filename), error); } void @@ -321,58 +362,39 @@ bile_write_map(struct bile *bile) { struct bile_object *obj, *new_map_obj, *new_map; size_t new_map_size, new_nobjects; - size_t size, n, new_n; + size_t pos, n; short error; - char *magic; - - new_nobjects = 1; /* for the new map */ - for (n = 0; n < bile->nobjects; n++) { - obj = &bile->map[n]; - - if (obj->pos == bile->map_pos || obj->id == BILE_PURGE_ID) - /* ignore old map and purgable objects */ - continue; - - new_nobjects++; - } + /* allocate a new map slightly larger than we need */ + new_nobjects = bile->nobjects; + if (!bile->map_pos) + new_nobjects++; new_map_size = BILE_OBJECT_SIZE * new_nobjects; - new_map_obj = bile_alloc(bile, new_map_size); - new_map_obj->id = BILE_MAP_ID; - - /* write new map object header */ - if (new_map_obj->pos == bile->file_size) - error = SetFPos(bile->vrefid, fsFromLEOF, 0); - else - error = SetFPos(bile->vrefid, fsFromStart, new_map_obj->pos); - if (error) - goto write_error; - - size = BILE_OBJECT_SIZE; - error = FSWrite(bile->vrefid, &size, &new_map_obj); - if (error) - goto write_error; - + new_map_obj = bile_alloc(bile, BILE_MAP_TYPE, 0, new_map_size); new_map = xmallocarray(BILE_OBJECT_SIZE, new_nobjects); - new_n = 0; - for (n = 0; n < bile->nobjects; n++) { + + for (n = 0, new_nobjects = 0; n < bile->nobjects; n++) { obj = &bile->map[n]; - if (obj->pos == bile->map_pos || obj->id == BILE_PURGE_ID) - /* ignore old map and purgable objects */ + if (obj->type == BILE_MAP_TYPE && obj->pos == bile->map_pos) + /* don't include old map in new one */ continue; - - new_map[new_n++] = *obj; + if (obj->type == BILE_PURGE_TYPE) + continue; + + new_map[new_nobjects++] = *obj; } - size = new_map_size; - error = FSWrite(bile->vrefid, &size, new_map); - if (error) - goto write_error; + /* shrink to new object count */ + new_map_size = BILE_OBJECT_SIZE * new_nobjects; + new_map_obj->size = new_map_size; + bile->nobjects = new_nobjects; - error = SetFPos(bile->vrefid, fsFromLEOF, 0); - if (error) - goto write_error; + pos = bile_xwriteat(bile, new_map_obj->pos, BILE_OBJECT_SIZE, + &new_map_obj); + pos = bile_xwriteat(bile, pos, new_map_size, new_map); + + SetFPos(bile->vrefid, fsFromLEOF, 0); GetFPos(bile->vrefid, &bile->file_size); /* successfully wrote new map, switch over */ @@ -382,29 +404,44 @@ bile_write_map(struct bile *bile) bile->map_size = new_map_obj->size; /* write new header to point at new map object */ - magic = xstrdup(BILE_MAGIC); - size = BILE_MAGIC_LEN; - error = SetFPos(bile->vrefid, fsFromStart, 0); - if (error) - goto write_error; - error = FSWrite(bile->vrefid, &size, magic); - free(magic); - if (error) - goto write_error; - size = sizeof(long); - error = FSWrite(bile->vrefid, &size, &bile->map_pos); - if (error) - goto write_error; - error = FSWrite(bile->vrefid, &size, &bile->map_size); - if (error) - goto write_error; + pos = bile_xwriteat(bile, BILE_MAGIC_LEN, sizeof(long), + &bile->map_pos); + pos = bile_xwriteat(bile, pos, sizeof(long), &bile->map_size); /* TODO: flush? */ +} + +size_t +bile_xwriteat(struct bile *bile, size_t pos, size_t len, void *data) +{ + short error; + size_t wsize; + long asize; - return; - -write_error: - panic("bile_write_map: failed writing to %s: %d", - PtoCstr(bile->filename), error); + if (pos == bile->file_size) { + error = SetFPos(bile->vrefid, fsFromLEOF, 0); + } else if (pos > bile->file_size) { + /* may as well allocate to cover len too */ + asize = pos + len - bile->file_size; + error = Allocate(bile->vrefid, &asize); + if (error) + panic("bile_xwriteat: failed Allocate of %lu in %s: %d", + pos + len - bile->file_size, PtoCstr(bile->filename), error); + error = SetFPos(bile->vrefid, fsFromLEOF, 0); + } else + error = SetFPos(bile->vrefid, fsFromStart, pos); + if (error) + panic("bile_xwriteat: failed SetFPos to %lu in %s: %d", + pos, PtoCstr(bile->filename), error); + wsize = len; + error = FSWrite(bile->vrefid, &wsize, data); + if (error) + panic("bile_xwriteat: failed writing %lu at %lu to %s: %d", + len, pos, PtoCstr(bile->filename), error); + if (wsize != len) + panic("bile_xwriteat: short write of %lu at %lu to %s: %lu", + len, pos, PtoCstr(bile->filename), wsize); + + return pos + len; } --- bile.h Mon Jan 3 22:22:07 2022 +++ bile.h Tue Jan 4 16:21:13 2022 @@ -25,25 +25,27 @@ * [ map contents - (map_size) ] * [ object[0] position - long ] * [ object[0] size - long ] + * [ object[0] type - long ] * [ object[0] id - long ] * [ ... ] * [ object[0] start (map points to this as its position) ] * [ object[0] position - long ] * [ object[0] size - long ] + * [ object[0] type - long ] * [ object[0] id - long ] * [ object[1] start ] * [ .. ] */ #define BILE_MAGIC "BILE1" #define BILE_MAGIC_LEN 5 -#define BILE_MAP_ID (ULONG_MAX) -#define BILE_PURGE_ID (ULONG_MAX - 1) -#define BILE_FILE_TYPE 'BILE' #define BILE_HEADER_LEN (BILE_MAGIC_LEN + (sizeof(long) + sizeof(long))) +#define BILE_MAP_TYPE '_BLM' +#define BILE_PURGE_TYPE '_BLP' struct bile_object { unsigned long pos; unsigned long size; + OSType type; unsigned long id; }; #define BILE_OBJECT_SIZE (sizeof(struct bile_object)) @@ -59,11 +61,16 @@ struct bile { size_t nobjects; }; -struct bile * bile_create(Str255 filename, OSType creator); +struct bile * bile_create(Str255 filename, OSType creator, OSType type); struct bile * bile_open(Str255 filename); void bile_close(struct bile *bile); -struct bile_object * bile_find(struct bile *bile, unsigned long id); -struct bile_object * bile_alloc(struct bile *bile, size_t size); -size_t bile_read(struct bile *bile, unsigned long id, char **data); -size_t bile_write(struct bile *bile, unsigned long id, char *data, - size_t size); +struct bile_object * bile_find(struct bile *bile, OSType type, + unsigned long id); +size_t bile_next_id(struct bile *bile, OSType type); +struct bile_object * bile_alloc(struct bile *bile, OSType type, + unsigned long id, size_t size); +void bile_delete(struct bile *bile, OSType type, unsigned long id); +size_t bile_read(struct bile *bile, OSType type, unsigned long id, + char **data); +size_t bile_write(struct bile *bile, OSType type, unsigned long id, + char *data, size_t size);