#pragma once #include #include #include #include "store.h" #include "field.h" #include "collection.h" #include "auth_manager.h" // Singleton, for managing meta information of all collections and house keeping class CollectionManager { private: Store *store; AuthManager auth_manager; spp::sparse_hash_map collections; spp::sparse_hash_map collection_id_names; spp::sparse_hash_map collection_symlinks; // Auto incrementing ID assigned to each collection // Using a ID instead of a collection's name makes renaming possible uint32_t next_collection_id; static constexpr const char* COLLECTION_NAME_KEY = "name"; static constexpr const char* COLLECTION_ID_KEY = "id"; static constexpr const char* COLLECTION_SEARCH_FIELDS_KEY = "fields"; static constexpr const char* COLLECTION_DEFAULT_SORTING_FIELD_KEY = "default_sorting_field"; static constexpr const char* COLLECTION_CREATED = "created_at"; static constexpr const char* COLLECTION_NUM_MEMORY_SHARDS = "num_memory_shards"; std::string bootstrap_auth_key; float max_memory_ratio; /// During load, sleep `LOAD_THROTTLE_PERCENT`% of time taken for indexing to prevent CPU saturation float LOAD_THROTTLE_PERCENT = 10; CollectionManager(); ~CollectionManager() = default; Option get_first_index_error(const std::vector& index_records) { for(const auto & index_record: index_records) { if(!index_record.indexed.ok()) { return Option(index_record.indexed.error()); } } return Option(404, "Not found"); } public: static CollectionManager & get_instance() { static CollectionManager instance; return instance; } CollectionManager(CollectionManager const&) = delete; void operator=(CollectionManager const&) = delete; void init(Store *store, const float max_memory_ratio, const std::string & auth_key); Option load(const size_t init_batch_size=1000); // frees in-memory data structures when server is shutdown - helps us run a memory leak detector properly void dispose(); Collection* init_collection(const nlohmann::json & collection_meta, const uint32_t collection_next_seq_id); void add_to_collections(Collection* collection); bool auth_key_matches(const std::string& auth_key_sent, const std::string& action, const std::string& collection, std::map& params); Option create_collection(const std::string& name, const size_t num_memory_shards, const std::vector & fields, const std::string & default_sorting_field, const uint64_t created_at = static_cast(std::time(nullptr))); Collection* get_collection(const std::string & collection_name); Collection* get_collection_with_id(uint32_t collection_id); std::vector get_collections(); Option drop_collection(const std::string& collection_name, const bool remove_from_store = true); uint32_t get_next_collection_id(); static std::string get_symlink_key(const std::string & symlink_name); void set_next_collection_id(uint32_t next_id); Store* get_store(); AuthManager& getAuthManager(); static Option do_search(std::map& req_params, std::string& results_json_str); // symlinks Option resolve_symlink(const std::string & symlink_name); spp::sparse_hash_map & get_symlinks(); Option upsert_symlink(const std::string & symlink_name, const std::string & collection_name); Option delete_symlink(const std::string & symlink_name); static const size_t DEFAULT_NUM_MEMORY_SHARDS = 4; static constexpr const char* NEXT_COLLECTION_ID_KEY = "$CI"; static constexpr const char* SYMLINK_PREFIX = "$SL"; };