S1: the write side learns to stream
osFileStart, osFileWrite and osFileDone are the mirror of osFileInfo and osFileBlock. A program can now write a file it never holds: Pour writes twelve blocks and a tail while keeping 256 bytes of it at a time, and the host tool reads all 3,112 bytes back with every block where it was put. ONE WRITE IS OPEN AT A TIME AND COSMOS HOLDS IT. Reading needs no state - a name and an index are the whole question - but writing safely does, because the new file has to exist before the old one is thrown away and something has to remember which temporary belongs to which name. Keeping that here means the careful order is written once instead of in every program that streams. Nothing already on the disk is touched until osFileDone, so a disk without room says so while the old file is still there. That is stronger than osFileSave can manage, where the size is only known once the caller has every byte in hand. osFileSave stays: Edit and Files hand over whole documents and have no reason to learn any of this. osFileWrite refuses an index past the end of the file, and that refusal is not politeness. Files are contiguous, so block nine of a three block file is a real block belonging to something else, and writing it would put one file's bytes inside another with nothing anywhere saying so. Checked both ways: the tail block is allowed and the one past it is not. Three bugs, all of them the same shape - a register or pointer used for two things at once: DP3 carried the block count in and was popped high byte first, which is the wrong way round from every reader in the system and made the count two hundred and fifty six times too big. sbfsStreamStart took the name in DP0 and then wanted DP0 for something else before it had read it, so it walked whatever it last pointed at and reported that it could find no room. sbfsStreamWrite kept the caller's block in DP3 across a find - DP3 being the pointer a return does not put back, which is exactly why the find uses it too. What went to the disk was whatever the scan last looked at. It goes in memory now, and the file is correct because every block says which block it is; a check on the length alone would have passed all three of these. Writing no longer finds the file for each block either. Nothing moves a file once it is made, so where it starts is settled when the temporary is created. That was not even slow - a scan stops the moment it matches - but it was a walk of the directory per block for an answer that cannot change, and it is 28 per cent of the cost of writing forty blocks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
7cd5e34347
commit
9f7dffdeca
@@ -81,6 +81,28 @@
|
||||
; relative to here, so a program given a directory to work in can say "notes.txt" and mean
|
||||
; the one in it.
|
||||
osChangeDir 0d28
|
||||
|
||||
; ---- Writing a file a block at a time ----
|
||||
;
|
||||
; The mirror of osFileInfo and osFileBlock, and the way to write something too big to hold
|
||||
; in memory. osFileSave stays for a whole document handed over at once, which is what a
|
||||
; text editor has and what most programs want.
|
||||
;
|
||||
; ONE WRITE IS OPEN AT A TIME AND THE SYSTEM HOLDS IT. Reading needs no state - a name and
|
||||
; an index are the whole question - but writing safely does, because the new file has to
|
||||
; exist before the old one is thrown away and something must remember which temporary
|
||||
; belongs to which name. Keeping that here means the careful order is written once instead
|
||||
; of in every program that streams.
|
||||
;
|
||||
; Nothing that already exists is touched until osFileDone, so a disk without room says so
|
||||
; while the old file is still there.
|
||||
;
|
||||
; osFileStart is told the size the way an entry holds one, blocks and a tail, rather than a
|
||||
; count of bytes - so it reaches the whole disk. osFileSave is handed a byte count in two
|
||||
; registers and cannot write more than 65,535.
|
||||
osFileStart 0d29 ; DP0 names it, DP3 is whole blocks, A is bytes in the tail.
|
||||
osFileWrite 0d30 ; DP1 is the block, A and B together are which one, from zero.
|
||||
osFileDone 0d31 ; No arguments. The temporary takes the name.
|
||||
; Q is zero if it read, DP3 is how many of its bytes are the file's:
|
||||
; a whole 0d256 except in a last block that is short. That count is
|
||||
; why DP3 answers and not a register - 0d256 does not fit in a byte,
|
||||
|
||||
Reference in New Issue
Block a user