Commit Graph

11 Commits

Author SHA1 Message Date
michael stack 764222b18b Fix BulkLoad test non-determinism and add fault injection settings
- Use nondeterministicRandom() in MockS3Server to avoid diverging simulation state
- Add faultInjection=false to BulkLoad tests to prevent timeout failures
- Add extraMachineCountDC=3 for non-overlapping teams in HA configs --
  makes it so can allow HA on these tests (Had been off up to this).
2026-01-30 10:53:25 -08:00
michael stack ae93c620df Add BulkDump/BulkLoad integration tests with chaos and multi-range
Add two new simulation tests for BulkLoad restore integration:

  1. BackupS3BlobBulkLoadRestoreWithChaos.toml - Tests BulkDump/BulkLoad under
     aggressive S3 fault injection (15% error rate, 20% throttling, 10% delays,
     0.5% corruption) to validate resilience and retry mechanisms.

  2. BackupS3BlobBulkLoadRestoreMultiRange.toml - Tests BulkDump/BulkLoad with
     multiple non-contiguous backup ranges (backupRangesCount=5) to validate
     correct handling of multiple SST file sets and range boundaries.

  Both tests use snapshotMode=1 (BULKDUMP) and useRangeFileRestore=false
  (BulkLoad) to exercise the new SST-file-based backup/restore path.

  Fix BulkDump/BulkLoad race conditions and MockS3 concurrent writes

  - Fix race where failing BulkDump task incorrectly resets mode to 0
  - Fix MockS3 concurrent write collision using unique temp filenames
  - Add encryption metadata write verification
  - Add singleRegion config option to prevent HA in tests
  - Enable HA (multi-region) testing for BulkLoad tests
2026-01-28 11:00:20 -08:00
Michael Stack 10a63f9fa3
S3 Backup chaos in simulation (#12539)
Add chaos support to BackupS3BlobCorrectness test

    Implements chaos injection for the BackupS3BlobCorrectness workload following
    the pattern from S3ClientWorkload and BulkDumping chaos implementations.

    Features:
    - New BackupS3BlobCorrectnessWithChaos.toml test with four variants:
      Stable (no chaos), LightChaos, MediumChaos, HeavyChaos
    - Extended BackupS3BlobCorrectness workload with chaos parameters:
      enableChaos, errorRate, throttleRate, delayRate, corruptionRate, maxDelay
    - Conditionally uses MockS3ServerChaos when chaos is enabled

    Bug Fix:
    - Remove TraceEvent calls from lazy persistence initialization paths
    - TraceEvent can access GlobalConfig which may not be initialized yet
    - Fixes crash: Bad pointer dereference in GlobalConfig::get() during early S3 access

    This completes chaos coverage for all S3 operations in FoundationDB:
    - S3ClientWorkload: Direct S3 client operations
    - BulkDumping: Bulk data dump/load via S3
    - BackupS3BlobCorrectness: Backup and restore via S3

    Changes:
    - fdbserver/workloads/BackupS3BlobCorrectness.actor.cpp: chaos support
    - tests/slow/BackupS3BlobCorrectnessWithChaos.toml: new test configuration
    - tests/CMakeLists.txt: register new test
    - fdbserver/MockS3Server.actor.cpp: remove early TraceEvent calls
2025-11-06 11:06:51 -08:00
Michael Stack b9f1dce6ad
Add chaos to S3BulkDumping test. (#12522)
- Add chaos injection support to BulkDumping workload
- Added MockS3ServerChaos include to BulkDumping.actor.cpp
- Added chaos configuration options (errorRate, throttleRate, delayRate, corruptionRate, maxDelay)
- Enhanced _setup() to support both regular and chaos MockS3 servers
- Added detection for already-registered servers to avoid conflicts
- Configure chaos rates per-test to allow progressive intensity testing
- Created BulkDumpingS3WithChaos.toml test suite with 4 test scenarios:
  * Stable (0% chaos) - baseline
  * Light chaos (5-10%) - minor disruptions
  * Medium chaos (15-20%) - moderate disruptions
  * Heavy chaos (30-40%) - severe disruptions

This mirrors the S3ClientWorkloadWithChaos design and allows testing
BulkDumping resilience to S3 failures in simulation.

The validateBulkLoadJobHistory function incorrectly asserted that every
job in history had the same jobId, when it should have been searching
for a specific job. This caused crashes when multiple jobs existed in
history from cancellations/retries during chaos testing.

* Fix bulk load hangs with empty ranges and improve chaos test resilience

Empty Range Handling Fixes:
1. BulkLoadUtil.actor.cpp (bulkLoadDownloadTaskFileSets):
   - Fixed root cause where empty ranges were skipped entirely with 'continue',
     never added to localFileSets, causing FetchKeys to hang forever
   - Now creates empty BulkLoadFileSet entries for empty ranges to track them

2. BulkLoadUtil.actor.cpp (bulkLoadTransportBlobstore_impl):
   - Added hasDataFile() check before attempting S3 downloads
   - Skip data file download gracefully for empty ranges

3. storageserver.actor.cpp (tryGetRangeForBulkLoad):
   - Added hasDataFile() check to prevent calling getDataFileFullPath() on empty fileSets
   - Added empty result signaling: when all ranges are empty, send empty RangeResult
     with end_of_stream() to properly complete FetchKeys operations

4. storageserver.actor.cpp (bulk load SST ingestion):
   - Added hasDataFile() checks before accessing data file paths during SST processing

5. storageserver.actor.cpp (restoreDurableState):
   - Improved bulk load recovery robustness by using intersectingRanges() instead
     of exact range match during storage server recovery
   - Handle range boundary mismatches that can occur due to splits/chaos
   - Added comprehensive error logging for debugging recovery issues

Performance and Retry Improvements:
1. Added BULKLOAD_DOWNLOAD_RETRY_DELAY knob (2.0s for both simulation and production)
2. Added BULKLOAD_DOWNLOAD_MAX_RETRIES knob (20 for both simulation and production)
   - Total retry window: 20 retries × 2s = 40 seconds maximum
3. Reduced BLOBSTORE_MAX_DELAY_RETRYABLE_ERROR from 60s to 20s in production
4. Added retry limits to prevent infinite retry loops in bulk load downloads
2025-11-04 09:01:26 -08:00
Michael Stack ccd56bf7db
Implement MockS3ServerChaos: S3 Error Injection for Testing (#12515)
* Implement MockS3ServerChaos: S3 Error Injection for Testing

Add chaos injection system for MockS3Server following AsyncFileChaos pattern.
Tests S3BlobStore client resilience against realistic S3 failures.

- MockS3ServerChaos wrapper with configurable fault injection
- S3FaultInjector with error/throttle/delay/corruption rates
- Chaos support integrated into S3ClientWorkload
- Simplified URL parsing and improved error handling
- Multipart upload idempotency and BUGGIFY fix
- ChaosMetrics tracking for S3 events
- Comprehensive test suite with multiple chaos levels

Design doc: design/mocks3server_chaos_design.md
Tests: tests/slow/S3ClientWorkloadWithChaos.toml

Currently adds light/medium/heavy chaos to the simple s3client
test. Will follow-on with similar for bulkload via s3 and for
backup via s3.

* Mostly around registration of http server across test runs inside a workflow

* Formatting

* Missing state qualifier

* * fdbclient/S3BlobStore.actor.cpp
 Fix bug where we are accumulating headers across retries.

* fdbserver/MockS3Server.actor.cpp
* fdbserver/MockS3ServerChaos.actor.cpp
* fdbserver/include/fdbserver/MockS3Server.h
 Add check if we should persist mocks3 data.

* tests/slow/S3ClientWorkloadWithChaos.toml
 Use one mocks3, the one that does chaos for all loads.
2025-10-31 12:17:01 -07:00
Michael Stack 70e7bf8a34
Address nightly failure in fast/BackupS3BlobCorrectness.toml, seed 634541705 (#12524)
* Reduce expected duration wait

* Ameliorate test timing out by turning down the aggressiveness and
having connection failures run for the start of the test rather
than all through it; the backup/restore was struggling to complete
and could timeout before doing so.

Also address case where we were not being s3-like.

* fdbserver/MockS3Server.actor.cpp
 Backup can have two different clients uploading the same file. This is
 legit in s3; last file wins. Accommodate (file system was logging a
 SevError when second process went looking for .part file removed by
 first).

* fdbserver/tester.actor.cpp
 Allow setting how long connection failures run for.

* fdbserver/workloads/BackupS3BlobCorrectness.actor.cpp
 Return void rather than hang around -- was covering actual
 issues.

* tests/fast/BackupS3BlobCorrectness.toml
 Have the test run less virulently.

* Be more radical; turn off the chaos-making. We will be adding it back in a subsequent, controlled PR
2025-10-29 11:47:51 -07:00
Michael Stack 2c658719c4
Add persistence to MockS3Server for crash recovery and post-test analysis (#12516)
* Add MockS3 persistence

Add comprehensive persistence to MockS3Server for crash recovery and post-test
analysis.

Key Changes:
- MockS3 persistence: Objects/multipart uploads persist to simfdb/mocks3/:
        simfdb/mocks3/objects/<bucket>/<object>.{data,meta.json}
        simfdb/mocks3/multipart/<uploadId>.{state.json,part.N}
- Crash resilience: State restored on restart, survives process kills
- Virtual function guards: Prevent pure virtual crashes in MockS3RequestHandler
- JSON with rapidjson: Replace manual string building with Document API
- Actor workaround: Document 'state dummy' pattern for early returns
- Simulator: Allow mocks3 directory in simfdb validation
- Test scripts: Centralize PRESERVE_TEST_DATA cleanup logic
- Atomic writes prevent corruption, sorted loading ensures determinism

* Simplify createParentDirectories to use platform API

Replaced manual loop with single call to platform::createDirectory(),
which already handles recursive creation and EEXIST errors properly.
This is cleaner, more robust, and leverages well-tested platform code.

* Remove arbitrary 100MB file size limit from readFileContent

Removed hardcoded 100MB limit for MockS3 metadata file reads.
Metadata should be tiny (<1KB), and if it's unreasonably large,
that's a bug we should surface, not silently ignore with an
arbitrary threshold.

* Simplify deletePersistedFile by removing redundant fileExists check

Removed fileExists() check from deletePersistedFile wrapper since
IAsyncFileSystem::deleteFile() already handles missing files gracefully.
Kept the wrapper for centralized trace events and error handling across
10+ call sites in MockS3 persistence code.

* Replace magic numbers with named constants for file suffixes

Defined constants for MockS3 persistence file extensions:
- OBJECT_DATA_SUFFIX = ".data" (length 5)
- OBJECT_META_SUFFIX = ".meta.json" (length 10)
- MULTIPART_STATE_SUFFIX = ".state.json" (length 11)

Replaced all hardcoded length checks (10, 11) and string literals
throughout the file. This makes the code more maintainable and
self-documenting.

* Fix 'magic numbers'.. use defines

* Remove unused OBJECT_DATA_SUFFIX_LEN constant

Removed OBJECT_DATA_SUFFIX_LEN which was triggering -Werror in CI/CD.
This constant was never used in length checks (we only concatenate
the suffix, never measure it).

* Fix MockS3 blocking during multipart cleanup

Added periodic yielding (every 10 parts) in deletePersistedMultipart
to prevent blocking other MockS3 requests during large multipart upload
cleanup. Without this, deleting 110+ parts would take 4-5 seconds of
continuous file operations, causing S3 client requests to timeout with
operation_cancelled errors.

Fixes BulkDumpingS3 test failures where bucket existence checks would
get cancelled while MockS3 was busy deleting multipart files.

* Increase yield frequency in multipart cleanup (every 5 parts with 10ms delay)

Changed from yielding every 10 parts with delay(0) to every 5 parts
with delay(0.01). The previous fix wasn't aggressive enough - 110 parts
were still taking 10+ seconds to delete, causing HTTP request timeouts.

With this change:
- Yield twice as often (every 5 parts instead of 10)
- Add 10ms actual delay (not just event loop yield)
- Gives HTTP requests real time to be processed

Fixes persistent BulkDumpingS3 test failures.

* Increase multipart cleanup yield frequency (every 2 parts, 20ms delay)

Changed from yielding every 5 parts with 10ms delay to every 2 parts
with 20ms delay. The previous fix still allowed deletions to take 11+
seconds for 110 parts, causing HTTP timeouts at 6.5 seconds.

New behavior for 110-part uploads:
- Yields ~55 times (vs 22 previously)
- Total delay time: ~1.1s (vs ~220ms)
- Much more breathing room for concurrent HTTP requests

Fixes BulkDumpingS3 test failures with seed 1268929493.

* Refactor: Extract common cleanup_with_preserve_check function

Consolidates repeated test data preservation logic from three test scripts
into a single function in tests_common.sh.

Before: Each test had duplicate code checking PRESERVE_TEST_DATA and
conditionally shutting down servers.

After: All tests call cleanup_with_preserve_check() which handles both
the preservation check and server shutdown.

Changes:
- Added cleanup_with_preserve_check() to tests_common.sh
- Updated s3_backup_test.sh to use common function
- Updated s3client_test.sh to use common function
- Updated bulkload_test.sh to use common function

No functional change, just reduces duplication.

* Improve ACTOR state variable initialization comment

Expanded the comment explaining why state variables must be declared
before early returns in ACTOR functions. The previous comment was too
brief and didn't explain the underlying mechanism.

New comment explains:
- How the actor compiler creates internal Promise<T> objects
- What 'sendable' means (canBeSet() must return true)
- Why Promise initialization depends on state variable declarations
- What canBeSet() assertion failure you get if violated
- Clear correct vs wrong pattern examples

This addresses reviewer feedback asking what 'properly initialize
the actor's Promise object' means.

* Clarify ACTOR state variable initialization patterns

Expanded comment to show three valid patterns for state variable
initialization, addressing reviewer feedback about declaration vs
initialization.

Key additions:
- Pattern 2 shows declaring + initializing together (simpler)
- Pattern 1 shows declaring early, initializing later (conditional)
- Pattern 3 shows dummy variable when real vars come later
- Added 'CHOOSING A PATTERN' section with guidance
- Added NOTE about default constructor requirement

Clarifies that the reviewer's suggestion (declaring + initializing
together) is valid and often simpler. The declare-then-assign pattern
is mainly useful for conditional initialization or when constructor
might throw.

* Shorten ACTOR state variable initialization comment

Reduced from 66 lines to 27 lines while keeping essential information:
- What the issue is (canBeSet() crash)
- Why it happens (Promise init code generation)
- How to fix it (declare state var before early return)
- Correct vs wrong example

Removed verbose background explanations and multiple pattern variations.

* Clarify that state variable declaration alone is sufficient

Updated comment to emphasize the reviewer's point that just declaring
the state variable (without initialization) triggers Promise init.

Changes:
- Added 'Declaration alone is sufficient - initialization can happen later'
- Changed example to show declaration at top, initialization later
- Added NOTE for types without default constructors

This addresses jzhou77's feedback that declaring and initializing later
has the same effect as declaring+initializing together.

* Clarify ACTOR state variable comment with technical details

Rewrote comment to directly address reviewer feedback:

1. Explains what 'properly initialize Promise' means: The actor compiler
   generates a member initialization list (': member(value)') which ensures
   the Actor<T> base class and its Promise are initialized before any code runs.

2. Clarifies why TIMING matters: Compiler must see state variable before early
   return to generate the init list. Declaring it after is 'too late - compiler
   didn't see it early enough'.

3. Removed the NOTE about default constructors (less critical).

Based on proof from generated code showing state variables trigger member
initialization list generation.

* Add note about default constructor requirement for state variables

Addresses jzhou77's feedback: declaring 'state SomeType variable;' requires
a default constructor. If the type doesn't have one, you must initialize at
declaration: 'state MyType x(params);'

* With fault injection, a bucket exists can be cancelled. Allow. Don't log severity=40 for something that is going to happen

---------

Co-authored-by: stack <stack@duboce.com>
2025-10-27 16:12:03 -07:00
Michael Stack 6c78bcec65
Fix MockS3Server canBeSet() assertion failure. Seen on mac. (#12497)
* Fix MockS3Server canBeSet() assertion failure. Seen on mac.

- Fix UnsentPacketQueue pointer overwrite issue in MockS3Server; was
  overwriting existing response->data.content pointer.
- Replace 'new UnsentPacketQueue()' with 'discardAll()' to use existing content queue
- Remove conditional reference counting that could cause memory corruption
- Simplify clone() method to always return new instance
- Add null check on globals and aggressive clearing of currentProcess.

* ASSERT global id >= 0.
Comment on when currentProcess is nullptr

(Address review feedback)

---------

Co-authored-by: michael stack <stack@duboce.com>
2025-10-23 17:24:41 -07:00
Michael Stack 276a2b13c8
Use MockS3Server instead of seaweedfs for ctest. (#12412)
* Use MockS3Server instead of seaweedfs for ctest.
Avoid download of seaweedfs and the 25second startup.
Preserve the try-another-port if expected is occupied.
Preserve use of s3 if available.

* Call describeBackup w/ invalidVersion so metadata is written when blobstore url
2025-10-20 10:17:54 -07:00
Michael Stack 1ef779d854
Add HTTP range header support to mocks3 (#12410)
* Add HTTP range header support to support partial content requests.

Made storage global rather than instance-based.
Made safe against process context switching mid-insert.

Enabled tests  and made them test s3-ness (bucket in path, etc.)
Added range tests.
2025-10-02 15:36:38 -07:00
Michael Stack d45a17b657
Add a MockS3Server plus an s3client and bulkdumpings3 simulation test (#12279)
* Add a MockS3Server. Register it at 127.0.0.1:8080 on the simulated
network (simulated network intercepts requests for 127.0.0.1:8080
and does appropriate forwarding to s3 handler). Add two workloads,
one for s3client against 's3' and another that swaps in s3 as
backend for the BulkDumping test.

The Mock S3 Server is mostly generated (claude-sonnet-4) code. It
supports:
- Basic GET/PUT/DELETE/HEAD object operations
- Multipart uploads (initiate, upload parts, complete, abort)
- Object tagging (put/get tags)
- In-memory storage with deterministic behavior
- S3-compatible XML responses

* fdbserver/workloads/BulkDumping.actor.cpp
 Change this workload so it reads the transport to use
 from configuration file so can be used to test
 file-based and s3 bulk loading. If the transport is
 blobstore/s3, start up the mocks3server in _setup.

* fdbserver/workloads/S3ClientWorkload.actor.cpp
 Simple workload to exercise s3client. Starts up the
 mocks3server in _setup.

* fdbclient/S3BlobStore.actor.cpp
 Check BUGGIFY before messing w/ status codes.

* fdbrpc/HTTP.actor.cpp
 Add defines and log if failed parse of status line.

* Disable global buggify if the toml file turns off buggify

* Remove disable of fault injection if BUGGIFY set

* Remove an irrelevant configuration
2025-07-29 14:30:28 -07:00