2017-02-04 16:01:15 +08:00
|
|
|
#pragma once
|
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
#include <atomic>
|
2017-12-19 19:40:30 +08:00
|
|
|
#include <memory>
|
|
|
|
|
2018-01-10 19:18:03 +08:00
|
|
|
#include "database/counters.hpp"
|
2018-01-12 22:17:04 +08:00
|
|
|
#include "database/storage.hpp"
|
|
|
|
#include "database/storage_gc.hpp"
|
2018-01-26 00:19:33 +08:00
|
|
|
#include "distributed/rpc_worker_clients.hpp"
|
2017-11-13 16:50:49 +08:00
|
|
|
#include "durability/wal.hpp"
|
2018-01-15 21:03:07 +08:00
|
|
|
#include "io/network/endpoint.hpp"
|
2017-11-23 23:36:54 +08:00
|
|
|
#include "storage/concurrent_id_mapper.hpp"
|
2018-01-16 17:09:15 +08:00
|
|
|
#include "storage/types.hpp"
|
2017-02-18 18:54:37 +08:00
|
|
|
#include "transactions/engine.hpp"
|
2017-04-10 21:44:36 +08:00
|
|
|
#include "utils/scheduler.hpp"
|
2017-02-04 16:01:15 +08:00
|
|
|
|
2018-01-22 19:36:14 +08:00
|
|
|
namespace distributed {
|
2018-01-23 18:00:50 +08:00
|
|
|
class RemoteDataRpcServer;
|
|
|
|
class RemoteDataRpcClients;
|
|
|
|
class PlanDispatcher;
|
|
|
|
class PlanConsumer;
|
2018-01-25 17:09:54 +08:00
|
|
|
class RemotePullRpcClients;
|
|
|
|
class RemoteProduceRpcServer;
|
2018-01-22 19:36:14 +08:00
|
|
|
}
|
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
namespace database {
|
|
|
|
|
|
|
|
/// Database configuration. Initialized from flags, but modifiable.
|
|
|
|
struct Config {
|
|
|
|
Config();
|
|
|
|
// Durability flags.
|
|
|
|
bool durability_enabled;
|
|
|
|
std::string durability_directory;
|
|
|
|
bool db_recover_on_startup;
|
|
|
|
int snapshot_cycle_sec;
|
|
|
|
int snapshot_max_retained;
|
|
|
|
int snapshot_on_exit;
|
|
|
|
|
|
|
|
// Misc flags.
|
|
|
|
int gc_cycle_sec;
|
|
|
|
int query_execution_time_sec;
|
|
|
|
|
|
|
|
// Distributed master/worker flags.
|
|
|
|
int worker_id;
|
2018-01-15 21:03:07 +08:00
|
|
|
io::network::Endpoint master_endpoint;
|
|
|
|
io::network::Endpoint worker_endpoint;
|
2018-01-12 22:17:04 +08:00
|
|
|
};
|
|
|
|
|
2017-02-04 16:01:15 +08:00
|
|
|
/**
|
2018-01-12 22:17:04 +08:00
|
|
|
* An abstract base class for a SingleNode/Master/Worker graph db.
|
2017-10-30 17:43:25 +08:00
|
|
|
*
|
|
|
|
* Always be sure that GraphDb object is destructed before main exits, i. e.
|
|
|
|
* GraphDb object shouldn't be part of global/static variable, except if its
|
|
|
|
* destructor is explicitly called before main exits. Consider code:
|
|
|
|
*
|
2018-01-12 22:17:04 +08:00
|
|
|
* GraphDb db; // KeyIndex is created as a part of database::Storage
|
2017-10-30 17:43:25 +08:00
|
|
|
* int main() {
|
|
|
|
* GraphDbAccessor dba(db);
|
|
|
|
* auto v = dba.InsertVertex();
|
|
|
|
* v.add_label(dba.Label(
|
|
|
|
* "Start")); // New SkipList is created in KeyIndex for LabelIndex.
|
|
|
|
* // That SkipList creates SkipListGc which
|
|
|
|
* // initialises static Executor object.
|
|
|
|
* return 0;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* After main exits: 1. Executor is destructed, 2. KeyIndex is destructed.
|
|
|
|
* Destructor of KeyIndex calls delete on created SkipLists which destroy
|
|
|
|
* SkipListGc that tries to use Excutioner object that doesn't exist anymore.
|
|
|
|
* -> CRASH
|
2017-02-04 16:01:15 +08:00
|
|
|
*/
|
2017-06-21 17:29:13 +08:00
|
|
|
class GraphDb {
|
2017-02-18 18:54:37 +08:00
|
|
|
public:
|
2018-01-23 18:00:50 +08:00
|
|
|
enum class Type { SINGLE_NODE, DISTRIBUTED_MASTER, DISTRIBUTED_WORKER };
|
2018-01-22 19:36:14 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
GraphDb() {}
|
|
|
|
virtual ~GraphDb() {}
|
|
|
|
|
2018-01-22 19:36:14 +08:00
|
|
|
virtual Type type() const = 0;
|
2018-01-19 21:49:58 +08:00
|
|
|
virtual Storage &storage() = 0;
|
|
|
|
virtual durability::WriteAheadLog &wal() = 0;
|
|
|
|
virtual tx::Engine &tx_engine() = 0;
|
|
|
|
virtual storage::ConcurrentIdMapper<storage::Label> &label_mapper() = 0;
|
|
|
|
virtual storage::ConcurrentIdMapper<storage::EdgeType>
|
|
|
|
&edge_type_mapper() = 0;
|
|
|
|
virtual storage::ConcurrentIdMapper<storage::Property> &property_mapper() = 0;
|
|
|
|
virtual database::Counters &counters() = 0;
|
|
|
|
virtual void CollectGarbage() = 0;
|
|
|
|
virtual int WorkerId() const = 0;
|
|
|
|
|
2018-01-22 19:36:14 +08:00
|
|
|
// Supported only in distributed master and worker, not in single-node.
|
|
|
|
virtual distributed::RemoteDataRpcServer &remote_data_server() = 0;
|
|
|
|
virtual distributed::RemoteDataRpcClients &remote_data_clients() = 0;
|
2018-01-25 17:09:54 +08:00
|
|
|
|
|
|
|
// Supported only in distributed master.
|
|
|
|
virtual distributed::RemotePullRpcClients &remote_pull_clients() = 0;
|
2018-01-23 18:00:50 +08:00
|
|
|
virtual distributed::PlanDispatcher &plan_dispatcher() = 0;
|
2018-01-31 23:07:23 +08:00
|
|
|
virtual distributed::RpcWorkerClients &index_rpc_clients() = 0;
|
2018-01-25 17:09:54 +08:00
|
|
|
|
|
|
|
// Supported only in distributed worker.
|
|
|
|
// TODO remove once end2end testing is possible.
|
|
|
|
virtual distributed::RemoteProduceRpcServer &remote_produce_server() = 0;
|
2018-01-23 18:00:50 +08:00
|
|
|
virtual distributed::PlanConsumer &plan_consumer() = 0;
|
2018-01-22 19:36:14 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
GraphDb(const GraphDb &) = delete;
|
|
|
|
GraphDb(GraphDb &&) = delete;
|
|
|
|
GraphDb &operator=(const GraphDb &) = delete;
|
|
|
|
GraphDb &operator=(GraphDb &&) = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace impl {
|
|
|
|
// Private GraphDb implementations all inherit `PrivateBase`.
|
|
|
|
// Public GraphDb implementations all inherit `PublicBase`.
|
|
|
|
class PrivateBase;
|
|
|
|
|
|
|
|
// Base class for all GraphDb implementations exposes to the client programmer.
|
|
|
|
// Encapsulates an instance of a private implementation of GraphDb and performs
|
|
|
|
// initialization and cleanup.
|
|
|
|
class PublicBase : public GraphDb {
|
|
|
|
public:
|
2018-01-22 19:36:14 +08:00
|
|
|
Type type() const override;
|
2018-01-19 21:49:58 +08:00
|
|
|
Storage &storage() override;
|
|
|
|
durability::WriteAheadLog &wal() override;
|
|
|
|
tx::Engine &tx_engine() override;
|
|
|
|
storage::ConcurrentIdMapper<storage::Label> &label_mapper() override;
|
|
|
|
storage::ConcurrentIdMapper<storage::EdgeType> &edge_type_mapper() override;
|
|
|
|
storage::ConcurrentIdMapper<storage::Property> &property_mapper() override;
|
|
|
|
database::Counters &counters() override;
|
|
|
|
void CollectGarbage() override;
|
|
|
|
int WorkerId() const override;
|
2018-01-22 19:36:14 +08:00
|
|
|
distributed::RemoteDataRpcServer &remote_data_server() override;
|
|
|
|
distributed::RemoteDataRpcClients &remote_data_clients() override;
|
2018-01-23 18:00:50 +08:00
|
|
|
distributed::PlanDispatcher &plan_dispatcher() override;
|
2018-01-31 23:07:23 +08:00
|
|
|
distributed::RpcWorkerClients &index_rpc_clients() override;
|
2018-01-23 18:00:50 +08:00
|
|
|
distributed::PlanConsumer &plan_consumer() override;
|
2018-01-25 17:09:54 +08:00
|
|
|
distributed::RemotePullRpcClients &remote_pull_clients() override;
|
|
|
|
distributed::RemoteProduceRpcServer &remote_produce_server() override;
|
2017-10-30 17:43:25 +08:00
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
protected:
|
2018-01-19 21:49:58 +08:00
|
|
|
explicit PublicBase(std::unique_ptr<PrivateBase> impl);
|
|
|
|
~PublicBase();
|
2017-12-20 19:48:19 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
std::unique_ptr<PrivateBase> impl_;
|
2017-10-30 17:43:25 +08:00
|
|
|
|
|
|
|
private:
|
2018-01-12 22:17:04 +08:00
|
|
|
std::unique_ptr<Scheduler> snapshot_creator_;
|
2017-11-13 16:50:49 +08:00
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
void MakeSnapshot();
|
|
|
|
};
|
2018-01-19 21:49:58 +08:00
|
|
|
} // namespace impl
|
2017-04-10 21:44:36 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
class MasterBase : public impl::PublicBase {
|
2018-01-12 22:17:04 +08:00
|
|
|
public:
|
2018-01-19 21:49:58 +08:00
|
|
|
explicit MasterBase(std::unique_ptr<impl::PrivateBase> impl);
|
2018-01-12 22:17:04 +08:00
|
|
|
bool is_accepting_transactions() const { return is_accepting_transactions_; }
|
2017-08-11 15:48:13 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
~MasterBase();
|
2017-05-17 16:08:57 +08:00
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
private:
|
|
|
|
/** When this is false, no new transactions should be created. */
|
|
|
|
std::atomic<bool> is_accepting_transactions_{true};
|
2017-08-17 15:19:58 +08:00
|
|
|
Scheduler transaction_killer_;
|
2018-01-12 22:17:04 +08:00
|
|
|
};
|
2017-09-13 23:09:04 +08:00
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
class SingleNode : public MasterBase {
|
|
|
|
public:
|
|
|
|
explicit SingleNode(Config config = Config());
|
|
|
|
};
|
2017-12-19 19:40:30 +08:00
|
|
|
|
2018-01-12 22:17:04 +08:00
|
|
|
class Master : public MasterBase {
|
|
|
|
public:
|
|
|
|
explicit Master(Config config = Config());
|
2018-01-22 19:36:14 +08:00
|
|
|
/** Gets this master's endpoint. */
|
|
|
|
io::network::Endpoint endpoint() const;
|
|
|
|
/** Gets the endpoint of the worker with the given id. */
|
|
|
|
// TODO make const once Coordination::GetEndpoint is const.
|
|
|
|
io::network::Endpoint GetEndpoint(int worker_id);
|
2018-01-12 22:17:04 +08:00
|
|
|
};
|
2017-12-19 19:40:30 +08:00
|
|
|
|
2018-01-19 21:49:58 +08:00
|
|
|
class Worker : public impl::PublicBase {
|
2018-01-12 22:17:04 +08:00
|
|
|
public:
|
|
|
|
explicit Worker(Config config = Config());
|
2018-01-22 19:36:14 +08:00
|
|
|
/** Gets this worker's endpoint. */
|
|
|
|
io::network::Endpoint endpoint() const;
|
|
|
|
/** Gets the endpoint of the worker with the given id. */
|
|
|
|
// TODO make const once Coordination::GetEndpoint is const.
|
|
|
|
io::network::Endpoint GetEndpoint(int worker_id);
|
2018-01-12 22:17:04 +08:00
|
|
|
void WaitForShutdown();
|
2017-02-04 16:01:15 +08:00
|
|
|
};
|
2018-01-12 22:17:04 +08:00
|
|
|
} // namespace database
|