AmendHub

jcs

/

subtext

/

amendments

/

134

bile: Bug fixes, store highest ids when deleting

The previous fix was bogus, back it out.
The "o = &bile->map[n - 1]" line seems to have been erroneously copied
and pasted (many times) from another loop where I was going
backwards :(
Implement storage of highest ids seen when deleting, so that
bile_next_id hands out 1 higher than that id. This way we won't
re-use ids of deleted things like users, posts, etc.

jcs made amendment 134 5 months ago
--- bile.c Thu Jun 9 16:12:42 2022 +++ bile.c Sat Jun 11 19:59:05 2022 @@ -23,6 +23,7 @@ static short _bile_error = 0; static short _bile_open_ignore_primary_map = 0; +void bile_find_highest_ids(struct bile *bile); struct bile_object * bile_alloc(struct bile *bile, const OSType type, const unsigned long id, const size_t size); struct bile_object * bile_object_in_map(struct bile *bile, @@ -124,7 +125,7 @@ struct bile * bile_open(const Str255 filename, short vrefnum) { struct bile *bile = NULL; - struct bile_object map_obj; + struct bile_object map_obj, *o; char magic[BILE_MAGIC_LEN + 1]; size_t file_size, map_size, size; short fh, old_map_tried = 0; @@ -291,7 +292,7 @@ bile_count_by_type(struct bile *bile, const OSType typ _bile_error = bile->last_error = 0; for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n - 1]; + o = &bile->map[n]; if (o->type == type) count++; } @@ -309,7 +310,7 @@ bile_sorted_ids_by_type(struct bile *bile, const OSTyp bile_check_sanity(bile); for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n - 1]; + o = &bile->map[n]; if (o->type != type) continue; @@ -344,7 +345,7 @@ bile_get_nth_of_type(struct bile *bile, const size_t i _bile_error = bile->last_error = 0; for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n - 1]; + o = &bile->map[n]; if (o->type != type) continue; @@ -364,17 +365,24 @@ bile_next_id(struct bile *bile, const OSType type) { struct bile_object *o; size_t n, id = 1; + unsigned long highest; bile_check_sanity(bile); _bile_error = bile->last_error = 0; for (n = 0; n < bile->nobjects; n++) { - o = &bile->map[n - 1]; + o = &bile->map[n]; if (o->type == type && o->id >= id) id = o->id + 1; } + if (bile_read(bile, BILE_TYPE_HIGHESTID, type, &highest, + sizeof(unsigned long)) == sizeof(unsigned long)) { + if (highest > id) + id = highest + 1; + } + return id; } @@ -383,8 +391,9 @@ bile_delete(struct bile *bile, const OSType type, cons { static char zero[128] = { 0 }; struct bile_object *o; - size_t pos, size, wsize; - + size_t pos, size, wsize, n; + unsigned long highest; + bile_check_sanity(bile); _bile_error = bile->last_error = 0; @@ -413,10 +422,31 @@ bile_delete(struct bile *bile, const OSType type, cons if (_bile_error) return -1; } + + /* + * If this is the highest id of this type, store it so it won't get + * handed out again from bile_next_id + */ + highest = id; + for (n = 0; n < bile->nobjects; n++) { + o = &bile->map[n]; + if (o->type == type && o->id > highest) { + highest = o->id; + break; + } + } - bile_write_map(bile); - if (_bile_error) - return -1; + if (highest == id) { + /* store the type as the id, and the highest id as the data */ + bile_write(bile, BILE_TYPE_HIGHESTID, type, &highest, + sizeof(unsigned long)); + + /* bile_write wrote a new map for us */ + } else { + bile_write_map(bile); + if (_bile_error) + return -1; + } return 0; } @@ -710,19 +740,23 @@ short bile_verify(struct bile *bile) { struct bile_object o; - size_t n, size; + size_t n, size, pos; char data; bile_check_sanity(bile); _bile_error = bile->last_error = 0; - for (n = 0; n < bile->nobjects; n++) { + for (n = 0, pos = 0; n < bile->nobjects; n++) { size = bile_read_object(bile, &bile->map[n], &data, 1); if (bile_error(bile)) return bile_error(bile); else if (size == 0) return -1; + + if (bile->map[n].pos <= pos) + return -1; + pos = bile->map[n].pos + bile->map[n].size; } return 0; @@ -763,14 +797,13 @@ bile_alloc(struct bile *bile, const OSType type, const _bile_error = bile->last_error = 0; - /* find a last_pos we can use */ + /* find a gap big enough to hold our object + its size */ for (n = 0; n < bile->nobjects; n++) { - if (n > 0 && - bile->map[n].pos - last_pos >= (size + BILE_OBJECT_SIZE)) + if (bile->map[n].pos - last_pos >= (size + BILE_OBJECT_SIZE)) break; last_pos = bile->map[n].pos + BILE_OBJECT_SIZE + bile->map[n].size; } - + /* * The map is always sorted, so walk the map to find out where to * wedge a copy of this new object, then return a pointer to it in --- bile.h Wed Jun 8 11:26:04 2022 +++ bile.h Sat Jun 11 20:00:38 2022 @@ -48,11 +48,12 @@ * [ map id - long ] * [ map contents ] */ -#define BILE_MAGIC "BILE2" -#define BILE_MAGIC_LEN 5 -#define BILE_TYPE_MAP '_BLM' -#define BILE_TYPE_MAPPTR '_BL>' -#define BILE_TYPE_PURGE '_BLP' +#define BILE_MAGIC "BILE2" +#define BILE_MAGIC_LEN 5 +#define BILE_TYPE_MAP '_BLM' +#define BILE_TYPE_MAPPTR '_BL>' +#define BILE_TYPE_PURGE '_BLP' +#define BILE_TYPE_HIGHESTID '_BLH' struct bile_object { unsigned long pos; @@ -75,6 +76,11 @@ struct bile_object { #define BILE_ERR_NEED_UPGRADE_1 -4000 #define BILE_ERR_BOGUS_OBJECT -4001 + +struct bile_highest_id { + OSType type; + unsigned long highest_id; +}; struct bile { struct bile_object map_ptr;