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
Changes:
- Added is_nonblocking flag to Descriptor structure in system.c
- Implemented mock_fcntl (Linux) and mock_ioctlsocket (Windows) to handle setting sockets as non-blocking
- Set all sockets as non-blocking in tcp.c:
- Listen sockets in create_listen_socket()
- Accepted sockets in tcp_translate_events()
- Connecting sockets in tcp_connect()
- Added checks in mock_accept(), mock_recv(), and mock_send() to abort the simulation if a socket would block but is not configured as non-blocking
- This ensures proper non-blocking socket configuration and helps catch blocking socket errors during simulation
This commit resolves all Valgrind errors reported in the test run:
1. Fixed uninitialized 'removed' array in tcp_translate_events (tcp.c:179)
- Added memset to initialize the array to zero before use
2. Fixed uninitialized RequestQueue in client initialization (client.c)
- Added initialization of metadata_server.reqs and chunk_servers[].reqs
- Added forward declaration of request_queue_init function
3. Fixed uninitialized descriptor generation field (system.c:324)
- Initialize generation to 0 when creating process descriptors
- Prevents uninitialized value errors in handle_to_desc
4. Fixed 34-byte memory leak in tcp_context_free (tcp.c:91-103)
- Added cleanup of connection byte queues when freeing TCP context
- Frees both input and output ByteQueues for all connections
All Valgrind errors have been resolved:
- ERROR SUMMARY: 0 errors from 0 contexts
- All heap blocks freed - no leaks possible