aboutsummaryrefslogtreecommitdiffstats
path: root/core/module-list.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-29 06:35:05 +0100
committereunhhu <[email protected]>2026-09-29 06:35:05 +0100
commitc8f0704b6f88f331be24a89df7d7cb6a4bf29164 (patch)
treeeb47503b5dd08e1d993b3c81eb06b37b608166d6 /core/module-list.c
parentc97e4e1a203d13852d5f7cd4a404f88b44f4064f (diff)
downloadpure-c8f0704b6f88f331be24a89df7d7cb6a4bf29164.tar.gz
pure-c8f0704b6f88f331be24a89df7d7cb6a4bf29164.zip
Keep the outbox as a list: a save logs only the sends and trims it made
The sends not yet trimmed were written whole into the links value at every save, as the numbers heard were: a sender whose receiver is away or slow saved all its waiting sends again with each new one. They are now a runtime list {output (its name), seq, payload}, in the order sent, stored as a list state is (image "0sent" and its changes in the log). A send is a change of the list with its event; a trim lets the sends go at once and a failed save brings them back; the host sees the saved ones (sent_saved). Outputs are named in the items, so a module replaced keeps them without moving anything; one that lacks or changed an output with sends left is refused as before. Links stored before (PLK1, PLK2) move their sends to the list at a start and are stored again without them (PLK3). A list field may now hold any bytes (kind 2), unchecked, besides a number and a UTF-8 text. Saving 5,000 sends of 16 KB one by one took 84.8 s and left a store of 400 MB; now 0.91 s and 144 MB. 20,000 of 61 bytes: 8.4 s, now 2.9 s.
Diffstat (limited to 'core/module-list.c')
-rw-r--r--core/module-list.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/core/module-list.c b/core/module-list.c
index 522523f..f32fd05 100644
--- a/core/module-list.c
+++ b/core/module-list.c
@@ -497,7 +497,7 @@ PureList *pure_list_new(unsigned fields, const uint8_t *text_fields) {
l->fields = fields;
size_t at = sizeof(Node);
for (unsigned f = 0; f < fields; ++f) {
- l->text_fields[f] = text_fields[f] != 0;
+ l->text_fields[f] = text_fields[f]; /* 1 text (UTF-8), 2 bytes */
l->column[f] = (uint32_t)at;
at += FANOUT * (l->text_fields[f] ? sizeof(PureSpan) : sizeof(double));
if (l->text_fields[f]) l->text_field[l->texts++] = (uint8_t)f;
@@ -635,7 +635,8 @@ static bool decode_cell(const Layout *l, unsigned field, const unsigned char *by
memcpy(&cell->num, &bits, sizeof(bits));
return isfinite(cell->num);
}
- if (bits > size - *at || !pure_utf8_valid((PureSpan){bytes + *at, (size_t)bits})) return false;
+ if (bits > size - *at || (l->text_fields[field] == 1 && !pure_utf8_valid((PureSpan){bytes + *at, (size_t)bits})))
+ return false;
*cell = (PureCell){0, (unsigned char *)bytes + *at, (size_t)bits};
*at += (size_t)bits;
return true;
@@ -697,7 +698,8 @@ static bool get_compact(const Layout *l, unsigned field, const unsigned char *by
*cell = (PureCell){0};
if (!get_varint(bytes, size, at, &value)) return false;
if (l->text_fields[field]) {
- if (value > size - *at || !pure_utf8_valid((PureSpan){bytes + *at, (size_t)value})) return false;
+ if (value > size - *at || (l->text_fields[field] == 1 && !pure_utf8_valid((PureSpan){bytes + *at, (size_t)value})))
+ return false;
*cell = (PureCell){0, (unsigned char *)bytes + *at, (size_t)value};
*at += (size_t)value;
return true;