Expose BackupEngine C API additions: StopBackup and rate limiters (#14722)

Summary:
Extends RocksDB's C API with two `BackupEngine` capabilities needed by
language bindings (e.g. Rust via librocksdb-sys) that consume the C API:

- **StopBackup**: Add `rocksdb_backup_engine_stop_backup()` to allow cancelling
  an in-progress backup.

- **Rate limiters**: Add
  `rocksdb_backup_engine_options_set_backup_rate_limiter()` and
  `rocksdb_backup_engine_options_set_restore_rate_limiter()` to expose the
  `shared_ptr<RateLimiter>` fields on `BackupEngineOptions`. The existing
  `uint64_t` setters only throttle writes; these expose the richer `RateLimiter`
  object that supports read+write throttling (e.g. `kAllIo` mode).

Pull Request resolved: https://github.com/facebook/rocksdb/pull/14722

Test Plan:
- [x] New tests in `db/c_test.c` cover `StopBackup` and rate limiter
  setter/getter roundtrips, plus opening a real backup engine with rate
  limiters set and running a backup end-to-end
- [x] `make check` passes with no regressions

Reviewed By: pdillinger

Differential Revision: D107654882

Pulled By: xingbowang

fbshipit-source-id: f50c3989779e6a099113fec203231d47b9480cb9
This commit is contained in:
Raj Suvariya
2026-06-08 11:52:53 -07:00
committed by meta-codesync[bot]
parent a214d3f1f8
commit 0493154a73
4 changed files with 91 additions and 0 deletions
+18
View File
@@ -1385,6 +1385,10 @@ void rocksdb_backup_engine_info_destroy(
delete info;
}
void rocksdb_backup_engine_stop_backup(rocksdb_backup_engine_t* be) {
be->rep->StopBackup();
}
void rocksdb_backup_engine_close(rocksdb_backup_engine_t* be) {
delete be->rep;
delete be;
@@ -1466,6 +1470,20 @@ uint64_t rocksdb_backup_engine_options_get_restore_rate_limit(
return options->rep.restore_rate_limit;
}
void rocksdb_backup_engine_options_set_backup_rate_limiter(
rocksdb_backup_engine_options_t* options, rocksdb_ratelimiter_t* limiter) {
if (limiter) {
options->rep.backup_rate_limiter = limiter->rep;
}
}
void rocksdb_backup_engine_options_set_restore_rate_limiter(
rocksdb_backup_engine_options_t* options, rocksdb_ratelimiter_t* limiter) {
if (limiter) {
options->rep.restore_rate_limiter = limiter->rep;
}
}
void rocksdb_backup_engine_options_set_max_background_operations(
rocksdb_backup_engine_options_t* options, int val) {
options->rep.max_background_operations = val;
+52
View File
@@ -1018,6 +1018,12 @@ int main(int argc, char** argv) {
Free(&before_db_id);
Free(&after_db_id);
rocksdb_backup_engine_stop_backup(be);
rocksdb_backup_engine_create_new_backup(be, db, &err);
CheckCondition(err != NULL);
free(err);
err = NULL;
rocksdb_backup_engine_close(be);
}
@@ -3697,6 +3703,52 @@ int main(int argc, char** argv) {
CheckCondition(37 ==
rocksdb_backup_engine_options_get_restore_rate_limit(bdo));
{
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);
rocksdb_backup_engine_options_t* rate_beo =
rocksdb_backup_engine_options_create(dbbackupname);
rocksdb_ratelimiter_t* backup_limiter =
rocksdb_ratelimiter_create_with_mode(1024 * 1024, 100 * 1000, 10, 2,
0);
rocksdb_ratelimiter_t* restore_limiter =
rocksdb_ratelimiter_create_with_mode(1024 * 1024, 100 * 1000, 10, 2,
0);
rocksdb_backup_engine_options_set_backup_rate_limiter(rate_beo,
backup_limiter);
rocksdb_backup_engine_options_set_restore_rate_limiter(rate_beo,
restore_limiter);
rocksdb_ratelimiter_destroy(backup_limiter);
rocksdb_ratelimiter_destroy(restore_limiter);
rocksdb_env_t* rate_benv = rocksdb_create_default_env();
rocksdb_backup_engine_t* rate_be =
rocksdb_backup_engine_open_opts(rate_beo, rate_benv, &err);
rocksdb_backup_engine_options_destroy(rate_beo);
rocksdb_env_destroy(rate_benv);
CheckNoError(err);
rocksdb_backup_engine_create_new_backup(rate_be, db, &err);
CheckNoError(err);
{
char rate_restore_path[220];
snprintf(rate_restore_path, sizeof(rate_restore_path),
"%s.rate_restore", dbname);
rocksdb_restore_options_t* rate_restore_opts =
rocksdb_restore_options_create();
rocksdb_backup_engine_restore_db_from_latest_backup(
rate_be, rate_restore_path, rate_restore_path, rate_restore_opts,
&err);
CheckNoError(err);
rocksdb_restore_options_destroy(rate_restore_opts);
rocksdb_destroy_db(options, rate_restore_path, &err);
err = NULL;
}
rocksdb_backup_engine_close(rate_be);
}
rocksdb_backup_engine_options_set_max_background_operations(bdo, 20);
CheckCondition(
20 == rocksdb_backup_engine_options_get_max_background_operations(bdo));
+18
View File
@@ -273,6 +273,12 @@ extern ROCKSDB_LIBRARY_API uint32_t rocksdb_backup_engine_info_number_files(
extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_info_destroy(
const rocksdb_backup_engine_info_t* info);
/* Cancels any in-progress backup. This is a one-way operation: once called,
all future CreateNewBackup requests on this engine will fail with
Status::Incomplete. Open a new BackupEngine instance to resume backups. */
extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_stop_backup(
rocksdb_backup_engine_t* be);
extern ROCKSDB_LIBRARY_API void rocksdb_backup_engine_close(
rocksdb_backup_engine_t* be);
@@ -379,6 +385,18 @@ extern ROCKSDB_LIBRARY_API uint64_t
rocksdb_backup_engine_options_get_restore_rate_limit(
rocksdb_backup_engine_options_t* options);
/* Sets a RateLimiter for backup transfers. When non-null, overrides the
uint64_t backup_rate_limit value. */
extern ROCKSDB_LIBRARY_API void
rocksdb_backup_engine_options_set_backup_rate_limiter(
rocksdb_backup_engine_options_t* options, rocksdb_ratelimiter_t* limiter);
/* Sets a RateLimiter for restore transfers. When non-null, overrides the
uint64_t restore_rate_limit value. */
extern ROCKSDB_LIBRARY_API void
rocksdb_backup_engine_options_set_restore_rate_limiter(
rocksdb_backup_engine_options_t* options, rocksdb_ratelimiter_t* limiter);
extern ROCKSDB_LIBRARY_API void
rocksdb_backup_engine_options_set_max_background_operations(
rocksdb_backup_engine_options_t* options, int val);
+3
View File
@@ -1429,6 +1429,9 @@ IOStatus BackupEngineImpl::CreateNewBackupWithMetadata(
BackupID* new_backup_id_ptr) {
assert(initialized_);
assert(!read_only_);
if (ShouldStopBackup()) {
return status_to_io_status(Status::Incomplete("Backup stopped"));
}
if (app_metadata.size() > kMaxAppMetaSize) {
return IOStatus::InvalidArgument("App metadata too large");
}