2020-02-26 22:33:19 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Access/MemoryAccessStorage.h>
|
|
|
|
#include <Common/ThreadPool.h>
|
|
|
|
#include <boost/container/flat_set.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
/// Loads and saves access entities on a local disk to a specified directory.
|
|
|
|
class DiskAccessStorage : public IAccessStorage
|
|
|
|
{
|
|
|
|
public:
|
2020-08-05 19:54:06 +00:00
|
|
|
static constexpr char STORAGE_TYPE[] = "local directory";
|
|
|
|
|
|
|
|
DiskAccessStorage(const String & storage_name_, const String & directory_path_, bool readonly_ = false);
|
|
|
|
DiskAccessStorage(const String & directory_path_, bool readonly_ = false);
|
2020-02-26 22:33:19 +00:00
|
|
|
~DiskAccessStorage() override;
|
|
|
|
|
2020-08-05 19:54:06 +00:00
|
|
|
const char * getStorageType() const override { return STORAGE_TYPE; }
|
2020-09-14 22:51:53 +00:00
|
|
|
String getStorageParamsJSON() const override;
|
2020-09-11 16:54:22 +00:00
|
|
|
|
2020-09-14 22:51:53 +00:00
|
|
|
String getPath() const { return directory_path; }
|
|
|
|
bool isPathEqual(const String & directory_path_) const;
|
2020-09-11 16:54:22 +00:00
|
|
|
|
|
|
|
void setReadOnly(bool readonly_) { readonly = readonly_; }
|
2020-09-14 22:51:53 +00:00
|
|
|
bool isReadOnly() const { return readonly; }
|
2020-02-26 22:33:19 +00:00
|
|
|
|
|
|
|
private:
|
2021-11-18 20:54:18 +00:00
|
|
|
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
|
|
|
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
2020-02-26 22:33:19 +00:00
|
|
|
bool existsImpl(const UUID & id) const override;
|
|
|
|
AccessEntityPtr readImpl(const UUID & id) const override;
|
|
|
|
String readNameImpl(const UUID & id) const override;
|
|
|
|
bool canInsertImpl(const AccessEntityPtr & entity) const override;
|
|
|
|
UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
|
|
|
|
void removeImpl(const UUID & id) override;
|
|
|
|
void updateImpl(const UUID & id, const UpdateFunc & update_func) override;
|
2021-06-15 19:55:21 +00:00
|
|
|
scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override;
|
2021-11-18 20:54:18 +00:00
|
|
|
scope_guard subscribeForChangesImpl(AccessEntityType type, const OnChangedHandler & handler) const override;
|
2020-02-26 22:33:19 +00:00
|
|
|
bool hasSubscriptionImpl(const UUID & id) const override;
|
2021-11-18 20:54:18 +00:00
|
|
|
bool hasSubscriptionImpl(AccessEntityType type) const override;
|
2020-02-26 22:33:19 +00:00
|
|
|
|
2020-05-03 03:12:03 +00:00
|
|
|
void clear();
|
2020-02-26 22:33:19 +00:00
|
|
|
bool readLists();
|
2020-03-18 14:11:44 +00:00
|
|
|
bool writeLists();
|
2021-11-18 20:54:18 +00:00
|
|
|
void scheduleWriteLists(AccessEntityType type);
|
2020-03-18 14:11:44 +00:00
|
|
|
bool rebuildLists();
|
2020-02-26 22:33:19 +00:00
|
|
|
|
|
|
|
void listsWritingThreadFunc();
|
2020-09-07 23:08:42 +00:00
|
|
|
void stopListsWritingThread();
|
2020-02-26 22:33:19 +00:00
|
|
|
|
|
|
|
void insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, Notifications & notifications);
|
|
|
|
void removeNoLock(const UUID & id, Notifications & notifications);
|
|
|
|
void updateNoLock(const UUID & id, const UpdateFunc & update_func, Notifications & notifications);
|
|
|
|
|
|
|
|
AccessEntityPtr readAccessEntityFromDisk(const UUID & id) const;
|
|
|
|
void writeAccessEntityToDisk(const UUID & id, const IAccessEntity & entity) const;
|
|
|
|
void deleteAccessEntityOnDisk(const UUID & id) const;
|
|
|
|
|
|
|
|
using NameToIDMap = std::unordered_map<String, UUID>;
|
|
|
|
struct Entry
|
|
|
|
{
|
2020-05-03 03:12:03 +00:00
|
|
|
UUID id;
|
|
|
|
String name;
|
2021-11-18 20:54:18 +00:00
|
|
|
AccessEntityType type;
|
2020-02-26 22:33:19 +00:00
|
|
|
mutable AccessEntityPtr entity; /// may be nullptr, if the entity hasn't been loaded yet.
|
|
|
|
mutable std::list<OnChangedHandler> handlers_by_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
void prepareNotifications(const UUID & id, const Entry & entry, bool remove, Notifications & notifications) const;
|
|
|
|
|
|
|
|
String directory_path;
|
2020-09-11 16:54:22 +00:00
|
|
|
std::atomic<bool> readonly;
|
2020-05-03 03:12:03 +00:00
|
|
|
std::unordered_map<UUID, Entry> entries_by_id;
|
2021-11-18 20:54:18 +00:00
|
|
|
std::unordered_map<std::string_view, Entry *> entries_by_name_and_type[static_cast<size_t>(AccessEntityType::MAX)];
|
|
|
|
boost::container::flat_set<AccessEntityType> types_of_lists_to_write;
|
2020-02-26 22:33:19 +00:00
|
|
|
bool failed_to_write_lists = false; /// Whether writing of the list files has been failed since the recent restart of the server.
|
|
|
|
ThreadFromGlobalPool lists_writing_thread; /// List files are written in a separate thread.
|
|
|
|
std::condition_variable lists_writing_thread_should_exit; /// Signals `lists_writing_thread` to exit.
|
2020-09-07 23:08:42 +00:00
|
|
|
bool lists_writing_thread_is_waiting = false;
|
2021-11-18 20:54:18 +00:00
|
|
|
mutable std::list<OnChangedHandler> handlers_by_type[static_cast<size_t>(AccessEntityType::MAX)];
|
2020-02-26 22:33:19 +00:00
|
|
|
mutable std::mutex mutex;
|
|
|
|
};
|
|
|
|
}
|