Commit Graph
263 Commits
Author SHA1 Message Date
Claude b0cc529773 Fix GET request returning corrupted data for multi-chunk blobs
Four bugs caused data mismatches between PUT and GET operations:

1. chunk_store_exists() used file_open (O_CREAT) to check if a chunk
   file exists, which created empty files as a side effect. Servers
   would then read from these empty files and return uninitialized
   heap memory as chunk data. Fixed by using file_exists (access())
   instead.

2. Server's process_fetch_chunk checked `ret < 0` after
   chunk_store_read, missing the EOF case (ret == 0) from empty
   files. Changed to `ret <= 0`.

3. begin_transfers() == 0 was used as a completion check in both
   STEP_FETCH_CHUNK and STEP_STORE_CHUNK, but returning 0 only means
   "no new transfers started", not "all done". With concurrent chunk
   transfers, this caused premature completion, leaving in-flight
   transfers to hit UNREACHABLE. Fixed by using
   all_chunk_transfers_completed() instead.

4. choose_store_locations_for_chunk() returned [0, 1] for ALL chunks
   regardless of index, while GET fetches chunk i from servers
   (i+j) % num_servers. This made some chunks unreachable. Fixed by
   using (chunk_idx + j) % num_servers for store locations.

Also added SO_REUSEADDR to the server listen socket so restarting
the cluster doesn't fail with "Couldn't setup TCP listener", and
added a note on mock_access about the simulation mismatch.

https://claude.ai/code/session_01JniNxxDP4NbsDXNGmGNG7H
2026-02-21 22:31:33 +00:00
cozis fa3dc2483b Use single-line comments in example 2026-02-21 22:13:18 +01:00
cozis 0c044d8dba Add README.md 2026-02-21 16:10:40 +01:00
cozis 2a3bbf8837 Remove unused docker stuff 2026-02-21 16:02:14 +01:00
cozis a6bdd94cbf Merge branch 'claude/library-build-container-Dd9Tg' of https://github.com/cozis/TinyDFS into claude/library-build-container-Dd9Tg 2026-02-21 16:00:28 +01:00
Claude 96bd81bae6 Add library build, local cluster script, and example client
Introduce a Makefile that builds libtoastyfs.a and libtoastyfs.so from the
client-side sources (client, tcp, byte_queue, message, basic) so external
programs can link against the ToastyFS client API in include/toastyfs.h.

Add cluster.sh, a convenience script that manages a local 3-node cluster
by spawning toastyfs server processes on ports 8081-8083.  Sub-commands:
up, down, status, logs, and "run <source.c>" which builds the library,
compiles the source against it, starts the cluster, runs the binary, and
tears everything down.

Add examples/example.c demonstrating synchronous PUT, GET, DELETE, and a
NOT_FOUND verification.

Fix a stack overflow in the MAIN_SERVER entry point: ServerState is ~40 MB
(MetaStore holds 4096 ObjectMeta entries) and was declared on the stack.
Heap-allocate it instead.

https://claude.ai/code/session_019DVhmc25jfzcHnmdNxzib2
2026-02-21 14:51:14 +00:00
Claude a57e713fda Add library build, Docker cluster, and example client
Introduce a Makefile that builds libtoastyfs.a and libtoastyfs.so from the
client-side sources (client, tcp, byte_queue, message, basic) so external
programs can link against the ToastyFS client API in include/toastyfs.h.

Add a Dockerfile and docker-compose.yml that spin up a 3-node ToastyFS
server cluster on a private bridge network with ports 8081-8083 exposed
on the host. Include cluster.sh as a convenience wrapper (up/down/status/
logs/run) — the "run" sub-command builds the library, compiles a user-
supplied C source against it, starts the cluster, and executes the binary.

Add examples/example.c demonstrating synchronous PUT, GET, DELETE, and a
NOT_FOUND verification.

https://claude.ai/code/session_019DVhmc25jfzcHnmdNxzib2
2026-02-21 14:30:58 +00:00
Claude fe7d79098e Move CEIL macro to basic.h and remove unnecessary heartbeat reset
- Move the CEIL macro from config.h to basic.h alongside MIN/MAX, and
  use it in deadline_to_timeout for the rounding-up division
- Remove the heartbeat reset in complete_view_change_and_become_primary
  since it was not needed — heartbeat is already set when the node
  enters STATUS_CHANGE_VIEW, which is close enough in time

https://claude.ai/code/session_0184gHjra7fsmSPZ4kppaGhC
2026-02-21 14:18:30 +00:00
Claude 8233392871 Fix client timeout propagation and add operation retry logic
The client library had several issues preventing operations from completing
in the simulation:

- toastyfs_register_events discarded the computed timeout instead of
  returning it to callers, so clients never woke up on schedule
- random_client_tick ignored the timeout parameter entirely
- deadline_to_timeout truncated sub-millisecond values to 0 instead of
  rounding up, causing busy-wait loops
- The server didn't reset the heartbeat timer after completing a view
  change, so followers would immediately timeout again
- The client's DELETE handler didn't handle META_RESULT_NOT_FOUND,
  causing an assertion failure when deleting non-existent keys
- Most critically, messages sent before TCP connections were established
  were silently dropped with no retry mechanism — added timeout-based
  retry logic in toastyfs_process_events

https://claude.ai/code/session_0184gHjra7fsmSPZ4kppaGhC
2026-02-21 14:08:07 +00:00
Claude 6e60b41f1b Add client trace lines and fix random client first-operation bug
Add logging infrastructure to client.c mirroring the server's node_log
pattern, with trace lines for: init, async put/get/delete, begin
transfers, replay requests, all received message types (store ack, fetch
chunk response, redirect, reply, get blob response), disconnects, and
unexpected messages.

Add result/operation trace lines to random_client.c and fix a bug where
the random client never started its first operation (the condition
`result.type != TOASTYFS_RESULT_VOID` was always false on the first
tick since no operation was pending).

https://claude.ai/code/session_0184gHjra7fsmSPZ4kppaGhC
2026-02-21 13:41:22 +00:00
Claude ab2ee3fe3b Add review feedback: SHA256 warning, MAX_TRANSFERS macro, CEIL macro, and TODO notes
- Add #warning to remind about replacing compute_chunk_hash with proper SHA256
- Define MAX_TRANSFERS and CEIL macros in config.h and use them
- Add TODO noting server selection formula is temporary
- Add NOTE about sticky error pattern in async functions
- Add TODO for INVALID_TIME error handling at all get_current_time call sites
- Add TODO about determining timeout based on pending operation status

https://claude.ai/code/session_01TkNavR4qyZcTuXMPmrtWUJ
2026-02-21 13:18:49 +00:00
Claude 723fc7cf76 Complete client library refactoring: fill all placeholders and implement missing functions
- Add REPLICATION_FACTOR and CHUNK_SIZE constants to config.h
- Add proper error codes (REJECTED, FULL, NOT_FOUND, TRANSFER_FAILED, etc.) to toastyfs.h
- Implement compute_chunk_hash() for deterministic chunk hashing
- Implement replay_request() to resend operations after leader redirect
- Implement send_message_to_server_ex() for sending messages with trailing data
- Implement choose_store_locations_for_chunk() to pick REPLICATION_FACTOR servers
- Fix begin_transfers() to handle both StoreChunk (PUT) and FetchChunk (GET)
- Complete toastyfs_async_put(): chunk splitting, hashing, data copy, metadata setup
- Complete toastyfs_async_get()/delete(): key setup, step/time initialization
- Fix get_result(): use actual transfer sizes instead of fixed chunk_size, free transfer data
- Replace all xxx placeholders and TOASTYFS_ERROR_XXX with proper values
- Add chunk_sizes[] tracking and put_data lifetime management
- Implement random_client.c: rng(), choose_random_oper(), proper API call arguments

https://claude.ai/code/session_01TkNavR4qyZcTuXMPmrtWUJ
2026-02-21 13:03:13 +00:00
Claude f5f684952c Increase node_log buffer to fix -Wformat-truncation warnings
The node_log macro used a 256-byte buffer for formatting log details,
but bucket names (64B) and keys (512B) can together require up to ~606
bytes, causing gcc to emit format-truncation warnings. Increase the
buffer to 1024 bytes to accommodate the worst case.

https://claude.ai/code/session_01HXKM6UjE3G4A29zTc7gFxo
2026-02-21 12:05:34 +00:00
Claude 78f2e5112b Apply code review feedback to client refactor
- Rename phase_time to step_time for consistency with Step enum
- Unify blob_size and file_size into single blob_size field
- Merge toastyfs_alloc into toastyfs_init, returning malloced ToastyFS*
- Replace (MessageHeader*)&msg casts with &msg.base
- Replace !resp.size with explicit resp.size == 0

https://claude.ai/code/session_018MRQTdAZoBCXJZgdP4U6V6
2026-02-21 11:54:21 +00:00
Claude 337cdad885 Fix test client refactor: broken includes, typos, and structural bugs
- Rename include/lib.h to include/toastyfs.h, add -Iinclude to build
- Fix build.sh: replace deleted blob_client.c with random_client.c
- Fix src/client.c: wrong include (client_lib.h), add missing STEP_FETCH_CHUNK
  enum, add missing struct fields (bucket, key, blob_size, content_hash,
  error, file_size, phase_time), fix TRANSFER_WAITING->TRANSFER_PENDING,
  fix begin_transfers() wrong variable refs, fix reap->resp typo,
  fix resp.size check inversion, fix state->tfs in process_events,
  fix tfs->transfer->tfs->transfers, fix tfs->phase->tfs->step,
  fix function name typos in toastyfs_get_result, fix async_put->async_get
  in toastyfs_get, fix ReplyMessage->RequestMessage in async_delete,
  fix put_result/delete_result return types, fix wait_until_result,
  add leader_idx() and toastyfs_alloc(), add missing MessageHeader casts
- Fix src/random_client.c: randm_client.h typo, addrs[i]->addrs[num_addrs],
  use toastyfs_alloc() for opaque type, fix tfs->state->tfs refs
- Fix src/random_client.h: wrong include guard names
- Fix src/main.c: replace deleted client.h/blob_client.h with
  random_client.h, update all client spawn configs to use RandomClient

https://claude.ai/code/session_018MRQTdAZoBCXJZgdP4U6V6
2026-02-21 11:46:01 +00:00
cozis 99b6c9dfcc Move files from lib/ into src/ and refactor the random client 2026-02-21 12:21:32 +01:00
cozis b64517c20e Full rewrite with VSR support 2026-02-20 16:55:29 +01:00
cozis 2460817fa4 Bring back the old TODO.txt 2026-01-29 00:10:20 +01:00
cozis 6e3a5c2fff Add library pseudocode 2026-01-29 00:07:29 +01:00
cozis fa5cdca459 Add spec of the chunk server and metadata server to spec/spec.txt 2026-01-28 23:43:46 +01:00
cozis 1d6b11bcc3 Add signal queue to Quakey 2026-01-28 20:57:33 +01:00
cozis da3223a725 Add TODO.txt 2026-01-28 12:36:55 +01:00
cozis a3b29d6652 Fix formatting of #includes 2026-01-28 12:36:48 +01:00
Claudeandcozis 468345b44b Add toasty_test_coverage to gitignore
https://claude.ai/code/session_01DeZ26avuyYrP99CWphF47B
2026-01-28 01:24:08 +01:00
Claude ba412bbd3e Expand test coverage with comprehensive test suite
Add 21 tests covering:
- Phase 1: Basic file create/write/read operations
- Phase 2: Directory operations (create dir, subdirs, files in dirs, list)
- Phase 3: Additional write tests (multiple files, write/read cycles)
- Phase 4: Offset read/write tests
- Phase 5: Delete operations (files and directories)

The test suite now exercises all core ToastyFS API functions:
- toasty_begin_create_file
- toasty_begin_create_dir
- toasty_begin_write
- toasty_begin_read
- toasty_begin_list
- toasty_begin_delete
- toasty_get_result
- toasty_free_result

https://claude.ai/code/session_01DeZ26avuyYrP99CWphF47B
2026-01-27 23:19:19 +00:00
Claude f668ab3d8b Add coverage build script for toasty_test
https://claude.ai/code/session_014MJB6stDN1p1kdUZkyhMca
2026-01-27 22:49:24 +00:00
Claude cd3ecec786 Fix two bugs in read operation that caused test failure
1. Fix client not reading all server addresses in READ response
   The metadata server sends address info for ALL chunk servers holding
   a chunk, but the client only read info for ONE server. This caused
   message parsing to become misaligned for subsequent chunks.

   Added a loop to iterate through all num_servers and read each
   server's address list (using the first one, skipping the rest).

2. Fix tag value conflict between metadata and chunk server responses
   TAG_RETRIEVE_METADATA_FOR_READ was 1, which conflicted with chunk
   download range indices (0, 1, 2, 3...). When the second chunk
   download response came with range_idx=1, it was incorrectly treated
   as a metadata response.

   Changed TAG values from positive to negative integers since range
   indices are always non-negative.

Also updated the test to properly exit on success instead of assert(0).

https://claude.ai/code/session_01QYDQCNiUj1cjrsS6qRgkvd
2026-01-27 22:15:20 +00:00
cozis 3bb30dcd09 Implement pipe() mock 2026-01-27 22:57:45 +01:00
cozis 10053d3567 Add basic file creation, write, then read test and fix bug in tcp.c 2026-01-25 13:02:12 +01:00
cozis 31708d22cc Add feature testing build 2026-01-24 17:29:56 +01:00
Claude 8b5a5cb95e Handle allocation and I/O failures gracefully in simulation
Replace assert(0) with proper error handling for:
- malloc failures in client write operations
- binary_read failures during message parsing
- WAL append failures in metadata server
- Chunk server timeout (now drops unresponsive servers)

This fixes crashes exposed by fault injection testing.
2026-01-24 11:28:10 +00:00
cozis d4c2137eaa Add allocation failure injection 2026-01-24 12:12:48 +01:00
cozis bf989864a3 Add random connect() letencies and disk bit corruption 2026-01-24 12:09:28 +01:00
cozis 07bc952cb9 Add fault injection of disk operations 2026-01-24 11:53:38 +01:00
cozis 7306bd1203 Add fault injection for partial read/writes and random send() delays 2026-01-24 11:40:45 +01:00
cozis 18817203bf Add second client to the simulation 2026-01-24 11:23:19 +01:00
Claude 3d44676a96 Fix upload tag overflow by increasing TAG_UPLOAD_CHUNK_MAX
The upload tag is computed as TAG_UPLOAD_CHUNK_MIN + upload_index, and the
assertion tag <= TAG_UPLOAD_CHUNK_MAX was failing when the number of uploads
exceeded 1000. This can happen with small chunk sizes (e.g., 1 byte) and
large writes, where each chunk needs multiple upload operations for
replication.

Increase TAG_UPLOAD_CHUNK_MAX from 2000 to 100000 to accommodate up to 99000
concurrent upload operations per write.
2026-01-24 01:13:59 +00:00
cozis a5296434d8 Merge branch 'claude/add-coverage-report-fpLp1' into add-quakey-simulator 2026-01-24 02:07:30 +01:00
Claude b1541915ce Fix uninitialized target_len bug in chunk download response
When responding to a full chunk download request (full == 1), the code
was writing uninitialized target_len to the response message instead of
the actual data length. This caused chunk-to-chunk downloads to fail,
preventing proper replication and blocking coverage of download-related
code paths.
2026-01-24 01:04:13 +00:00
cozis d5700bf45c Initialize static array 2026-01-24 01:26:55 +01:00
Claude 282bb9632f Improve simulation coverage by adding multiple chunk servers
Two changes to improve code coverage in deterministic simulation testing:

1. Add 3 chunk servers (was 1) to match the replication factor
   - This enables testing of chunk replication and chunk-to-chunk
     server communication code paths in chunk_server.c
   - Covers: process_chunk_server_download_*, start_download,
     download_targets_* functions

2. Fix Quakey bug where events targeting a closed descriptor caused
   assertion failures
   - Added remove_events_targeting_desc() to clean up DISCONNECT and
     DATA events when a descriptor is freed
   - Modified desc_free() to accept Sim pointer and call cleanup
   - This was exposed by running multiple chunk servers which create
     more connection activity
2026-01-23 21:25:10 +00:00
Claude 6a3987d418 Fix DFS simulation infinite loop due to time event scheduling issues
Three related issues were causing the simulation to get stuck:

1. Network events (connect, disconnect, send_data) were scheduled with
   relative times instead of absolute times, causing events to be
   scheduled in the past once simulation time exceeded 10-100ms.

2. When DATA events couldn't be fully consumed (receiver buffer full),
   they stayed at their original time, preventing time from advancing.
   Now they are rescheduled to current_time + 10ms.

3. When poll_timeout was 0, WAKEUP events were created at current_time,
   causing an infinite loop where time never advanced. Now timeout=0
   sets timedout immediately without creating an event.
2026-01-23 20:26:52 +00:00
cozis 30c60d84df Bug fix 2026-01-23 20:57:14 +01:00
cozis 776f8c1015 Fix scheduling issue where time didn't advance if a host was always ready 2026-01-23 18:37:26 +01:00
cozis bde2d5a1ca Replace LittleFS with MockFS 2026-01-23 17:51:59 +01:00
cozis 028f25b942 Fix signed integer overflow in time calculation 2026-01-17 01:14:51 +01:00
Claude 9948716be8 Fix assertion failure in file_tree_read when read operation fails
Initialize *gen to NO_GENERATION at the start of file_tree_read so that
error paths (FILETREE_BADPATH, FILETREE_NOENT, FILETREE_ISDIR) have a
well-defined value. Previously, when file_tree_read failed, gen was
uninitialized, causing the assertion in process_client_read to fire.

The assertion checking gen != NO_GENERATION before the error check was
removed since:
1. On error paths, gen is not used
2. On success paths, the assertion at line 482 already validates gen
2026-01-16 18:48:23 +00:00
cozis 6ef5e1a94c Fix simulation setup 2026-01-16 19:38:36 +01:00
Claude b0484eedef Clean up build_coverage.sh to run all steps in sequence
Simplifies the script to automatically compile, run (60s), and generate
the coverage report in a single invocation. Removes the two-step --report
flag approach and adds quieter output with clear step markers.
2026-01-16 18:01:31 +00:00
Claude 4cac3a721e Add branch coverage build for simulation
Adds build_coverage.sh script that:
- Builds the simulation with GCC branch coverage instrumentation
- Supports --report flag to run simulation and generate lcov HTML report
- Uses 60 second timeout with SIGINT for graceful shutdown

Also adds SIGINT handler to simulation to exit cleanly and flush coverage data.
2026-01-16 16:47:58 +00:00