50 descendants of 4536dae44c2ceb11
|
2026-10-29
| ||
| 14:01 |
fix(content): serve a kept tree only where a fresh read would give it
Review of the tree memo found it could classify differently warm than cold. A kept tree was served whenever the store held its name at its rid, even when the store could no longer expand it (a delta whose source became a phantom or lost its row), where a fresh read skips the tree. Each view now lists, once, the rids its store cannot expand: a recursive walk of the delta table seeded with the phantoms and the delta sources the store holds no row for. Those sources only appear when a row is deleted, which forces a full read, so they are found once per lineage (about 20ms on fossil-scm.org) and the per-view walk costs about 0.3ms. The phantom check folds into it. Publish dropped the trees a view read whenever the memo had gone past that view's store, though trees do not depend on the store; they are now kept either way. A view over a store read in full after the memo's is no longer taken for a stale one, so a store whose highest rid was deleted stops being read in full on every view. The names bound that replaced the byte cap counted pieces, not names, so one publish could pass it; it now counts the names each piece adds, on the fresh-index path too, and is passed as a parameter so it is tested. The tests compare the names a horizon's walk produces, memo against fresh, which classification alone can hide: a tree's lost nodes also stop its files counting as files. They lose trees as phantoms, as deleted nodes, behind phantom and deleted delta sources, and by a shun and rebuild in stock fossil; removing either check fails them. check-in: c50ff7c9e2 user: [email protected] tags: main, perf/463-memo-trees, trunk | |
| 12:46 |
perf(content): keep the memo's trees for the life of the memo
HZ-6.2-10 asks that an origin read each structural artifact's F cards once per store. The memo's tree index already kept fossil-scm.org's whole tree history in about 11MiB, yet it still read trees again in two cases: past a 64MiB bound, and after any full read of the store, which dropped the index with its lineage. Neither was needed. A tree piece is what its name's bytes say, so it is valid in every store that holds the name; the rid it was read at is checked against the view's own rid-to-name map, and a renumbered store reads it once more and moves it to its rid. The index grows with the store like the reference graph beside it, so the byte bound goes; only a names bound at the most artifacts a classified store can hold remains, which one store cannot reach. On the fossil-scm.org clone a horizon 2000 back after a full read now takes 1.0-1.8s instead of 4.3-6.2s, and the whole history after a full read reads no tree (1.3-1.5s, from 14-17s). Cold runs and peak heap are unchanged. HZ-6.2-10 is now covered; the trees still enter the graph when a walk first reaches them, as the reverted eager read cost 4-5x cold. leaf check-in: bfce209a24 user: [email protected] tags: main, perf/463-memo-trees, trunk | |
| 12:46 |
test(content): measure the memo's trees after a full read and over all history
The corpus test timed horizons cold and warm, but not the case HZ-6.2-10 left open: a full read of the store (an arrival a held artifact cited) dropped every tree the memo had read. It now times a horizon again after one, and a second test walks the whole history to report what keeping every tree costs in heap and time. check-in: e690ff7ad2 user: [email protected] tags: main, perf/463-memo-trees, trunk | |
| 05:35 |
Merge pull request #525 from danmestas/feat/horizon-peer-serving
fix(sync): a horizon store refuses a pull it does not hold and mints no seed check-in: 301c8e2337 user: [email protected] tags: main, trunk | |
| 04:57 |
refactor(sync): keep an allowlist of reply cards on a horizon refusal
A refusal keeps only gimmes, errors, messages and the session-level pragmas, so a pull-side card type added later is dropped until judged safe. The refused-pull case now asks for every pull-side card kind and asserts the reply holds only allowlisted types. check-in: fb36eb5653 user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 04:21 | Merge remote-tracking branch 'origin/main' into feat/horizon-peer-serving leaf check-in: fa65d2c2d5 user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 03:45 |
fix(sync): a refused horizon sync still takes the peer's push
Re-review of #525. Resetting the reply after the card loop dropped the gimmes that answer the client's igot announcements. The real client sends only igots in its first round, so its push never landed. - Server: a §6.4 refusal drops only what the pull half put in the reply. That is content, announcements and the pragmas serving the horizon. The push half's cards stay, its gimmes and any push error, and the horizon-not-held error goes last, since a client stops reading at an error card. - Client: on a horizon-not-held refusal the pull stops and later requests carry no pull card. Rounds go on answering gimmes until the push converges, bounded by MaxRounds, and Sync then returns the refusal. A structural store does not read the refusal as a reason to fall back. - The refused-push case now drives the real client: an earlier-C peer with a check-in of its own syncs, and the store holds that check-in while the peer is sent no content. A push error survives the refusal. - The requirement table and concept doc say why taking the push is consistent with §6.4's "no content". check-in: a557971c28 user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 03:30 |
Merge pull request #526 from danmestas/perf/wasm-size-and-refusal
Return receive-budget refusals as *RefusedError; libfossil_nohttp tag cuts the TinyGo engine ~97 KB check-in: 0ffed7ff5f user: [email protected] tags: main, trunk | |
| 03:21 |
docs: libfossil_nohttp is for library embedders, who supply their own transport
The cli package and examples/tinygo, which calls NewHTTPTransport, do not build with the tag; a tagged embedder supplies its own Transport and serves through HandleSyncWithOpts. check-in: 4069607141 user: [email protected] tags: main, trunk | |
| 03:06 |
perf(wasm): add a libfossil_nohttp build tag that leaves out net/http
Under TinyGo, importing net/http at all links its TLS and X.509 code (crypto/x509, encoding/asn1, math/big's integers, AES-GCM, SHA-3, netip) whether or not a request is ever made: a five-line program that calls only http.StatusText grows by about 430 KB raw. The library imports it for its HTTP client transport and its HTTP server, which a program that serves sync through HandleSyncWithOpts and supplies its own transport never calls. Built with -tags libfossil_nohttp, the library leaves out NewHTTPTransport, WithHTTPClient, Repo.Pull, Repo.XferHandler and Repo.ServeHTTP, and the internal/sync client, server, redirect handling and peer-address trace they use. HandleSync, HandleSyncWithOpts, Sync over a host Transport and everything else are unchanged. Without the tag nothing changes. The retry classifier keeps the two statuses it read from net/http as constants, and DNS fault classification moves to its own file so it stays in the tagged build. For the html-artifact-publisher engine (TinyGo 0.43.0, Go 1.26.0) the tag takes the gzipped binary from 1,100,251 to 1,003,279 bytes. A test builds the library, db and simio with the tag for the host and js/wasm and checks none links net/http, net/http/httptrace or crypto/tls, and that the untagged library still does. check-in: 9594cf3bae user: [email protected] tags: main, trunk | |
| 03:06 |
perf(fsltype): format a 53-bit text Julian day in float64, no math/big
Fossil's %.17g of a text Julian day is computed in the platform's long double, which this package emulates with big.Float at that precision. A 53-bit long double is a double, and big.Float at 53 bits with round-to-nearest-even is exactly IEEE double arithmetic over this range, so that case (wasm, macOS arm64, Windows) is now computed in float64, each product converted explicitly so none fuses into a multiply-add. The big.Float path remains for the 64- and 113-bit long doubles and is left out of wasm builds, whose long double is 53 bits; a wasm TinyGo binary loses math/big's floating point, about 5 KB gzipped. A test checks the float64 path against the big.Float one at 53 bits over 50,000 random times and every ~1 s of three days, and the existing fossil-binary sweep passes unchanged. Stored times do not change. check-in: f7eb80beae user: [email protected] tags: main, trunk | |
| 03:06 |
feat(sync): return a receive-budget refusal to the host as *RefusedError
With HandleOpts.MaxStoredBytes set, a refused push rolls its request transaction back and replies with one error card. A host whose storage treats any rollback as an abort of the whole call (a Durable Object running the request in one transactionSync) discards that reply, so the client saw only "transaction rolled back". HandleSyncWithOpts now returns the encoded reply together with a *RefusedError whose Message is the error card's text, matchable with errors.As. Such a host can report or render the refusal itself without parsing xfer; a host serving HTTP sends the reply as before. Only the budget refusal reports this way, so no released behaviour changes: the budget is unreleased and opt-in. check-in: dd7401ad01 user: [email protected] tags: main, trunk | |
| 03:02 |
fix(sync): judge the horizon refusal after the push, serve later peers
Review of #525. - A requested C this store cannot place is a peer ahead of it, not one asking for history it lacks, and is served what the store holds. A peer at a later C the store holds is placed inside its held set and served. - The refusal is judged after the card loop, once the pull card has passed its permission check and the push half is stored. Only the pull half is refused: the reply is reset to the one error card, the request is not rolled back, and a push in the same sync is kept. - The held sets are computed through the classification memo, which keeps them per store and drops them when the store changes; the inventory reuses the view the judgment read. - The refusal begins with the machine-readable prefix horizon-not-held:, which the client matches instead of the whole text. - The fallback remedy moves from a new result field into the existing diagnostics, prefixed horizon-fallback:: SyncResult.Errors and CloneResult.Messages. The CLI still prints it. check-in: ad975ea85b user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 02:12 | refactor(sync): separate the seeded-store check's error from its answer check-in: 2cac21987f user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 02:06 |
fix(sync): a horizon store refuses a pull it does not hold and mints no seed
A server over a horizon clone answered a horizon pull or sync at an earlier C from its own partial graph. It now refuses any horizon pull whose held set is not a subset of its own with one error card and no content, rolled back whole, and a go-libfossil client fails the round on that reply (draft-fossil-horizon-00 §6.4). partial-mirror serves it, as it does an uncovered clone. The clone coverage check now judges the horizon the request asked for, not the depth serving cut it to. A store at a structural horizon no longer mints a seed from its own seed: it answers a structural request at the content level (§6.2.3) and names its horizon-history-url. The requester falls back and reports HorizonRemedy, naming C and the dense origin that holds the manifests below it; the CLI prints it. The concept doc states when a horizon store may serve a horizon peer. Conformance covers §6.4 on the pull path, a structural store answering as content, and the fallback a structural clone takes from such a peer; zit pulls from a go-libfossil horizon store in both outcomes. Closes #490 check-in: 8802c5704f user: [email protected] tags: feat/horizon-peer-serving, main, trunk | |
| 01:51 |
Merge pull request #524 from danmestas/feat/receive-size-budget
feat(sync): per-store artifact size budget on the receive path check-in: d385bc8746 user: [email protected] tags: main, trunk | |
| 01:42 |
fix(sync): name a too-big file only to a reader, never by a private check-in
The budget refusal names the file and check-in only when the requester may read the repository, and phantomName skips private check-ins. HandleOpts, XferHandler and ServeHTTP document that the default handler applies no budget, so a host that needs one serves HandleSyncWithOpts itself. Tests: an artifact held in full is not refused; a bare phantom is; a path holding card syntax goes out as one encoded error line; a sync round with pull and igot cards is refused whole with FilesReceived 0. Atomicity checks now cover unclustered, phantom, delta and mlink alongside blob. check-in: 41102e04af user: [email protected] tags: feat/receive-size-budget, main, trunk | |
| 01:35 | Merge remote-tracking branch 'origin/main' into feat/receive-size-budget check-in: 8426695b6c user: [email protected] tags: feat/receive-size-budget, main, trunk | |
| 00:48 |
Merge pull request #522 from danmestas/perf/memo-tree-encoding
perf(content): keep the memo's trees as interned id sets and differences check-in: 6d860dc574 user: [email protected] tags: main, trunk | |
| 00:42 |
Merge remote-tracking branch 'origin/main' into feat/receive-size-budget
# Conflicts: # CHANGELOG.md check-in: 767f64016a user: [email protected] tags: feat/receive-size-budget, main, trunk | |
| 00:39 |
content: compare the intern count as uint64 so 32-bit targets build
math.MaxUint32 overflows int on TinyGo's wasm target. check-in: 53338a5536 user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 00:24 | Merge remote-tracking branch 'origin/main' into perf/memo-tree-encoding check-in: e5b5f30ace user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 00:24 |
Merge pull request #523 from danmestas/feat/attachments
feat(attachments): fossil-compatible attachments API, with Quarry external stubs check-in: 6520f5dbb0 user: [email protected] tags: main, trunk | |
| 00:15 |
fix(attachments): stamp each attachment write after the latest for its name
A default-time deletion could share the addition's millisecond, leaving both rows latest: the deleted file stayed listed but could not be read. A synced attachment stamped in the future made a default-time deletion a silent no-op. Every write is now stamped strictly after the latest for its name -- now, or a millisecond after it -- and an explicit earlier or equal time is refused, for additions as for deletions. The ambiguity error names the kinds that matched, and an external name of "." or ".." is refused up front. leaf check-in: cfc0ab51e8 user: [email protected] tags: feat/attachments, main, trunk | |
| 00:10 |
feat(attachments): add, delete, list and read attachments as fossil does
AttachmentAdd, AttachmentDelete, Attachments and AttachmentRead write and read the artifacts fossil 2.28's attach.c writes: the file as one ordinary blob and an A C D U Z control artifact naming it, a deletion as an A card with no source. Targets are a wiki page's exact name or a ticket's or tech note's id or unique prefix; a name two kinds answer to is refused. AttachmentAddExternal stores Quarry RFC 0016's stub in place of the bytes, with the mimetype on the N card; list and read report the reference and never hand the stub's text back as the file. check-in: f747958447 user: [email protected] tags: feat/attachments, main, trunk | |
| 00:01 |
feat(sync): per-store artifact size budget on the receive path
HandleOpts.MaxStoredBytes (internal and public) caps how many bytes one pushed artifact may occupy in blob.content as stored: a cfile card's stored form, otherwise the blob.Compress form of the file card's payload (the delta for a delta card). A plain payload whose compression bound fits is not compressed just to measure it. An artifact over the budget fails the request (h.fail): one error card naming the hash, stored size and limit, plus the file name and check-in when a crosslinked check-in already lists the phantom. The request transaction rolls back, so nothing from the round is stored and FilesReceived is 0. Stock fossil 2.28 prints the error on push. 0 keeps today's behaviour; clone and pull serving are not limited. Related to #459. leaf check-in: bd2efd6d5a user: [email protected] tags: feat/receive-size-budget, main, trunk | |
|
2026-10-28
| ||
| 23:43 |
perf(content): bound and test the memo's compact trees
Count the decoded file set a tree index keeps as the next difference's base toward memoTreeBytes, check a decoded id's gap without wrapping in uint64, and say what cloning the index on publish costs (about 0.5ms for fossil-scm.org's whole history, BenchmarkTreeIndexClone). TestMemoWideTreesMatchFresh classifies every cone over wide trees that rename, delete and add files, in all three manifest forms, with chains of differences 15 long and with a limit that starts the index again, before and after the store gains check-ins; a branch heads the chains trunk trees continue, so a trunk horizon decodes trees whose chain starts outside its held set. check-in: 7ba1eb6915 user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 23:40 |
Merge remote-tracking branch 'origin/main' into perf/memo-tree-encoding
# Conflicts: # CHANGELOG.md check-in: a90035689e user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 23:01 |
Merge pull request #520 from danmestas/feat/demand-fetch-reads
feat(horizon): targeted demand fetch for reads below the horizon check-in: c63cab2f36 user: [email protected] tags: main, trunk | |
| 22:58 | Keep blob.Load's query text, which read-count tests match on leaf check-in: 9e4f80b2df user: [email protected] tags: feat/chunked-blobs, main, trunk | |
| 22:52 |
Record chunked length in blob.content and verify parts on read
Review of the chunked-blob change found a missing last part read back short with no error, and a chunked write outside a transaction could leave a torn row that looked held. A chunked row now keeps its stored length in blob.content as an INTEGER. Reads check the parts run unbroken from seq 0, are full-sized but for the last, and add up to that length; anything else is ErrPartsCorrupt, and a NULL content is no longer mistaken for a chunked one. StoredLenSQL reads the length off the row and needs no schema probe. Chunked writes, and the phantom fill around them, run in a savepoint of the caller's transaction or a transaction of their own, so a failed part leaves nothing behind. A value needing more than 4096 parts is an error, not a panic, since stored values can come from peers. The cone and sparse local payload reads use ReadStoredExact, which loads a value only at the length already budgeted for. MaxValueBytes is documented as process-wide, and unversioned content as not chunked. check-in: 0fc4d176c3 user: [email protected] tags: feat/chunked-blobs, main, trunk | |
| 22:49 | Merge remote-tracking branch 'origin/main' into feat/demand-fetch-reads check-in: 2eb8cc938d user: [email protected] tags: feat/demand-fetch-reads, main, trunk | |
| 22:47 | Merge remote-tracking branch 'origin/main' into feat/chunked-blobs check-in: 0f72c73fe6 user: [email protected] tags: feat/chunked-blobs, main, trunk | |
| 22:44 | Merge remote-tracking branch 'origin/main' into perf/memo-tree-encoding leaf check-in: 6ae0bf4b3d user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 22:44 |
perf(content): read trees lazily again, kept in the compact encoding
A full read of every tree with the graph made a cold classification on fossil-scm.org's clone three to four times slower, which an origin that starts cold often cannot afford. Walks read a tree when they first need it, as before, and the memo keeps what they read as a treeIndex (interned ids, delta-varint sets, full manifests as differences), replaced on each publish so views read it without the lock. memoTreeBytes now bounds that encoding, which holds the whole history of fossil-scm.org in about 11 MiB; past it the index starts again. HZ-6.2-10 stays partial: trees are still read on first use, not with the graph. check-in: b53551c192 user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 22:41 |
fix(horizon): place the held set once per read; annotate falls back when the peer is short
- manifest.Placement computes the horizon's held set at most once per operation, so an annotate walk or a whole-check-in diff no longer rebuilds the check-in graph on every failed read. - AnnotateContext whose peer cannot supply a version returns the partial result, the lines past C marked BelowHorizon, as Annotate does without a peer; only a cancelled context fails it. - AnnotatedLine documents that BelowHorizon lines carry C's identity and that a partial annotate is signalled only by those marks. check-in: 02a2ea3214 user: [email protected] tags: feat/demand-fetch-reads, main, trunk | |
| 22:23 |
fix(horizon): label only absences below C; annotate fetches what it walks
Review follow-ups on the demand fetch for reads below the horizon: - A read is refused as below the horizon, and demand-fetched, only when its check-in lies outside the held set K; an unheld payload above C, such as one outside the store cone's paths, keeps its own error and is not fetched. - Annotate no longer refuses without a peer: on a content-horizon store it reports the lines it cannot attribute past C at the horizon, marked BelowHorizon, as a structural store does. AnnotateContext fetches each version as the walk reaches it, so nothing the walk does not read is fetched, up to 200 payloads; past that it returns the partial result. - diffWholeCheckin reports a failed structure classification, and the read paths take the caller's context through to the fetch. - Tests: misclassification above C, annotate over-fetch, the partial result over the limit, and a structural peer withholding the payload. check-in: 52f026832e user: [email protected] tags: feat/demand-fetch-reads, main, trunk | |
| 21:55 |
feat(horizon): targeted demand fetch for reads below the horizon
ReadFileContext, ReadFileAtContext, AnnotateContext and DiffContext take RequiredContentOpts and, when a read needs content a horizon store does not hold, fetch exactly the artifacts it names from the peer and read again (draft-fossil-horizon-00 4.4): the payload, and on a structural store first the check-in's manifest, baseline and nodes. The store cone and its horizon do not move; fetched artifacts are held content. Reads now refuse with content.MissingBelowHorizon, which matches ErrBelowHorizon and names the horizon. Annotate gathers every missing version along its walk into one round and Diff both sides; a read over one round's gimme budget is refused naming DeepenHorizon. Closes #489 leaf check-in: 8821596379 user: [email protected] tags: feat/demand-fetch-reads, main, trunk | |
| 21:53 |
Store blobs over a hosted value limit across blobpart rows
A hosted SQLite that caps value size (a Durable Object's 2 MB) cannot hold a large file's stored blob in one blob.content value. With the new db.DriverConfig.MaxValueBytes set, a stored value over the limit is written in 1,000,000-byte parts to blobpart(rid, seq, content), created on first use, leaving blob.content NULL and blob.size the expanded length, so phantoms (size < 0) stay unambiguous. Chunking sits below compression: hashes, deltas and the wire format are unchanged. internal/blob owns the seam (ReadStored, WriteStored, InsertStored, StoredHead, DropStored, SweepParts and two scan expressions), and every direct reader or writer of blob.content now goes through it: delta rewrite and undelta, receive, clone send and walk, compaction, sparse demotion, seed drop, shun purge, horizon cost and cone preparation. Zero, the default, keeps every value inline and creates no table, so local stores stay byte-identical. A store with blobpart rows is not readable by stock fossil; enable it only for hosted backends. Closes #459 check-in: 1fd12b3ed3 user: [email protected] tags: feat/chunked-blobs, main, trunk | |
| 21:50 |
Merge pull request #519 from danmestas/conf/hz-4-1-1-zit-scope
conformance: HZ-4.1-1 scoped to zit and go-libfossil origins check-in: 1455a3803e user: [email protected] tags: main, trunk | |
| 21:26 |
perf(content): read the memo's trees with its graph, as interned id sets
The origin classification memo now reads the F cards of every tree in the store once, with its references, and extends them by appended check-ins (draft-fossil-horizon-00 §6.2, HZ-6.2-10). Blob names are interned to uint32 ids, each tree's file set is a sorted delta-varint id list, and a full manifest is kept as its symmetric difference from the previous full manifest read, at most 15 links from a piece kept whole, decoded through a 16-entry LRU per view. A store whose index would pass memoTreeBytes keeps none and falls back to the bounded cache of walked trees. On a clone of fossil-scm.org the trees take 11 MiB (the walked-tree cache held 50 MiB for two horizons), the memo's retained heap halves and peak in-use heap drops from 345-524 MiB to about 170 MiB. Tracked in #463. check-in: 1cb9e11a65 user: [email protected] tags: main, perf/memo-tree-encoding, trunk | |
| 21:24 | docs: regenerate conformance data for HZ-4.1-1 check-in: 71eb242f08 user: [email protected] tags: conf/hz-4-1-1-zit-scope, main, trunk | |
| 21:14 |
conformance: HZ-4.1-1 scopes horizon origins to zit and go-libfossil
Drop the stock-fossil caveat from the row, so it reports COVERED, and probe zit's reply to req-clusters under a horizon pragma (after a dense control). leaf check-in: e9eb2cabac user: [email protected] tags: conf/hz-4-1-1-zit-scope, main, trunk | |
| 14:48 |
Merge pull request #516 from danmestas/perf/cone-clone-resend
perf: carry a cone clone's forwarded delta chains across rounds check-in: b85673a6cb user: [email protected] tags: main, trunk | |
| 14:33 | Merge remote-tracking branch 'origin/main' into perf/cone-clone-resend check-in: 8f0f4fb0f5 user: [email protected] tags: main, perf/cone-clone-resend, trunk | |
| 14:33 |
Merge pull request #517 from danmestas/perf/cone-clone-rounds
fix(content): classify a fossil-written store's file versions from its tables check-in: d3574f0c74 user: [email protected] tags: main, trunk | |
| 14:24 | Merge remote-tracking branch 'origin/main' into perf/cone-clone-rounds check-in: a40dd502cd user: [email protected] tags: main, perf/cone-clone-rounds, trunk | |
| 14:22 |
docs(content): say the file-version decision applies to every store
The mlink-named, unclaimed versions are taken as file content in a store with the non-artifact record too, including this library's own between a Checkin that commits an artifact-shaped file and the sweep that links it. The comment now says so, and that the window closes as the sweep's batches add the claims the memo follows. check-in: dd3f875e99 user: [email protected] tags: main, perf/cone-clone-rounds, trunk | |
| 13:58 |
fix(content): keep a partial non-artifact record from reading old files
A push into a store fossil wrote starts the non-artifact record with what arrived, and loadFiles then took only the record's versions as file content: every older version went back to be read raw, past the budget on a real repository. File versions are now the record's together with those mlink names and no claim table names (fileVersionsSQL), in a full load and in a memo's extension alike, and the memo's prefix counts the claims in every store, since file versions follow them whether or not a record exists. The horizon memo conformance case that pushes a manifest ahead of its blob into such a store now extends by the arrivals again. leaf check-in: 9cc2297ef8 user: [email protected] tags: main, perf/cone-clone-rounds, trunk | |
| 13:35 |
fix(content): follow a record-less store's claim tables in the memo
Without the non-artifact record, file versions are those mlink names and no claim table names, and a sweep linking an artifact late adds claims without adding a blob. The memo's store prefix now also counts the rids the claim tables name at or below its top (claimRows; distinct rids, so a check-in's propagated tags do not move it), which settled checks before extending, and an extension takes as file content the old versions the arrivals' mlink rows name that no claim table names, as it does with the record. loadFiles' comment now says what the fallback decides rather than claiming a proof: an unlinked blob that parses as an artifact is the file mlink says it is, elided outside the cone, and a corrupt out-of-cone version is elided unread. Tests pin both. check-in: 40b018695a user: [email protected] tags: main, perf/cone-clone-rounds, trunk | |
| 12:47 |
fix(content): classify a fossil-written store's file versions from its tables
A store this library crosslinked records each blob it found to be no artifact, and classification skips the file versions among them. A store fossil wrote has no such record, so classification read every file version raw and exceeded its byte budget: on a copy of fossil-scm.org's repository it failed on every request. A cone clone's walk then kept no base it had not reached yet, sent every in-cone version whole, and fit two or three 2-4 MB sqlite3.c texts into a 16 MB round: about 390 rounds and 30 minutes, where a dense clone takes 8 rounds. Without the record, a version that mlink names and no table an artifact's crosslink writes claims is file content too, the proof the cone walk's knownFile already relies on; a table the store lacks claims nothing. That clone now takes 12 rounds and 9 minutes, verifying the same. Related to #465. check-in: 4536dae44c user: [email protected] tags: main, perf/cone-clone-rounds, trunk | |