diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-12-05 17:00:28 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-12-05 17:00:28 +1100 |
| commit | 009f69c929eb1d1b65d75b0937fbf3b8de5d9148 (patch) | |
| tree | ad7f9994226eb8c57ac7c060d4c4476f5c7d0c46 /src/database/database.cpp | |
| parent | 4f5422e906b1d17720592d97bc0d5e82a71b1e5f (diff) | |
| download | tangara-fw-009f69c929eb1d1b65d75b0937fbf3b8de5d9148.tar.gz | |
Add basic track queue save/load support
Not wired up yet; I need to do a bunch of cleanup before i wire it in
Diffstat (limited to 'src/database/database.cpp')
| -rw-r--r-- | src/database/database.cpp | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/src/database/database.cpp b/src/database/database.cpp index 03451c05..e646154e 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -18,6 +18,7 @@ #include <sstream> #include "collation.hpp" +#include "cppbor.h" #include "esp_log.h" #include "ff.h" #include "freertos/projdefs.h" @@ -52,6 +53,8 @@ static const char kDbPath[] = "/.tangara-db"; static const char kKeyDbVersion[] = "schema_version"; static const uint8_t kCurrentDbVersion = 3; + +static const char kKeyCustom[] = "U\0"; static const char kKeyCollator[] = "collator"; static const char kKeyTrackId[] = "next_track_id"; @@ -197,6 +200,19 @@ Database::~Database() { sIsDbOpen.store(false); } +auto Database::Put(const std::string& key, const std::string& val) -> void { + db_->Put(leveldb::WriteOptions{}, kKeyCustom + key, val); +} + +auto Database::Get(const std::string& key) -> std::optional<std::string> { + std::string val; + auto res = db_->Get(leveldb::ReadOptions{}, kKeyCustom + key, &val); + if (!res.ok()) { + return {}; + } + return val; +} + auto Database::Update() -> std::future<void> { events::Ui().Dispatch(event::UpdateStarted{}); return worker_task_->Dispatch<void>([&]() -> void { @@ -883,6 +899,45 @@ Iterator::Iterator(std::weak_ptr<Database> db, const IndexInfo& idx) .page_size = 1}; } +auto Iterator::Parse(std::weak_ptr<Database> db, const cppbor::Array& encoded) + -> std::optional<Iterator> { + // Ensure the input looks reasonable. + if (encoded.size() != 3) { + return {}; + } + + if (encoded[0]->type() != cppbor::TSTR) { + return {}; + } + const std::string& prefix = encoded[0]->asTstr()->value(); + + std::optional<Continuation> current_pos{}; + if (encoded[1]->type() == cppbor::TSTR) { + const std::string& key = encoded[1]->asTstr()->value(); + current_pos = Continuation{ + .prefix = {prefix.data(), prefix.size()}, + .start_key = {key.data(), key.size()}, + .forward = true, + .was_prev_forward = true, + .page_size = 1, + }; + } + + std::optional<Continuation> prev_pos{}; + if (encoded[2]->type() == cppbor::TSTR) { + const std::string& key = encoded[2]->asTstr()->value(); + current_pos = Continuation{ + .prefix = {prefix.data(), prefix.size()}, + .start_key = {key.data(), key.size()}, + .forward = false, + .was_prev_forward = false, + .page_size = 1, + }; + } + + return Iterator{db, std::move(current_pos), std::move(prev_pos)}; +} + Iterator::Iterator(std::weak_ptr<Database> db, const Continuation& c) : db_(db), pos_mutex_(), current_pos_(c), prev_pos_() {} @@ -892,6 +947,11 @@ Iterator::Iterator(const Iterator& other) current_pos_(other.current_pos_), prev_pos_(other.prev_pos_) {} +Iterator::Iterator(std::weak_ptr<Database> db, + std::optional<Continuation>&& cur, + std::optional<Continuation>&& prev) + : db_(db), current_pos_(cur), prev_pos_(prev) {} + Iterator& Iterator::operator=(const Iterator& other) { current_pos_ = other.current_pos_; prev_pos_ = other.prev_pos_; @@ -995,6 +1055,53 @@ auto Iterator::InvokeNull(Callback cb) -> void { std::invoke(cb, std::optional<IndexRecord>{}); } +auto Iterator::cbor() const -> cppbor::Array&& { + cppbor::Array res; + + std::pmr::string prefix; + if (current_pos_) { + prefix = current_pos_->prefix; + } else if (prev_pos_) { + prefix = prev_pos_->prefix; + } else { + ESP_LOGW(kTag, "iterator has no prefix"); + return std::move(res); + } + + if (current_pos_) { + res.add(cppbor::Tstr(current_pos_->start_key)); + } else { + res.add(cppbor::Null()); + } + + if (prev_pos_) { + res.add(cppbor::Tstr(prev_pos_->start_key)); + } else { + res.add(cppbor::Null()); + } + + return std::move(res); +} + +auto TrackIterator::Parse(std::weak_ptr<Database> db, + const cppbor::Array& encoded) + -> std::optional<TrackIterator> { + TrackIterator ret{db}; + + for (const auto& item : encoded) { + if (item->type() == cppbor::ARRAY) { + auto it = Iterator::Parse(db, *item->asArray()); + if (it) { + ret.levels_.push_back(std::move(*it)); + } else { + return {}; + } + } + } + + return ret; +} + TrackIterator::TrackIterator(const Iterator& it) : db_(it.db_), levels_() { if (it.current_pos_) { levels_.push_back(it); @@ -1005,6 +1112,8 @@ TrackIterator::TrackIterator(const Iterator& it) : db_(it.db_), levels_() { TrackIterator::TrackIterator(const TrackIterator& other) : db_(other.db_), levels_(other.levels_) {} +TrackIterator::TrackIterator(std::weak_ptr<Database> db) : db_(db), levels_() {} + TrackIterator& TrackIterator::operator=(TrackIterator&& other) { levels_ = std::move(other.levels_); return *this; @@ -1057,4 +1166,12 @@ auto TrackIterator::NextLeaf() -> void { } } +auto TrackIterator::cbor() const -> cppbor::Array&& { + cppbor::Array res; + for (const auto& i : levels_) { + res.add(i.cbor()); + } + return std::move(res); +} + } // namespace database |
