From 3f7f199cb940c8d5f6d48f77fd59971adffe49ef Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 7 Dec 2023 16:57:05 +1100 Subject: Remove pre-iterator concepts - No more IndexRecord/Result/dbGetPage nonsense - Queue is just track ids - i am so tired and have so much to do --- src/database/include/database.hpp | 229 +++++++++++++++------------------ src/database/include/file_gatherer.hpp | 8 +- src/database/include/tag_parser.hpp | 14 +- src/database/include/track.hpp | 2 +- 4 files changed, 113 insertions(+), 140 deletions(-) (limited to 'src/database/include') diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp index 327db3cb..c75dbf96 100644 --- a/src/database/include/database.hpp +++ b/src/database/include/database.hpp @@ -35,61 +35,18 @@ namespace database { -struct Continuation { - std::pmr::string prefix; - std::pmr::string start_key; - bool forward; - bool was_prev_forward; - size_t page_size; -}; +struct SearchKey; +class Record; +class Iterator; /* - * Wrapper for a set of results from the database. Owns the list of results, as - * well as a continuation token that can be used to continue fetching more - * results if they were paginated. + * Handle to an open database. This can be used to store large amounts of + * persistent data on the SD card, in a manner that can be retrieved later very + * quickly. + * + * A database includes a number of 'indexes'. Each index is a sorted, + * hierarchical view of all the playable tracks on the device. */ -template -class Result { - public: - auto values() const -> const std::vector>& { - return values_; - } - - auto next_page() -> std::optional& { return next_page_; } - auto prev_page() -> std::optional& { return prev_page_; } - - Result(const std::vector>&& values, - std::optional next, - std::optional prev) - : values_(values), next_page_(next), prev_page_(prev) {} - - Result(const Result&) = delete; - Result& operator=(const Result&) = delete; - - private: - std::vector> values_; - std::optional next_page_; - std::optional prev_page_; -}; - -class IndexRecord { - public: - explicit IndexRecord(const IndexKey&, - std::optional, - std::optional); - - auto text() const -> std::optional; - auto track() const -> std::optional; - - auto Expand(std::size_t) const -> std::optional; - auto ExpandHeader() const -> IndexKey::Header; - - private: - IndexKey key_; - std::optional override_text_; - std::optional track_; -}; - class Database { public: enum DatabaseError { @@ -106,31 +63,19 @@ class Database { ~Database(); - auto Put(const std::string& key, const std::string& val) -> void; - auto Get(const std::string& key) -> std::optional; - - auto Update() -> std::future; + /* Adds an arbitrary record to the database. */ + auto put(const std::string& key, const std::string& val) -> void; - auto GetTrackPath(TrackId id) -> std::future>; + /* Retrives a value previously stored with `put`. */ + auto get(const std::string& key) -> std::optional; - auto GetTrack(TrackId id) -> std::future>; + auto getTrackPath(TrackId id) -> std::optional; + auto getTrack(TrackId id) -> std::shared_ptr; - /* - * Fetches data for multiple tracks more efficiently than multiple calls to - * GetTrack. - */ - auto GetBulkTracks(std::vector id) - -> std::future>>; - - auto GetIndexes() -> std::vector; - auto GetTracksByIndex(IndexId index, std::size_t page_size) - -> std::future*>; - auto GetTracks(std::size_t page_size) -> std::future*>; - auto GetDump(std::size_t page_size) -> std::future*>; - - template - auto GetPage(Continuation* c) -> std::future*>; + auto getIndexes() -> std::vector; + auto updateIndexes() -> void; + // Cannot be copied or moved. Database(const Database&) = delete; Database& operator=(const Database&) = delete; @@ -157,106 +102,134 @@ class Database { std::shared_ptr worker); auto dbMintNewTrackId() -> TrackId; - auto dbEntomb(TrackId track, uint64_t hash) -> void; + auto dbEntomb(TrackId track, uint64_t hash) -> void; auto dbPutTrackData(const TrackData& s) -> void; auto dbGetTrackData(TrackId id) -> std::shared_ptr; auto dbPutHash(const uint64_t& hash, TrackId i) -> void; auto dbGetHash(const uint64_t& hash) -> std::optional; + auto dbCreateIndexesForTrack(const Track& track) -> void; auto dbRemoveIndexes(std::shared_ptr) -> void; + auto dbIngestTagHashes(const TrackTags&, std::pmr::unordered_map&) -> void; auto dbRecoverTagsFromHashes(const std::pmr::unordered_map&) -> std::shared_ptr; - template - auto dbGetPage(const Continuation& c) -> Result*; + auto getRecord(const SearchKey& c) + -> std::optional>; + auto countRecords(const SearchKey& c) -> size_t; +}; - auto dbCount(const Continuation& c) -> size_t; +/* + * Container for the data needed to iterate through database records. This is a + * lower-level type that the higher-level iterators are built from; most users + * outside this namespace shouldn't need to work with continuations. + */ +struct SearchKey { + std::pmr::string prefix; + /* If not given, then iteration starts from `prefix`. */ + std::optional key; + int offset; - template - auto ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) - -> std::shared_ptr; + auto startKey() const -> std::string_view; }; -template <> -auto Database::ParseRecord(const leveldb::Slice& key, - const leveldb::Slice& val) - -> std::shared_ptr; -template <> -auto Database::ParseRecord(const leveldb::Slice& key, - const leveldb::Slice& val) - -> std::shared_ptr; -template <> -auto Database::ParseRecord(const leveldb::Slice& key, - const leveldb::Slice& val) - -> std::shared_ptr; - /* - * Utility for accessing a large set of database records, one record at a time. + * A record belonging to one of the database's indexes. This may either be a + * leaf record, containing a track id, or a branch record, containing a new + * Header to retrieve results at the next level of the index. */ -class Iterator { +class Record { public: - static auto Parse(std::weak_ptr, const cppbor::Array&) - -> std::optional; + Record(const IndexKey&, const leveldb::Slice&); - Iterator(std::weak_ptr, const IndexInfo&); - Iterator(std::weak_ptr, const Continuation&); - Iterator(const Iterator&); + Record(const Record&) = default; + Record& operator=(const Record& other) = default; - Iterator& operator=(const Iterator& other); + auto text() const -> std::string_view; + auto contents() const -> const std::variant&; - auto database() const { return db_; } + private: + std::pmr::string text_; + std::variant contents_; +}; - using Callback = std::function)>; +/* + * Utility for accessing a large set of database records, one record at a time. + */ +class Iterator { + public: + Iterator(std::shared_ptr, IndexId); + Iterator(std::shared_ptr, const IndexKey::Header&); - auto Next(Callback) -> void; - auto NextSync() -> std::optional; + Iterator(const Iterator&) = default; + Iterator& operator=(const Iterator& other) = default; - auto Prev(Callback) -> void; + auto value() const -> const std::optional&; + std::optional operator*() const { return value(); } - auto PeekSync() -> std::optional; + auto next() -> void; + std::optional operator++() { + next(); + return value(); + } + std::optional operator++(int) { + auto val = value(); + next(); + return val; + } - auto Size() const -> size_t; + auto prev() -> void; + std::optional operator--() { + prev(); + return value(); + } + std::optional operator--(int) { + auto val = value(); + prev(); + return val; + } - auto cbor() const -> cppbor::Array&&; + auto count() const -> size_t; private: - Iterator(std::weak_ptr, - std::optional&&, - std::optional&&); + auto iterate(const SearchKey& key) -> void; friend class TrackIterator; - auto InvokeNull(Callback) -> void; - std::weak_ptr db_; - - std::mutex pos_mutex_; - std::optional current_pos_; - std::optional prev_pos_; + SearchKey key_; + std::optional current_; }; class TrackIterator { public: - static auto Parse(std::weak_ptr, const cppbor::Array&) - -> std::optional; - TrackIterator(const Iterator&); - TrackIterator(const TrackIterator&); - TrackIterator& operator=(TrackIterator&& other); + TrackIterator(const TrackIterator&) = default; + TrackIterator& operator=(TrackIterator&& other) = default; + + auto value() const -> std::optional; + std::optional operator*() const { return value(); } - auto Next() -> std::optional; - auto Size() const -> size_t; + auto next() -> void; + std::optional operator++() { + next(); + return value(); + } + std::optional operator++(int) { + auto val = value(); + next(); + return val; + } - auto cbor() const -> cppbor::Array&&; + auto count() const -> size_t; private: TrackIterator(std::weak_ptr); - - auto NextLeaf() -> void; + auto next(bool advance) -> void; std::weak_ptr db_; std::vector levels_; diff --git a/src/database/include/file_gatherer.hpp b/src/database/include/file_gatherer.hpp index 378727f7..66127bb7 100644 --- a/src/database/include/file_gatherer.hpp +++ b/src/database/include/file_gatherer.hpp @@ -20,16 +20,16 @@ class IFileGatherer { virtual ~IFileGatherer(){}; virtual auto FindFiles( - const std::pmr::string& root, - std::function cb) + const std::string& root, + std::function cb) -> void = 0; }; class FileGathererImpl : public IFileGatherer { public: virtual auto FindFiles( - const std::pmr::string& root, - std::function cb) + const std::string& root, + std::function cb) -> void override; }; diff --git a/src/database/include/tag_parser.hpp b/src/database/include/tag_parser.hpp index 04817c59..977c9afc 100644 --- a/src/database/include/tag_parser.hpp +++ b/src/database/include/tag_parser.hpp @@ -16,24 +16,24 @@ namespace database { class ITagParser { public: virtual ~ITagParser() {} - virtual auto ReadAndParseTags(const std::pmr::string& path) + virtual auto ReadAndParseTags(const std::string& path) -> std::shared_ptr = 0; }; class GenericTagParser : public ITagParser { public: - auto ReadAndParseTags(const std::pmr::string& path) + auto ReadAndParseTags(const std::string& path) -> std::shared_ptr override; }; class TagParserImpl : public ITagParser { public: TagParserImpl(); - auto ReadAndParseTags(const std::pmr::string& path) + auto ReadAndParseTags(const std::string& path) -> std::shared_ptr override; private: - std::map> extension_to_parser_; + std::map> extension_to_parser_; GenericTagParser generic_parser_; /* @@ -43,14 +43,14 @@ class TagParserImpl : public ITagParser { std::mutex cache_mutex_; util::LruCache<16, std::pmr::string, std::shared_ptr> cache_; - // We could also consider keeping caches of artist name -> std::pmr::string - // and similar. This hasn't been done yet, as this isn't a common workload in + // We could also consider keeping caches of artist name -> std::string and + // similar. This hasn't been done yet, as this isn't a common workload in // any of our UI. }; class OpusTagParser : public ITagParser { public: - auto ReadAndParseTags(const std::pmr::string& path) + auto ReadAndParseTags(const std::string& path) -> std::shared_ptr override; }; diff --git a/src/database/include/track.hpp b/src/database/include/track.hpp index 8a24024f..0497c94d 100644 --- a/src/database/include/track.hpp +++ b/src/database/include/track.hpp @@ -123,7 +123,7 @@ struct TrackData { public: TrackData() : id(0), - filepath(&memory::kSpiRamResource), + filepath(), tags_hash(0), individual_tag_hashes(&memory::kSpiRamResource), is_tombstoned(false), -- cgit v1.2.3