2016-02-09 23:12:00 +00:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2017-07-15 23:03:42 +00:00
|
|
|
// 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).
|
2016-01-29 02:35:01 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2016-12-22 01:35:00 +00:00
|
|
|
#ifndef ROCKSDB_LITE
|
|
|
|
|
2016-01-29 02:35:01 +00:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "port/port.h"
|
|
|
|
|
2019-05-31 18:52:59 +00:00
|
|
|
#include "db/compaction/compaction.h"
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
#include "db/error_handler.h"
|
2019-05-30 03:44:08 +00:00
|
|
|
#include "file/delete_scheduler.h"
|
Introduce a new storage specific Env API (#5761)
Summary:
The current Env API encompasses both storage/file operations, as well as OS related operations. Most of the APIs return a Status, which does not have enough metadata about an error, such as whether its retry-able or not, scope (i.e fault domain) of the error etc., that may be required in order to properly handle a storage error. The file APIs also do not provide enough control over the IO SLA, such as timeout, prioritization, hinting about placement and redundancy etc.
This PR separates out the file/storage APIs from Env into a new FileSystem class. The APIs are updated to return an IOStatus with metadata about the error, as well as to take an IOOptions structure as input in order to allow more control over the IO.
The user can set both ```options.env``` and ```options.file_system``` to specify that RocksDB should use the former for OS related operations and the latter for storage operations. Internally, a ```CompositeEnvWrapper``` has been introduced that inherits from ```Env``` and redirects individual methods to either an ```Env``` implementation or the ```FileSystem``` as appropriate. When options are sanitized during ```DB::Open```, ```options.env``` is replaced with a newly allocated ```CompositeEnvWrapper``` instance if both env and file_system have been specified. This way, the rest of the RocksDB code can continue to function as before.
This PR also ports PosixEnv to the new API by splitting it into two - PosixEnv and PosixFileSystem. PosixEnv is defined as a sub-class of CompositeEnvWrapper, and threading/time functions are overridden with Posix specific implementations in order to avoid an extra level of indirection.
The ```CompositeEnvWrapper``` translates ```IOStatus``` return code to ```Status```, and sets the severity to ```kSoftError``` if the io_status is retryable. The error handling code in RocksDB can then recover the DB automatically.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5761
Differential Revision: D18868376
Pulled By: anand1976
fbshipit-source-id: 39efe18a162ea746fabac6360ff529baba48486f
2019-12-13 22:47:08 +00:00
|
|
|
#include "rocksdb/file_system.h"
|
2016-01-29 02:35:01 +00:00
|
|
|
#include "rocksdb/sst_file_manager.h"
|
|
|
|
|
2020-02-20 20:07:53 +00:00
|
|
|
namespace ROCKSDB_NAMESPACE {
|
2016-01-29 02:35:01 +00:00
|
|
|
|
|
|
|
class Env;
|
|
|
|
class Logger;
|
|
|
|
|
|
|
|
// SstFileManager is used to track SST files in the DB and control there
|
|
|
|
// deletion rate.
|
|
|
|
// All SstFileManager public functions are thread-safe.
|
|
|
|
class SstFileManagerImpl : public SstFileManager {
|
|
|
|
public:
|
Introduce a new storage specific Env API (#5761)
Summary:
The current Env API encompasses both storage/file operations, as well as OS related operations. Most of the APIs return a Status, which does not have enough metadata about an error, such as whether its retry-able or not, scope (i.e fault domain) of the error etc., that may be required in order to properly handle a storage error. The file APIs also do not provide enough control over the IO SLA, such as timeout, prioritization, hinting about placement and redundancy etc.
This PR separates out the file/storage APIs from Env into a new FileSystem class. The APIs are updated to return an IOStatus with metadata about the error, as well as to take an IOOptions structure as input in order to allow more control over the IO.
The user can set both ```options.env``` and ```options.file_system``` to specify that RocksDB should use the former for OS related operations and the latter for storage operations. Internally, a ```CompositeEnvWrapper``` has been introduced that inherits from ```Env``` and redirects individual methods to either an ```Env``` implementation or the ```FileSystem``` as appropriate. When options are sanitized during ```DB::Open```, ```options.env``` is replaced with a newly allocated ```CompositeEnvWrapper``` instance if both env and file_system have been specified. This way, the rest of the RocksDB code can continue to function as before.
This PR also ports PosixEnv to the new API by splitting it into two - PosixEnv and PosixFileSystem. PosixEnv is defined as a sub-class of CompositeEnvWrapper, and threading/time functions are overridden with Posix specific implementations in order to avoid an extra level of indirection.
The ```CompositeEnvWrapper``` translates ```IOStatus``` return code to ```Status```, and sets the severity to ```kSoftError``` if the io_status is retryable. The error handling code in RocksDB can then recover the DB automatically.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5761
Differential Revision: D18868376
Pulled By: anand1976
fbshipit-source-id: 39efe18a162ea746fabac6360ff529baba48486f
2019-12-13 22:47:08 +00:00
|
|
|
explicit SstFileManagerImpl(Env* env, std::shared_ptr<FileSystem> fs,
|
|
|
|
std::shared_ptr<Logger> logger,
|
2017-11-17 19:56:41 +00:00
|
|
|
int64_t rate_bytes_per_sec,
|
2018-03-22 22:42:44 +00:00
|
|
|
double max_trash_db_ratio,
|
|
|
|
uint64_t bytes_max_delete_chunk);
|
2016-01-29 02:35:01 +00:00
|
|
|
|
|
|
|
~SstFileManagerImpl();
|
|
|
|
|
|
|
|
// DB will call OnAddFile whenever a new sst file is added.
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
Status OnAddFile(const std::string& file_path, bool compaction = false);
|
2016-01-29 02:35:01 +00:00
|
|
|
|
2020-02-04 21:38:00 +00:00
|
|
|
// Overload where size of the file is provided by the caller rather than
|
|
|
|
// queried from the filesystem. This is an optimization.
|
|
|
|
Status OnAddFile(const std::string& file_path, uint64_t file_size,
|
|
|
|
bool compaction);
|
|
|
|
|
2016-01-29 02:35:01 +00:00
|
|
|
// DB will call OnDeleteFile whenever an sst file is deleted.
|
|
|
|
Status OnDeleteFile(const std::string& file_path);
|
|
|
|
|
|
|
|
// DB will call OnMoveFile whenever an sst file is move to a new path.
|
2017-06-12 23:51:37 +00:00
|
|
|
Status OnMoveFile(const std::string& old_path, const std::string& new_path,
|
|
|
|
uint64_t* file_size = nullptr);
|
2016-01-29 02:35:01 +00:00
|
|
|
|
2016-02-17 23:20:23 +00:00
|
|
|
// Update the maximum allowed space that should be used by RocksDB, if
|
|
|
|
// the total size of the SST files exceeds max_allowed_space, writes to
|
|
|
|
// RocksDB will fail.
|
|
|
|
//
|
|
|
|
// Setting max_allowed_space to 0 will disable this feature, maximum allowed
|
|
|
|
// space will be infinite (Default value).
|
|
|
|
//
|
|
|
|
// thread-safe.
|
|
|
|
void SetMaxAllowedSpaceUsage(uint64_t max_allowed_space) override;
|
|
|
|
|
2018-03-07 00:13:05 +00:00
|
|
|
void SetCompactionBufferSize(uint64_t compaction_buffer_size) override;
|
|
|
|
|
2016-02-17 23:20:23 +00:00
|
|
|
// Return true if the total size of SST files exceeded the maximum allowed
|
|
|
|
// space usage.
|
|
|
|
//
|
|
|
|
// thread-safe.
|
|
|
|
bool IsMaxAllowedSpaceReached() override;
|
|
|
|
|
2018-03-07 00:13:05 +00:00
|
|
|
bool IsMaxAllowedSpaceReachedIncludingCompactions() override;
|
|
|
|
|
|
|
|
// Returns true is there is enough (approximate) space for the specified
|
|
|
|
// compaction. Space is approximate because this function conservatively
|
|
|
|
// estimates how much space is currently being used by compactions (i.e.
|
|
|
|
// if a compaction has started, this function bumps the used space by
|
|
|
|
// the full compaction size).
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
bool EnoughRoomForCompaction(ColumnFamilyData* cfd,
|
|
|
|
const std::vector<CompactionInputFiles>& inputs,
|
|
|
|
Status bg_error);
|
2018-03-07 00:13:05 +00:00
|
|
|
|
|
|
|
// Bookkeeping so total_file_sizes_ goes back to normal after compaction
|
|
|
|
// finishes
|
|
|
|
void OnCompactionCompletion(Compaction* c);
|
|
|
|
|
|
|
|
uint64_t GetCompactionsReservedSize();
|
|
|
|
|
2016-01-29 02:35:01 +00:00
|
|
|
// Return the total size of all tracked files.
|
|
|
|
uint64_t GetTotalSize() override;
|
|
|
|
|
|
|
|
// Return a map containing all tracked files and there corresponding sizes.
|
|
|
|
std::unordered_map<std::string, uint64_t> GetTrackedFiles() override;
|
|
|
|
|
|
|
|
// Return delete rate limit in bytes per second.
|
|
|
|
virtual int64_t GetDeleteRateBytesPerSecond() override;
|
|
|
|
|
2017-03-16 19:06:04 +00:00
|
|
|
// Update the delete rate limit in bytes per second.
|
|
|
|
virtual void SetDeleteRateBytesPerSecond(int64_t delete_rate) override;
|
|
|
|
|
2017-11-17 19:56:41 +00:00
|
|
|
// Return trash/DB size ratio where new files will be deleted immediately
|
|
|
|
virtual double GetMaxTrashDBRatio() override;
|
|
|
|
|
|
|
|
// Update trash/DB size ratio where new files will be deleted immediately
|
|
|
|
virtual void SetMaxTrashDBRatio(double ratio) override;
|
|
|
|
|
2018-08-05 00:50:01 +00:00
|
|
|
// Return the total size of trash files
|
|
|
|
uint64_t GetTotalTrashSize() override;
|
|
|
|
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
// Called by each DB instance using this sst file manager to reserve
|
|
|
|
// disk buffer space for recovery from out of space errors
|
|
|
|
void ReserveDiskBuffer(uint64_t buffer, const std::string& path);
|
|
|
|
|
|
|
|
// Set a flag upon encountering disk full. May enqueue the ErrorHandler
|
|
|
|
// instance for background polling and recovery
|
|
|
|
void StartErrorRecovery(ErrorHandler* db, Status bg_error);
|
|
|
|
|
|
|
|
// Remove the given Errorhandler instance from the recovery queue. Its
|
|
|
|
// not guaranteed
|
|
|
|
bool CancelErrorRecovery(ErrorHandler* db);
|
|
|
|
|
2019-01-29 22:27:30 +00:00
|
|
|
// Mark file as trash and schedule it's deletion. If force_bg is set, it
|
|
|
|
// forces the file to be deleting in the background regardless of DB size,
|
|
|
|
// except when rate limited delete is disabled
|
2018-04-26 20:51:39 +00:00
|
|
|
virtual Status ScheduleFileDeletion(const std::string& file_path,
|
2019-01-29 22:27:30 +00:00
|
|
|
const std::string& dir_to_sync,
|
|
|
|
const bool force_bg = false);
|
2016-01-29 02:35:01 +00:00
|
|
|
|
|
|
|
// Wait for all files being deleteing in the background to finish or for
|
|
|
|
// destructor to be called.
|
|
|
|
virtual void WaitForEmptyTrash();
|
|
|
|
|
2017-06-12 23:51:37 +00:00
|
|
|
DeleteScheduler* delete_scheduler() { return &delete_scheduler_; }
|
|
|
|
|
2018-09-17 20:08:13 +00:00
|
|
|
// Stop the error recovery background thread. This should be called only
|
|
|
|
// once in the object's lifetime, and before the destructor
|
|
|
|
void Close();
|
|
|
|
|
2020-06-05 16:41:03 +00:00
|
|
|
void SetStatisticsPtr(const std::shared_ptr<Statistics>& stats) override {
|
|
|
|
stats_ = stats;
|
|
|
|
delete_scheduler_.SetStatisticsPtr(stats);
|
|
|
|
}
|
|
|
|
|
2016-01-29 02:35:01 +00:00
|
|
|
private:
|
|
|
|
// REQUIRES: mutex locked
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
void OnAddFileImpl(const std::string& file_path, uint64_t file_size,
|
|
|
|
bool compaction);
|
2016-01-29 02:35:01 +00:00
|
|
|
// REQUIRES: mutex locked
|
|
|
|
void OnDeleteFileImpl(const std::string& file_path);
|
|
|
|
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
void ClearError();
|
|
|
|
bool CheckFreeSpace() {
|
|
|
|
return bg_err_.severity() == Status::Severity::kSoftError;
|
|
|
|
}
|
|
|
|
|
2016-01-29 02:35:01 +00:00
|
|
|
Env* env_;
|
Introduce a new storage specific Env API (#5761)
Summary:
The current Env API encompasses both storage/file operations, as well as OS related operations. Most of the APIs return a Status, which does not have enough metadata about an error, such as whether its retry-able or not, scope (i.e fault domain) of the error etc., that may be required in order to properly handle a storage error. The file APIs also do not provide enough control over the IO SLA, such as timeout, prioritization, hinting about placement and redundancy etc.
This PR separates out the file/storage APIs from Env into a new FileSystem class. The APIs are updated to return an IOStatus with metadata about the error, as well as to take an IOOptions structure as input in order to allow more control over the IO.
The user can set both ```options.env``` and ```options.file_system``` to specify that RocksDB should use the former for OS related operations and the latter for storage operations. Internally, a ```CompositeEnvWrapper``` has been introduced that inherits from ```Env``` and redirects individual methods to either an ```Env``` implementation or the ```FileSystem``` as appropriate. When options are sanitized during ```DB::Open```, ```options.env``` is replaced with a newly allocated ```CompositeEnvWrapper``` instance if both env and file_system have been specified. This way, the rest of the RocksDB code can continue to function as before.
This PR also ports PosixEnv to the new API by splitting it into two - PosixEnv and PosixFileSystem. PosixEnv is defined as a sub-class of CompositeEnvWrapper, and threading/time functions are overridden with Posix specific implementations in order to avoid an extra level of indirection.
The ```CompositeEnvWrapper``` translates ```IOStatus``` return code to ```Status```, and sets the severity to ```kSoftError``` if the io_status is retryable. The error handling code in RocksDB can then recover the DB automatically.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5761
Differential Revision: D18868376
Pulled By: anand1976
fbshipit-source-id: 39efe18a162ea746fabac6360ff529baba48486f
2019-12-13 22:47:08 +00:00
|
|
|
std::shared_ptr<FileSystem> fs_;
|
2016-01-29 02:35:01 +00:00
|
|
|
std::shared_ptr<Logger> logger_;
|
|
|
|
// Mutex to protect tracked_files_, total_files_size_
|
|
|
|
port::Mutex mu_;
|
|
|
|
// The summation of the sizes of all files in tracked_files_ map
|
|
|
|
uint64_t total_files_size_;
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
// The summation of all output files of in-progress compactions
|
|
|
|
uint64_t in_progress_files_size_;
|
2018-03-07 00:13:05 +00:00
|
|
|
// Compactions should only execute if they can leave at least
|
|
|
|
// this amount of buffer space for logs and flushes
|
|
|
|
uint64_t compaction_buffer_size_;
|
|
|
|
// Estimated size of the current ongoing compactions
|
|
|
|
uint64_t cur_compactions_reserved_size_;
|
2016-01-29 02:35:01 +00:00
|
|
|
// A map containing all tracked files and there sizes
|
|
|
|
// file_path => file_size
|
|
|
|
std::unordered_map<std::string, uint64_t> tracked_files_;
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
// A set of files belonging to in-progress compactions
|
|
|
|
std::unordered_set<std::string> in_progress_files_;
|
2016-02-17 23:20:23 +00:00
|
|
|
// The maximum allowed space (in bytes) for sst files.
|
|
|
|
uint64_t max_allowed_space_;
|
2017-10-27 20:25:54 +00:00
|
|
|
// DeleteScheduler used to throttle file deletition.
|
2016-01-29 02:35:01 +00:00
|
|
|
DeleteScheduler delete_scheduler_;
|
Auto recovery from out of space errors (#4164)
Summary:
This commit implements automatic recovery from a Status::NoSpace() error
during background operations such as write callback, flush and
compaction. The broad design is as follows -
1. Compaction errors are treated as soft errors and don't put the
database in read-only mode. A compaction is delayed until enough free
disk space is available to accomodate the compaction outputs, which is
estimated based on the input size. This means that users can continue to
write, and we rely on the WriteController to delay or stop writes if the
compaction debt becomes too high due to persistent low disk space
condition
2. Errors during write callback and flush are treated as hard errors,
i.e the database is put in read-only mode and goes back to read-write
only fater certain recovery actions are taken.
3. Both types of recovery rely on the SstFileManagerImpl to poll for
sufficient disk space. We assume that there is a 1-1 mapping between an
SFM and the underlying OS storage container. For cases where multiple
DBs are hosted on a single storage container, the user is expected to
allocate a single SFM instance and use the same one for all the DBs. If
no SFM is specified by the user, DBImpl::Open() will allocate one, but
this will be one per DB and each DB will recover independently. The
recovery implemented by SFM is as follows -
a) On the first occurance of an out of space error during compaction,
subsequent
compactions will be delayed until the disk free space check indicates
enough available space. The required space is computed as the sum of
input sizes.
b) The free space check requirement will be removed once the amount of
free space is greater than the size reserved by in progress
compactions when the first error occured
c) If the out of space error is a hard error, a background thread in
SFM will poll for sufficient headroom before triggering the recovery
of the database and putting it in write-only mode. The headroom is
calculated as the sum of the write_buffer_size of all the DB instances
associated with the SFM
4. EventListener callbacks will be called at the start and completion of
automatic recovery. Users can disable the auto recov ery in the start
callback, and later initiate it manually by calling DB::Resume()
Todo:
1. More extensive testing
2. Add disk full condition to db_stress (follow-on PR)
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4164
Differential Revision: D9846378
Pulled By: anand1976
fbshipit-source-id: 80ea875dbd7f00205e19c82215ff6e37da10da4a
2018-09-15 20:36:19 +00:00
|
|
|
port::CondVar cv_;
|
|
|
|
// Flag to force error recovery thread to exit
|
|
|
|
bool closing_;
|
|
|
|
// Background error recovery thread
|
|
|
|
std::unique_ptr<port::Thread> bg_thread_;
|
|
|
|
// A path in the filesystem corresponding to this SFM. This is used for
|
|
|
|
// calling Env::GetFreeSpace. Posix requires a path in the filesystem
|
|
|
|
std::string path_;
|
|
|
|
// Save the current background error
|
|
|
|
Status bg_err_;
|
|
|
|
// Amount of free disk headroom before allowing recovery from hard errors
|
|
|
|
uint64_t reserved_disk_buffer_;
|
|
|
|
// For soft errors, amount of free disk space before we can allow
|
|
|
|
// compactions to run full throttle. If disk space is below this trigger,
|
|
|
|
// compactions will be gated by free disk space > input size
|
|
|
|
uint64_t free_space_trigger_;
|
|
|
|
// List of database error handler instances tracked by this sst file manager
|
|
|
|
std::list<ErrorHandler*> error_handler_list_;
|
|
|
|
// Pointer to ErrorHandler instance that is currently processing recovery
|
|
|
|
ErrorHandler* cur_instance_;
|
2020-06-05 16:41:03 +00:00
|
|
|
std::shared_ptr<Statistics> stats_;
|
2016-01-29 02:35:01 +00:00
|
|
|
};
|
|
|
|
|
2020-02-20 20:07:53 +00:00
|
|
|
} // namespace ROCKSDB_NAMESPACE
|
2016-12-22 01:35:00 +00:00
|
|
|
|
|
|
|
#endif // ROCKSDB_LITE
|