jcs
/amend
/amendments
/192
bile: Add bile_begin and bile_commit to do things in transactions
Rather than writing the new map on every change, one can enter a
transaction and defer writing the new map until bile_commit. This
way if a crash happens during changes, the map won't be left
pointing at partial progress.
jcs made amendment 192 18 days ago
--- bile.c Sat Oct 3 22:24:32 2026
+++ bile.c Sun Oct 4 00:41:47 2026
@@ -264,6 +264,33 @@ bile_close(struct bile *bile)
xfree(&bile->map);
}
+void
+bile_begin(struct bile *bile)
+{
+ bile_check_sanity(bile);
+
+ if (bile->in_transaction)
+ panic("bile_begin: transaction already in progress");
+
+ bile->in_transaction = true;
+}
+
+short
+bile_commit(struct bile *bile)
+{
+ bile_check_sanity(bile);
+
+ if (!bile->in_transaction)
+ panic("bile_commit: no transaction in progress");
+
+ bile->in_transaction = false;
+
+ if (bile_write_map(bile) != 0)
+ return -1;
+
+ return bile_flush(bile, true);
+}
+
struct bile_object *
bile_find(struct bile *bile, const OSType type, const unsigned long id)
{
@@ -413,21 +440,23 @@ bile_delete(struct bile *bile, const OSType type, cons
pos = o->pos;
size = o->size + BILE_OBJECT_SIZE;
- _bile_error = bile->last_error = SetFPos(bile->frefnum, fsFromStart,
- pos);
- if (_bile_error)
- return -1;
-
- while (size > 0) {
- wsize = MIN(128, size);
- size -= wsize;
-
- _bile_error = bile->last_error = FSWrite(bile->frefnum, &wsize,
- zero);
+ if (!bile->in_transaction) {
+ _bile_error = bile->last_error = SetFPos(bile->frefnum,
+ fsFromStart, pos);
if (_bile_error)
return -1;
- }
+ while (size > 0) {
+ wsize = MIN(128, size);
+ size -= wsize;
+
+ _bile_error = bile->last_error = FSWrite(bile->frefnum,
+ &wsize, zero);
+ 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
@@ -447,7 +476,7 @@ bile_delete(struct bile *bile, const OSType type, cons
sizeof(unsigned long));
/* bile_write wrote a new map for us */
- } else {
+ } else if (!bile->in_transaction) {
bile_write_map(bile);
if (_bile_error)
return -1;
@@ -620,10 +649,12 @@ bile_write(struct bile *bile, const OSType type, const
SetFPos(bile->frefnum, fsFromLEOF, 0);
GetFPos(bile->frefnum, &bile->file_size);
- bile_write_map(bile);
- if (bile->last_error)
- return 0;
-
+ if (!bile->in_transaction) {
+ bile_write_map(bile);
+ if (bile->last_error)
+ return 0;
+ }
+
return wrote;
}
--- bile.h Sat Mar 4 22:39:38 2023
+++ bile.h Sun Oct 4 00:36:47 2026
@@ -91,6 +91,7 @@ struct bile {
struct bile_object *map; /* array of bile_objects */
size_t nobjects;
char magic[5];
+ bool in_transaction;
};
struct bile_object_field {
@@ -108,6 +109,8 @@ struct bile * bile_open_recover_map(const Str255 fil
short vrefnum);
short bile_flush(struct bile *bile, bool and_vol);
void bile_close(struct bile *bile);
+void bile_begin(struct bile *bile);
+short bile_commit(struct bile *bile);
struct bile_object * bile_find(struct bile *bile, const OSType type,
const unsigned long id);