2018-01-24 00:39:44 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2018-05-29 10:42:48 +02:00
|
|
|
/// Uncomment or -D this #define to enable extensive log messages covering the
|
|
|
|
/// entire RocksDB callback surface. This is only useful for developers
|
|
|
|
/// specifically working on the backend of the DB and no real use for
|
|
|
|
/// developers making frontend queries to it. Massively verbose.
|
|
|
|
///
|
|
|
|
//#define RB_DEBUG_DB_ENV
|
|
|
|
|
|
|
|
/// This #define is more useful to developers making queries to the database.
|
|
|
|
/// It is still so verbose that it goes beyond what is tolerable and generally
|
|
|
|
/// useful even in debug-mode builds, thus the manual #define being required.
|
|
|
|
///
|
|
|
|
//#define RB_DEBUG_DB_SEEK
|
|
|
|
|
2018-08-16 13:48:21 +02:00
|
|
|
/// Uncomment or -D this #define to enable extensive log messages for the
|
|
|
|
/// experimental db environment-port implementation. This is only useful
|
|
|
|
/// for developers working on the port impl and want to debug all locking
|
|
|
|
/// and unlocking etc.
|
|
|
|
///
|
|
|
|
//#define RB_DEBUG_DB_PORT
|
|
|
|
|
2019-01-23 22:51:17 +01:00
|
|
|
#include <rocksdb/version.h>
|
|
|
|
#include <rocksdb/status.h>
|
|
|
|
#include <rocksdb/db.h>
|
|
|
|
#include <rocksdb/cache.h>
|
|
|
|
#include <rocksdb/comparator.h>
|
|
|
|
#include <rocksdb/merge_operator.h>
|
|
|
|
#include <rocksdb/perf_level.h>
|
|
|
|
#include <rocksdb/perf_context.h>
|
|
|
|
#include <rocksdb/iostats_context.h>
|
|
|
|
#include <rocksdb/listener.h>
|
|
|
|
#include <rocksdb/statistics.h>
|
|
|
|
#include <rocksdb/convenience.h>
|
|
|
|
#include <rocksdb/env.h>
|
|
|
|
#include <rocksdb/slice_transform.h>
|
|
|
|
#include <rocksdb/utilities/checkpoint.h>
|
|
|
|
#include <rocksdb/filter_policy.h>
|
|
|
|
#include <rocksdb/table.h>
|
|
|
|
#include <rocksdb/sst_file_manager.h>
|
|
|
|
#include <rocksdb/sst_dump_tool.h>
|
|
|
|
#include <rocksdb/compaction_filter.h>
|
2019-04-20 23:22:08 +02:00
|
|
|
#include <rocksdb/wal_filter.h>
|
2019-01-23 22:51:17 +01:00
|
|
|
|
2018-01-24 00:39:44 +01:00
|
|
|
namespace ircd::db
|
|
|
|
{
|
|
|
|
struct throw_on_error;
|
2018-08-23 13:19:32 +02:00
|
|
|
struct error_to_status;
|
2019-08-25 02:40:31 +02:00
|
|
|
struct prefetcher;
|
2018-01-24 00:39:44 +01:00
|
|
|
|
2018-12-28 19:55:57 +01:00
|
|
|
constexpr const auto BLOCKING { rocksdb::ReadTier::kReadAllTier };
|
|
|
|
constexpr const auto NON_BLOCKING { rocksdb::ReadTier::kBlockCacheTier };
|
2018-01-24 00:39:44 +01:00
|
|
|
|
2018-08-23 13:02:12 +02:00
|
|
|
// state
|
2018-01-30 18:58:36 +01:00
|
|
|
extern log::log rog;
|
2018-08-22 23:08:27 +02:00
|
|
|
extern conf::item<size_t> request_pool_size;
|
|
|
|
extern conf::item<size_t> request_pool_stack_size;
|
2018-12-28 21:57:32 +01:00
|
|
|
extern ctx::pool::opts request_pool_opts;
|
2018-08-19 04:30:25 +02:00
|
|
|
extern ctx::pool request;
|
2018-08-27 05:24:38 +02:00
|
|
|
extern ctx::mutex write_mutex;
|
2019-08-25 02:40:31 +02:00
|
|
|
extern db::prefetcher *prefetcher;
|
2018-01-24 00:39:44 +01:00
|
|
|
|
2018-08-23 13:02:12 +02:00
|
|
|
// reflections
|
2018-10-31 22:48:14 +01:00
|
|
|
string_view reflect(const rocksdb::Status::Severity &);
|
2018-01-24 00:39:44 +01:00
|
|
|
string_view reflect(const rocksdb::Env::Priority &p);
|
|
|
|
string_view reflect(const rocksdb::Env::IOPriority &p);
|
2018-11-02 09:07:09 +01:00
|
|
|
string_view reflect(const rocksdb::Env::WriteLifeTimeHint &);
|
2018-10-31 22:40:00 +01:00
|
|
|
string_view reflect(const rocksdb::WriteStallCondition &);
|
|
|
|
string_view reflect(const rocksdb::BackgroundErrorReason &);
|
2018-12-19 22:39:06 +01:00
|
|
|
string_view reflect(const rocksdb::CompactionReason &);
|
|
|
|
string_view reflect(const rocksdb::FlushReason &);
|
2018-01-24 00:39:44 +01:00
|
|
|
string_view reflect(const rocksdb::RandomAccessFile::AccessPattern &p);
|
|
|
|
const std::string &reflect(const rocksdb::Tickers &);
|
|
|
|
const std::string &reflect(const rocksdb::Histograms &);
|
2018-08-23 13:02:12 +02:00
|
|
|
|
|
|
|
// string_view <-> slice
|
2018-01-24 00:39:44 +01:00
|
|
|
rocksdb::Slice slice(const string_view &);
|
|
|
|
string_view slice(const rocksdb::Slice &);
|
|
|
|
|
|
|
|
// Frequently used get options and set options are separate from the string/map system
|
|
|
|
rocksdb::WriteOptions &operator+=(rocksdb::WriteOptions &, const sopts &);
|
|
|
|
rocksdb::ReadOptions &operator+=(rocksdb::ReadOptions &, const gopts &);
|
|
|
|
rocksdb::WriteOptions make_opts(const sopts &);
|
|
|
|
rocksdb::ReadOptions make_opts(const gopts &);
|
|
|
|
|
|
|
|
// Database options creator
|
|
|
|
bool optstr_find_and_remove(std::string &optstr, const std::string &what);
|
2018-04-09 20:51:36 +02:00
|
|
|
rocksdb::DBOptions make_dbopts(std::string optstr, std::string *const &out = nullptr, bool *read_only = nullptr, bool *fsck = nullptr);
|
2018-11-03 02:08:40 +01:00
|
|
|
rocksdb::CompressionType find_supported_compression(const std::string &);
|
2018-01-24 00:39:44 +01:00
|
|
|
|
2019-01-29 20:13:58 +01:00
|
|
|
// Read column names from filesystem
|
|
|
|
std::vector<std::string> column_names(const std::string &path, const rocksdb::DBOptions &);
|
|
|
|
std::vector<std::string> column_names(const std::string &path, const std::string &options);
|
|
|
|
|
2018-01-24 00:39:44 +01:00
|
|
|
// Validation functors
|
|
|
|
bool valid(const rocksdb::Iterator &);
|
|
|
|
bool operator!(const rocksdb::Iterator &);
|
|
|
|
using valid_proffer = std::function<bool (const rocksdb::Iterator &)>;
|
|
|
|
bool valid(const rocksdb::Iterator &, const valid_proffer &);
|
|
|
|
bool valid_eq(const rocksdb::Iterator &, const string_view &);
|
|
|
|
bool valid_lte(const rocksdb::Iterator &, const string_view &);
|
|
|
|
bool valid_gt(const rocksdb::Iterator &, const string_view &);
|
|
|
|
void valid_or_throw(const rocksdb::Iterator &);
|
|
|
|
void valid_eq_or_throw(const rocksdb::Iterator &, const string_view &);
|
|
|
|
|
|
|
|
// [GET] seek suite
|
|
|
|
template<class pos> bool seek(database::column &, const pos &, const rocksdb::ReadOptions &, std::unique_ptr<rocksdb::Iterator> &it);
|
|
|
|
template<class pos> bool seek(database::column &, const pos &, const gopts &, std::unique_ptr<rocksdb::Iterator> &it);
|
|
|
|
std::unique_ptr<rocksdb::Iterator> seek(column &, const gopts &);
|
|
|
|
std::unique_ptr<rocksdb::Iterator> seek(column &, const string_view &key, const gopts &);
|
|
|
|
std::vector<row::value_type> seek(database &, const gopts &);
|
|
|
|
std::pair<string_view, string_view> operator*(const rocksdb::Iterator &);
|
|
|
|
|
|
|
|
// [SET] writebatch suite
|
|
|
|
std::string debug(const rocksdb::WriteBatch &);
|
|
|
|
bool has(const rocksdb::WriteBatch &, const op &);
|
|
|
|
void commit(database &, rocksdb::WriteBatch &, const rocksdb::WriteOptions &);
|
|
|
|
void commit(database &, rocksdb::WriteBatch &, const sopts &);
|
|
|
|
void append(rocksdb::WriteBatch &, column &, const column::delta &delta);
|
|
|
|
void append(rocksdb::WriteBatch &, const cell::delta &delta);
|
|
|
|
}
|
|
|
|
|
2019-07-21 00:29:33 +02:00
|
|
|
#include "db_port.h"
|
|
|
|
#include "db_env.h"
|
|
|
|
#include "db_env_state.h"
|
|
|
|
#include "db_database.h"
|
|
|
|
|
2019-08-25 02:40:31 +02:00
|
|
|
//
|
|
|
|
// util
|
|
|
|
//
|
|
|
|
|
2018-01-24 00:39:44 +01:00
|
|
|
struct ircd::db::throw_on_error
|
|
|
|
{
|
|
|
|
throw_on_error(const rocksdb::Status & = rocksdb::Status::OK());
|
|
|
|
};
|
2018-08-23 13:19:32 +02:00
|
|
|
|
|
|
|
struct ircd::db::error_to_status
|
|
|
|
:rocksdb::Status
|
|
|
|
{
|
|
|
|
error_to_status(const std::error_code &);
|
2018-12-13 02:21:11 +01:00
|
|
|
error_to_status(const std::system_error &);
|
2018-08-23 13:19:32 +02:00
|
|
|
error_to_status(const std::exception &);
|
|
|
|
};
|
2019-07-21 00:29:33 +02:00
|
|
|
|
2019-08-25 02:40:31 +02:00
|
|
|
//
|
|
|
|
// txn
|
|
|
|
//
|
|
|
|
|
2019-07-21 00:29:33 +02:00
|
|
|
struct ircd::db::txn::handler
|
|
|
|
:rocksdb::WriteBatch::Handler
|
|
|
|
{
|
|
|
|
using Status = rocksdb::Status;
|
|
|
|
using Slice = rocksdb::Slice;
|
|
|
|
|
|
|
|
const database &d;
|
|
|
|
const std::function<bool (const delta &)> &cb;
|
|
|
|
bool _continue {true};
|
|
|
|
|
|
|
|
Status callback(const delta &) noexcept;
|
|
|
|
Status callback(const uint32_t &, const op &, const Slice &a, const Slice &b) noexcept;
|
|
|
|
|
|
|
|
bool Continue() noexcept override;
|
|
|
|
Status MarkRollback(const Slice &xid) noexcept override;
|
|
|
|
Status MarkCommit(const Slice &xid) noexcept override;
|
|
|
|
Status MarkEndPrepare(const Slice &xid) noexcept override;
|
|
|
|
Status MarkBeginPrepare(bool = false) noexcept override;
|
|
|
|
|
|
|
|
Status MergeCF(const uint32_t cfid, const Slice &, const Slice &) noexcept override;
|
|
|
|
Status SingleDeleteCF(const uint32_t cfid, const Slice &) noexcept override;
|
|
|
|
Status DeleteRangeCF(const uint32_t cfid, const Slice &, const Slice &) noexcept override;
|
|
|
|
Status DeleteCF(const uint32_t cfid, const Slice &) noexcept override;
|
|
|
|
Status PutCF(const uint32_t cfid, const Slice &, const Slice &) noexcept override;
|
|
|
|
|
|
|
|
handler(const database &d,
|
|
|
|
const std::function<bool (const delta &)> &cb)
|
|
|
|
:d{d}
|
|
|
|
,cb{cb}
|
|
|
|
{}
|
|
|
|
};
|
2019-08-25 02:40:31 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// prefetcher
|
|
|
|
//
|
|
|
|
|
|
|
|
struct ircd::db::prefetcher
|
|
|
|
{
|
|
|
|
struct request;
|
2019-09-08 22:31:41 +02:00
|
|
|
using closure = std::function<bool (request &)>;
|
2019-08-25 02:40:31 +02:00
|
|
|
|
|
|
|
ctx::dock dock;
|
|
|
|
std::deque<request> queue;
|
|
|
|
ctx::context context;
|
2019-09-08 22:31:41 +02:00
|
|
|
size_t handles {0};
|
2019-08-25 02:40:31 +02:00
|
|
|
size_t request_workers {0};
|
|
|
|
size_t request_counter {0};
|
|
|
|
size_t handles_counter {0};
|
2019-09-08 22:31:41 +02:00
|
|
|
size_t fetched_counter {0};
|
|
|
|
size_t cancels_counter {0};
|
2019-08-25 02:40:31 +02:00
|
|
|
|
2019-09-08 22:31:41 +02:00
|
|
|
size_t wait_pending();
|
2019-08-25 02:40:31 +02:00
|
|
|
void request_handle(request &);
|
|
|
|
void request_worker();
|
|
|
|
void handle();
|
|
|
|
void worker();
|
|
|
|
|
2019-09-08 22:31:41 +02:00
|
|
|
public:
|
|
|
|
size_t cancel(const closure &);
|
|
|
|
size_t cancel(database &); // Cancel all for db
|
|
|
|
size_t cancel(column &); // Cancel all for column
|
|
|
|
|
2019-08-25 02:40:31 +02:00
|
|
|
bool operator()(column &, const string_view &key, const gopts &);
|
|
|
|
|
|
|
|
prefetcher();
|
|
|
|
~prefetcher() noexcept;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ircd::db::prefetcher::request
|
|
|
|
{
|
|
|
|
std::string key;
|
|
|
|
database *d {nullptr};
|
|
|
|
steady_point start;
|
|
|
|
uint32_t cid {0};
|
|
|
|
};
|