CAUTION! This version is not fool proof yet. If you purge data of an OSD by overwriting the disk with zeroes and restart it then the same data will also be removed from other replicas :-). I plan to add protection from this situation before merging it into master. The idea is to make each OSD store a random "cookie" on disk and remove itself from history automatically if the cookie doesn't match.
147 lines
4.5 KiB
C++
147 lines
4.5 KiB
C++
// Copyright (c) Vitaliy Filippov, 2019+
|
|
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
|
|
|
|
#pragma once
|
|
|
|
#include "json11/json11.hpp"
|
|
#include "osd_id.h"
|
|
#include "timerfd_manager.h"
|
|
|
|
#define ETCD_CONFIG_WATCH_ID 1
|
|
#define ETCD_PG_STATE_WATCH_ID 2
|
|
#define ETCD_PG_HISTORY_WATCH_ID 3
|
|
#define ETCD_OSD_STATE_WATCH_ID 4
|
|
|
|
#define DEFAULT_BLOCK_SIZE 128*1024
|
|
#define MIN_DATA_BLOCK_SIZE 4*1024
|
|
#define MAX_DATA_BLOCK_SIZE 128*1024*1024
|
|
#define DEFAULT_BITMAP_GRANULARITY 4096
|
|
|
|
#define IMMEDIATE_NONE 0
|
|
#define IMMEDIATE_SMALL 1
|
|
#define IMMEDIATE_ALL 2
|
|
|
|
struct etcd_kv_t
|
|
{
|
|
std::string key;
|
|
json11::Json value;
|
|
uint64_t mod_revision;
|
|
};
|
|
|
|
struct pg_config_t
|
|
{
|
|
bool exists;
|
|
osd_num_t primary;
|
|
std::vector<osd_num_t> target_set;
|
|
std::vector<pg_history_set_t> target_history;
|
|
std::vector<osd_num_t> all_peers;
|
|
bool pause;
|
|
osd_num_t cur_primary;
|
|
int cur_state;
|
|
uint64_t epoch;
|
|
};
|
|
|
|
struct pool_config_t
|
|
{
|
|
bool exists;
|
|
pool_id_t id;
|
|
std::string name;
|
|
uint64_t scheme;
|
|
uint64_t pg_size, pg_minsize, parity_chunks;
|
|
uint32_t data_block_size, bitmap_granularity, immediate_commit;
|
|
uint64_t pg_count;
|
|
uint64_t real_pg_count;
|
|
std::string failure_domain;
|
|
uint64_t max_osd_combinations;
|
|
uint64_t pg_stripe_size;
|
|
std::map<pg_num_t, pg_config_t> pg_config;
|
|
};
|
|
|
|
struct inode_config_t
|
|
{
|
|
uint64_t num;
|
|
std::string name;
|
|
uint64_t size;
|
|
inode_t parent_id;
|
|
bool readonly;
|
|
// Arbitrary metadata
|
|
json11::Json meta;
|
|
// Change revision of the metadata in etcd
|
|
uint64_t mod_revision;
|
|
};
|
|
|
|
struct inode_watch_t
|
|
{
|
|
std::string name;
|
|
inode_config_t cfg;
|
|
};
|
|
|
|
struct http_co_t;
|
|
|
|
struct etcd_state_client_t
|
|
{
|
|
protected:
|
|
std::vector<std::string> local_ips;
|
|
std::vector<std::string> etcd_addresses;
|
|
std::vector<std::string> etcd_local;
|
|
std::string selected_etcd_address;
|
|
std::vector<std::string> addresses_to_try;
|
|
std::vector<inode_watch_t*> watches;
|
|
http_co_t *etcd_watch_ws = NULL, *keepalive_client = NULL;
|
|
int ws_keepalive_timer = -1;
|
|
int ws_alive = 0;
|
|
bool rand_initialized = false;
|
|
void add_etcd_url(std::string);
|
|
void pick_next_etcd();
|
|
public:
|
|
int etcd_keepalive_timeout = 30;
|
|
int etcd_ws_keepalive_interval = 30;
|
|
int max_etcd_attempts = 5;
|
|
int etcd_quick_timeout = 1000;
|
|
int etcd_slow_timeout = 5000;
|
|
uint64_t global_block_size = DEFAULT_BLOCK_SIZE;
|
|
uint32_t global_bitmap_granularity = DEFAULT_BITMAP_GRANULARITY;
|
|
uint32_t global_immediate_commit = IMMEDIATE_NONE;
|
|
|
|
std::string etcd_prefix;
|
|
int log_level = 0;
|
|
timerfd_manager_t *tfd = NULL;
|
|
|
|
int etcd_watches_initialised = 0;
|
|
uint64_t etcd_watch_revision = 0;
|
|
std::map<pool_id_t, pool_config_t> pool_config;
|
|
std::map<osd_num_t, json11::Json> peer_states;
|
|
std::map<inode_t, inode_config_t> inode_config;
|
|
std::map<std::string, inode_t> inode_by_name;
|
|
|
|
std::function<void(std::map<std::string, etcd_kv_t> &)> on_change_hook;
|
|
std::function<void(json11::Json::object &)> on_load_config_hook;
|
|
std::function<json11::Json()> load_pgs_checks_hook;
|
|
std::function<void(bool)> on_load_pgs_hook;
|
|
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;
|
|
std::function<void(osd_num_t)> on_change_osd_state_hook;
|
|
std::function<void()> on_reload_hook;
|
|
std::function<void(inode_t, bool)> on_inode_change_hook;
|
|
std::function<void(http_co_t *)> on_start_watcher_hook;
|
|
|
|
json11::Json::object serialize_inode_cfg(inode_config_t *cfg);
|
|
etcd_kv_t parse_etcd_kv(const json11::Json & kv_json);
|
|
std::vector<std::string> get_addresses();
|
|
void etcd_call_oneshot(std::string etcd_address, std::string api, json11::Json payload, int timeout, std::function<void(std::string, json11::Json)> callback);
|
|
void etcd_call(std::string api, json11::Json payload, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
|
void etcd_txn(json11::Json txn, int timeout, int retries, int interval, std::function<void(std::string, json11::Json)> callback);
|
|
void etcd_txn_slow(json11::Json txn, std::function<void(std::string, json11::Json)> callback);
|
|
void start_etcd_watcher();
|
|
void stop_ws_keepalive();
|
|
void start_ws_keepalive();
|
|
void load_global_config();
|
|
void load_pgs();
|
|
void parse_state(const etcd_kv_t & kv);
|
|
void parse_config(const json11::Json & config);
|
|
void insert_inode_config(const inode_config_t & cfg);
|
|
inode_watch_t* watch_inode(std::string name);
|
|
void close_watch(inode_watch_t* watch);
|
|
int address_count();
|
|
~etcd_state_client_t();
|
|
};
|