// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). // // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. #pragma once #ifndef ROCKSDB_LITE #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include #include #include #include #include #include "rocksdb/utilities/stackable_db.h" #include "rocksdb/env.h" #include "rocksdb/status.h" namespace rocksdb { struct BackupableDBOptions { // Where to keep the backup files. Has to be different than dbname_ // Best to set this to dbname_ + "/backups" // Required std::string backup_dir; // Backup Env object. It will be used for backup file I/O. If it's // nullptr, backups will be written out using DBs Env. If it's // non-nullptr, backup's I/O will be performed using this object. // If you want to have backups on HDFS, use HDFS Env here! // Default: nullptr Env* backup_env; // If share_table_files == true, backup will assume that table files with // same name have the same contents. This enables incremental backups and // avoids unnecessary data copies. // If share_table_files == false, each backup will be on its own and will // not share any data with other backups. // default: true bool share_table_files; // Backup info and error messages will be written to info_log // if non-nullptr. // Default: nullptr Logger* info_log; // If sync == true, we can guarantee you'll get consistent backup even // on a machine crash/reboot. Backup process is slower with sync enabled. // If sync == false, we don't guarantee anything on machine reboot. However, // chances are some of the backups are consistent. // Default: true bool sync; // If true, it will delete whatever backups there are already // Default: false bool destroy_old_data; // If false, we won't backup log files. This option can be useful for backing // up in-memory databases where log file are persisted, but table files are in // memory. // Default: true bool backup_log_files; // Max bytes that can be transferred in a second during backup. // If 0, go as fast as you can // Default: 0 uint64_t backup_rate_limit; // Backup rate limiter. Used to control transfer speed for backup. If this is // not null, backup_rate_limit is ignored. // Default: nullptr std::shared_ptr backup_rate_limiter{nullptr}; // Max bytes that can be transferred in a second during restore. // If 0, go as fast as you can // Default: 0 uint64_t restore_rate_limit; // Restore rate limiter. Used to control transfer speed during restore. If // this is not null, restore_rate_limit is ignored. // Default: nullptr std::shared_ptr restore_rate_limiter{nullptr}; // Only used if share_table_files is set to true. If true, will consider that // backups can come from different databases, hence a sst is not uniquely // identifed by its name, but by the triple (file name, crc32, file length) // Default: false // Note: this is an experimental option, and you'll need to set it manually // *turn it on only if you know what you're doing* bool share_files_with_checksum; // Up to this many background threads will copy files for CreateNewBackup() // and RestoreDBFromBackup() // Default: 1 int max_background_operations; // During backup user can get callback every time next // callback_trigger_interval_size bytes being copied. // Default: 4194304 uint64_t callback_trigger_interval_size; // When Open() is called, it will open at most this many of the latest // non-corrupted backups. If 0, it will open all available backups. // Default: 0 int max_valid_backups_to_open; void Dump(Logger* logger) const; explicit BackupableDBOptions( const std::string& _backup_dir, Env* _backup_env = nullptr, bool _share_table_files = true, Logger* _info_log = nullptr, bool _sync = true, bool _destroy_old_data = false, bool _backup_log_files = true, uint64_t _backup_rate_limit = 0, uint64_t _restore_rate_limit = 0, int _max_background_operations = 1, uint64_t _callback_trigger_interval_size = 4 * 1024 * 1024, int _max_valid_backups_to_open = 0) : backup_dir(_backup_dir), backup_env(_backup_env), share_table_files(_share_table_files), info_log(_info_log), sync(_sync), destroy_old_data(_destroy_old_data), backup_log_files(_backup_log_files), backup_rate_limit(_backup_rate_limit), restore_rate_limit(_restore_rate_limit), share_files_with_checksum(false), max_background_operations(_max_background_operations), callback_trigger_interval_size(_callback_trigger_interval_size), max_valid_backups_to_open(_max_valid_backups_to_open) { assert(share_table_files || !share_files_with_checksum); } }; struct RestoreOptions { // If true, restore won't overwrite the existing log files in wal_dir. It will // also move all log files from archive directory to wal_dir. Use this option // in combination with BackupableDBOptions::backup_log_files = false for // persisting in-memory databases. // Default: false bool keep_log_files; explicit RestoreOptions(bool _keep_log_files = false) : keep_log_files(_keep_log_files) {} }; typedef uint32_t BackupID; struct BackupInfo { BackupID backup_id; int64_t timestamp; uint64_t size; uint32_t number_files; std::string app_metadata; BackupInfo() {} BackupInfo(BackupID _backup_id, int64_t _timestamp, uint64_t _size, uint32_t _number_files, const std::string& _app_metadata) : backup_id(_backup_id), timestamp(_timestamp), size(_size), number_files(_number_files), app_metadata(_app_metadata) {} }; class BackupStatistics { public: BackupStatistics() { number_success_backup = 0; number_fail_backup = 0; } BackupStatistics(uint32_t _number_success_backup, uint32_t _number_fail_backup) : number_success_backup(_number_success_backup), number_fail_backup(_number_fail_backup) {} ~BackupStatistics() {} void IncrementNumberSuccessBackup(); void IncrementNumberFailBackup(); uint32_t GetNumberSuccessBackup() const; uint32_t GetNumberFailBackup() const; std::string ToString() const; private: uint32_t number_success_backup; uint32_t number_fail_backup; }; // A backup engine for accessing information about backups and restoring from // them. class BackupEngineReadOnly { public: virtual ~BackupEngineReadOnly() {} static Status Open(Env* db_env, const BackupableDBOptions& options, BackupEngineReadOnly** backup_engine_ptr); // Returns info about backups in backup_info // You can GetBackupInfo safely, even with other BackupEngine performing // backups on the same directory virtual void GetBackupInfo(std::vector* backup_info) = 0; // Returns info about corrupt backups in corrupt_backups virtual void GetCorruptedBackups( std::vector* corrupt_backup_ids) = 0; // Restoring DB from backup is NOT safe when there is another BackupEngine // running that might call DeleteBackup() or PurgeOldBackups(). It is caller's // responsibility to synchronize the operation, i.e. don't delete the backup // when you're restoring from it // See also the corresponding doc in BackupEngine virtual Status RestoreDBFromBackup( BackupID backup_id, const std::string& db_dir, const std::string& wal_dir, const RestoreOptions& restore_options = RestoreOptions()) = 0; // See the corresponding doc in BackupEngine virtual Status RestoreDBFromLatestBackup( const std::string& db_dir, const std::string& wal_dir, const RestoreOptions& restore_options = RestoreOptions()) = 0; // checks that each file exists and that the size of the file matches our // expectations. it does not check file checksum. // // If this BackupEngine created the backup, it compares the files' current // sizes against the number of bytes written to them during creation. // Otherwise, it compares the files' current sizes against their sizes when // the BackupEngine was opened. // // Returns Status::OK() if all checks are good virtual Status VerifyBackup(BackupID backup_id) = 0; }; // A backup engine for creating new backups. class BackupEngine { public: virtual ~BackupEngine() {} // BackupableDBOptions have to be the same as the ones used in previous // BackupEngines for the same backup directory. static Status Open(Env* db_env, const BackupableDBOptions& options, BackupEngine** backup_engine_ptr); // same as CreateNewBackup, but stores extra application metadata // Flush will always trigger if 2PC is enabled. virtual Status CreateNewBackupWithMetadata( DB* db, const std::string& app_metadata, bool flush_before_backup = false, std::function progress_callback = []() {}) = 0; // Captures the state of the database in the latest backup // NOT a thread safe call // Flush will always trigger if 2PC is enabled. virtual Status CreateNewBackup(DB* db, bool flush_before_backup = false, std::function progress_callback = []() {}) { return CreateNewBackupWithMetadata(db, "", flush_before_backup, progress_callback); } // deletes old backups, keeping latest num_backups_to_keep alive virtual Status PurgeOldBackups(uint32_t num_backups_to_keep) = 0; // deletes a specific backup virtual Status DeleteBackup(BackupID backup_id) = 0; // Call this from another thread if you want to stop the backup // that is currently happening. It will return immediatelly, will // not wait for the backup to stop. // The backup will stop ASAP and the call to CreateNewBackup will // return Status::Incomplete(). It will not clean up after itself, but // the state will remain consistent. The state will be cleaned up // next time you create BackupableDB or RestoreBackupableDB. virtual void StopBackup() = 0; // Returns info about backups in backup_info virtual void GetBackupInfo(std::vector* backup_info) = 0; // Returns info about corrupt backups in corrupt_backups virtual void GetCorruptedBackups( std::vector* corrupt_backup_ids) = 0; // restore from backup with backup_id // IMPORTANT -- if options_.share_table_files == true, // options_.share_files_with_checksum == false, you restore DB from some // backup that is not the latest, and you start creating new backups from the // new DB, they will probably fail. // // Example: Let's say you have backups 1, 2, 3, 4, 5 and you restore 3. // If you add new data to the DB and try creating a new backup now, the // database will diverge from backups 4 and 5 and the new backup will fail. // If you want to create new backup, you will first have to delete backups 4 // and 5. virtual Status RestoreDBFromBackup( BackupID backup_id, const std::string& db_dir, const std::string& wal_dir, const RestoreOptions& restore_options = RestoreOptions()) = 0; // restore from the latest backup virtual Status RestoreDBFromLatestBackup( const std::string& db_dir, const std::string& wal_dir, const RestoreOptions& restore_options = RestoreOptions()) = 0; // checks that each file exists and that the size of the file matches our // expectations. it does not check file checksum. // Returns Status::OK() if all checks are good virtual Status VerifyBackup(BackupID backup_id) = 0; // Will delete all the files we don't need anymore // It will do the full scan of the files/ directory and delete all the // files that are not referenced. virtual Status GarbageCollect() = 0; }; } // namespace rocksdb #endif // ROCKSDB_LITE