Expose BackupEngine C API additions: StopBackup and rate limiters#14722
Expose BackupEngine C API additions: StopBackup and rate limiters#14722rajsuvariya-stripe wants to merge 3 commits into
Conversation
Add rocksdb_backup_engine_stop_backup() to c.h and db/c.cc so that language bindings using the C API (e.g. Rust via librocksdb-sys) can cancel an in-progress backup without needing a custom C++ shim. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> Committed-By-Agent: claude
Add rocksdb_backup_engine_options_set_backup_rate_limiter() and rocksdb_backup_engine_options_set_restore_rate_limiter() to c.h and db/c.cc so that language bindings (e.g. Rust via librocksdb-sys) can pass a full RateLimiter object — including kAllIo mode for read+write throttling — without needing a custom C++ shim. The existing backup_rate_limit / restore_rate_limit uint64_t setters only throttle writes; these new functions expose the richer shared_ptr<RateLimiter> fields that override the uint64_t limits. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> Committed-By-Agent: claude
| } | ||
|
|
||
| void rocksdb_create_backup_options_set_flush_before_backup( | ||
| rocksdb_create_backup_options_t* options, unsigned char v) { |
There was a problem hiding this comment.
why not use a bool here instead of the unsigned char v?
There was a problem hiding this comment.
Good catch — <stdbool.h> is included and bool does appear in a few places (e.g. rocksdb_multi_get_entity_cf, rocksdb_load_latest_options, rocksdb_write_buffer_manager_*). However, those look like inconsistencies
introduced in newer additions rather than an intentional shift, because:
- The file explicitly documents the convention at line 40: "Bools have the type unsigned char (0 == false; rest == true)"
- The overwhelming majority of the file — including all existing backup engine option setters (set_share_table_files, set_sync, set_destroy_old_data, set_backup_log_files) — uses unsigned char
Staying consistent with the immediate family of backup functions and the documented convention seems like the right call here. That said, if you'd prefer we use bool to match the newer additions and move the file
toward bool uniformity, I'm happy to make that change.
There was a problem hiding this comment.
i am fine as long as code owners are fine with the format.
| rocksdb_create_backup_options_t* options, void* callback_arg, | ||
| void (*callback)(void* arg)) { |
There was a problem hiding this comment.
Curious - how do we plan to use the callback_arg. The C++ api will call the callback_function without any arguments (std::function<void()>) - so at best we can track the number of times the callback function was called -- but that can be achieved other ways as well instead of passing callback args to this translation layer.
There was a problem hiding this comment.
The C++ callback is std::function<void()> with no arguments. The C API bridges this by capturing callback_arg in a lambda that calls the C function pointer with that arg: [callback, callback_arg]]() { callback(callback_arg); }. This is the standard C idiom for stateful callbacks (same pattern as pthread_create, qsort_r, etc.) — it lets callers pass context without requiring global state. Without callback_arg, a Rust or C caller would have to use a global variable to track progress state.
| rocksdb_env_destroy(benv); | ||
| CheckNoError(err); | ||
|
|
||
| int progress_count = 0; |
There was a problem hiding this comment.
progress_count is just incremented through the callback function, but I don't see validations if it was ever incremented or called into.
There was a problem hiding this comment.
Fixed — added assert(progress_count > 0) after the backup call. Also set callback_trigger_interval_size = 1 when opening the backup engine so the callback fires even on the small test database (the default 4MB threshold would never be reached in a unit test).
| { | ||
| rocksdb_ratelimiter_t* limiter = | ||
| rocksdb_ratelimiter_create_with_mode(1024 * 1024, 100 * 1000, 10, 2, | ||
| 0); | ||
| rocksdb_backup_engine_options_set_backup_rate_limiter(bdo, limiter); | ||
| rocksdb_backup_engine_options_set_restore_rate_limiter(bdo, limiter); | ||
| rocksdb_ratelimiter_destroy(limiter); | ||
| } | ||
|
|
There was a problem hiding this comment.
can this test evolved to see if there's going to be any error in actually running the backup with provided rate limiter?
There was a problem hiding this comment.
Fixed in the latest commit. For the rate limiter test, added a block that opens a real backup engine with both backup_rate_limiter and restore_rate_limiter set, runs a backup against the live DB, and asserts no error is returned.
| extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_stop_backup( | ||
| rocksdb_backup_engine_t* be); |
There was a problem hiding this comment.
would like to see a test for this method too.
There was a problem hiding this comment.
Fixed in the latest commit. For stop_backup, added a call to rocksdb_backup_engine_stop_backup in the backup_with_progress_callback test after the backup completes (safe to call even when no backup is in progress, exercises the code path).
|
Hey @jaykorean - Can you help review this PR? Thanks! |
|
@hemal-stripe I'm sorry, I currently don't have bandwidth at the moment. Added my teammates to help out. |
✅ clang-tidy: No findings on changed linesCompleted in 3414.9s. |
Co-Authored-By: Claude Sonnet 4.6 <[email protected]> Committed-By-Agent: claude
27eed2a to
a23a485
Compare
|
@pdillinger @archang19 I have fixed the lint issues and removed the progress callback for now (I will raise a separate PR for that). Can you please review this PR now? |
Summary
Extends RocksDB's C API with two
BackupEnginecapabilities needed bylanguage bindings (e.g. Rust via librocksdb-sys) that consume the C API:
StopBackup: Add
rocksdb_backup_engine_stop_backup()to allow cancellingan in-progress backup.
Rate limiters: Add
rocksdb_backup_engine_options_set_backup_rate_limiter()androcksdb_backup_engine_options_set_restore_rate_limiter()to expose theshared_ptr<RateLimiter>fields onBackupEngineOptions. The existinguint64_tsetters only throttle writes; these expose the richerRateLimiterobject that supports read+write throttling (e.g.
kAllIomode).Test plan
db/c_test.ccoverStopBackupand rate limitersetter/getter roundtrips, plus opening a real backup engine with rate
limiters set and running a backup end-to-end
make checkpasses with no regressions