aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-27 23:38:54 +0100
committereunhhu <[email protected]>2026-09-27 23:38:54 +0100
commitad27f1f5a4fc7a53d116feb9b1e2352239147fe0 (patch)
tree85c2bca2056d9b62d4057f4fed82f1fcbb6cd959
parent72f8e1ca1fba181eeed6d2643a21f05881272d83 (diff)
downloadpure-ad27f1f5a4fc7a53d116feb9b1e2352239147fe0.tar.gz
pure-ad27f1f5a4fc7a53d116feb9b1e2352239147fe0.zip
Let a runtime-owned state grow past the document limit
A list's stored form is one value in the tree store, so the limit on a document (1.38 MiB, what a host carries whole as an HTTP body) capped a table at about 51,000 rows of 28 bytes. A value the runtime owns, a state (a key starting with '.') or a draft without a key, may now grow to 1 GiB; documents keep their limit. The store's format is unchanged: its trees already reach far past either.
-rw-r--r--core/store.h5
-rw-r--r--store/store-tree.c10
2 files changed, 13 insertions, 2 deletions
diff --git a/core/store.h b/core/store.h
index dbfa8f8..64b8d9e 100644
--- a/core/store.h
+++ b/core/store.h
@@ -5,6 +5,11 @@
#include <stdint.h>
#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+/* A document (what a host carries whole, as an HTTP body) is at most
+ * PURE_OBJECT_LIMIT bytes. A value the runtime owns (an app's list or text
+ * state: a key starting with '.', or a draft without a key) may grow to
+ * PURE_STATE_LIMIT: a table of a million rows is one such value. */
+#define PURE_STATE_LIMIT (UINT64_C(1) << 30)
typedef struct {
void *mapping;
size_t mapped_size, object_size;
diff --git a/store/store-tree.c b/store/store-tree.c
index 024809b..0f83f27 100644
--- a/store/store-tree.c
+++ b/store/store-tree.c
@@ -879,6 +879,12 @@ static bool write_root(const Tree *tree, Writer *writer, Entry *root, bool reloc
return root_height(tree, *root, &height) && write_subtree(tree, writer, root, height, relocate);
}
+/* How large a value under key may grow: a runtime-owned state's ('.', or no
+ * key at all) or a document's (store.h). */
+static uint64_t limit_of(const char *key) {
+ return !key[0] || key[0] == '.' ? PURE_STATE_LIMIT : PURE_OBJECT_LIMIT;
+}
+
static bool read_record(const Tree *tree, Entry catalog, uint64_t index,
unsigned char record[RECORD], Entry *document, int64_t *revision) {
unsigned height;
@@ -888,7 +894,7 @@ static bool read_record(const Tree *tree, Entry catalog, uint64_t index,
uint64_t stored = decode64(record + KEY + 16);
*revision = (int64_t)stored;
return stored && stored <= (uint64_t)INT64_MAX && !document->ref == !document->bytes &&
- document->bytes <= PURE_OBJECT_LIMIT;
+ document->bytes <= limit_of((const char *)record);
}
/* Binary search over records ordered by their zero-padded key bytes. */
@@ -1579,7 +1585,7 @@ static void collect(PureDraft *draft) {
PureResult pure_draft_splice(PureDraft *draft, size_t offset, size_t remove, PureSpan insert) {
uint64_t size = draft->root.bytes;
if (insert.size && !insert.data) return PURE_INVALID;
- if (offset > size || remove > size - offset || insert.size > PURE_OBJECT_LIMIT - (size - remove))
+ if (offset > size || remove > size - offset || insert.size > limit_of(draft->key) - (size - remove))
return PURE_LIMIT;
if (!remove && !insert.size) return PURE_OK;
Entry next;