1#pragma once
2
3#include <Access/IAccessStorage.h>
4#include <list>
5#include <memory>
6#include <mutex>
7#include <unordered_map>
8
9
10namespace DB
11{
12/// Implementation of IAccessStorage which keeps all data in memory.
13class MemoryAccessStorage : public IAccessStorage
14{
15public:
16 MemoryAccessStorage(const String & storage_name_ = "memory");
17 ~MemoryAccessStorage() override;
18
19 /// Sets all entities at once.
20 void setAll(const std::vector<AccessEntityPtr> & all_entities);
21 void setAll(const std::vector<std::pair<UUID, AccessEntityPtr>> & all_entities);
22
23private:
24 std::optional<UUID> findImpl(std::type_index type, const String & name) const override;
25 std::vector<UUID> findAllImpl(std::type_index type) const override;
26 bool existsImpl(const UUID & id) const override;
27 AccessEntityPtr readImpl(const UUID & id) const override;
28 String readNameImpl(const UUID & id) const override;
29 UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
30 void removeImpl(const UUID & id) override;
31 void updateImpl(const UUID & id, const UpdateFunc & update_func) override;
32 SubscriptionPtr subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override;
33 SubscriptionPtr subscribeForChangesImpl(std::type_index type, const OnChangedHandler & handler) const override;
34 bool hasSubscriptionImpl(const UUID & id) const override;
35 bool hasSubscriptionImpl(std::type_index type) const override;
36
37 struct Entry
38 {
39 UUID id;
40 AccessEntityPtr entity;
41 mutable std::list<OnChangedHandler> handlers_by_id;
42 };
43
44 void insertNoLock(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, Notifications & notifications);
45 void removeNoLock(const UUID & id, Notifications & notifications);
46 void updateNoLock(const UUID & id, const UpdateFunc & update_func, Notifications & notifications);
47 void setAllNoLock(const std::vector<std::pair<UUID, AccessEntityPtr>> & all_entities, Notifications & notifications);
48 void prepareNotifications(const Entry & entry, bool remove, Notifications & notifications) const;
49
50 using NameTypePair = std::pair<String, std::type_index>;
51 struct Hash
52 {
53 size_t operator()(const NameTypePair & key) const
54 {
55 return std::hash<String>{}(key.first) - std::hash<std::type_index>{}(key.second);
56 }
57 };
58
59 mutable std::mutex mutex;
60 std::unordered_map<UUID, Entry> entries; /// We want to search entries both by ID and by the pair of name and type.
61 std::unordered_map<NameTypePair, Entry *, Hash> names; /// and by the pair of name and type.
62 mutable std::unordered_multimap<std::type_index, OnChangedHandler> handlers_by_type;
63 std::shared_ptr<const MemoryAccessStorage *> shared_ptr_to_this; /// We need weak pointers to `this` to implement subscriptions.
64};
65}
66