summaryrefslogtreecommitdiff
path: root/src/database/include/database.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/database/include/database.hpp')
-rw-r--r--src/database/include/database.hpp80
1 files changed, 62 insertions, 18 deletions
diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp
index bc102ca8..61918d96 100644
--- a/src/database/include/database.hpp
+++ b/src/database/include/database.hpp
@@ -11,6 +11,7 @@
#include "leveldb/cache.h"
#include "leveldb/db.h"
#include "leveldb/iterator.h"
+#include "leveldb/options.h"
#include "leveldb/slice.h"
#include "result.hpp"
@@ -33,17 +34,33 @@ struct Song {
struct SongMetadata {};
+typedef std::unique_ptr<leveldb::Iterator> Continuation;
+
template <typename T>
-class DbResult {
+class Result {
public:
- DbResult(const std::vector<T>& values, std::unique_ptr<leveldb::Iterator> it)
- : values_(values), it_(std::move(it)) {}
- auto values() -> std::vector<T> { return values_; }
- auto it() -> leveldb::Iterator* { return it_.release(); };
+ auto values() -> std::unique_ptr<std::vector<T>> {
+ return std::move(values_);
+ }
+ auto continuation() -> Continuation { return std::move(c_); }
+ auto HasMore() -> bool { return c_->Valid(); }
+
+ Result(std::unique_ptr<std::vector<T>> values, Continuation c)
+ : values_(std::move(values)), c_(std::move(c)) {}
+
+ Result(Result&& other)
+ : values_(std::move(other.values_)), c_(std::move(other.c_)) {}
+
+ Result operator=(Result&& other) {
+ return Result(other.values(), other.continuation());
+ }
+
+ Result(const Result&) = delete;
+ Result& operator=(const Result&) = delete;
private:
- std::vector<T> values_;
- std::unique_ptr<leveldb::Iterator> it_;
+ std::unique_ptr<std::vector<T>> values_;
+ Continuation c_;
};
class Database {
@@ -58,23 +75,23 @@ class Database {
auto Populate() -> std::future<void>;
- auto GetArtists(std::size_t page_size) -> std::future<DbResult<Artist>>;
- auto GetMoreArtists(std::size_t page_size, DbResult<Artist> continuation)
- -> std::future<DbResult<Artist>>;
+ auto GetArtists(std::size_t page_size) -> std::future<Result<Artist>>;
+ auto GetMoreArtists(std::size_t page_size, Continuation c)
+ -> std::future<Result<Artist>>;
auto GetAlbums(std::size_t page_size, std::optional<Artist> artist)
- -> std::future<DbResult<Album>>;
- auto GetMoreAlbums(std::size_t page_size, DbResult<Album> continuation)
- -> std::future<DbResult<Album>>;
+ -> std::future<Result<Album>>;
+ auto GetMoreAlbums(std::size_t page_size, Continuation c)
+ -> std::future<Result<Album>>;
- auto GetSongs(std::size_t page_size) -> std::future<DbResult<Song>>;
+ auto GetSongs(std::size_t page_size) -> std::future<Result<Song>>;
auto GetSongs(std::size_t page_size, std::optional<Artist> artist)
- -> std::future<DbResult<Song>>;
+ -> std::future<Result<Song>>;
auto GetSongs(std::size_t page_size,
std::optional<Artist> artist,
- std::optional<Album> album) -> std::future<DbResult<Song>>;
- auto GetMoreSongs(std::size_t page_size, DbResult<Song> continuation)
- -> std::future<DbResult<Song>>;
+ std::optional<Album> album) -> std::future<Result<Song>>;
+ auto GetMoreSongs(std::size_t page_size, Continuation c)
+ -> std::future<Result<Song>>;
auto GetSongIds(std::optional<Artist> artist, std::optional<Album> album)
-> std::future<std::vector<SongId_t>>;
@@ -89,6 +106,33 @@ class Database {
std::unique_ptr<leveldb::Cache> cache_;
Database(leveldb::DB* db, leveldb::Cache* cache);
+
+ template <typename T>
+ using Parser = std::function<std::optional<T>(const leveldb::Slice& key,
+ const leveldb::Slice& value)>;
+
+ template <typename T>
+ auto Query(const leveldb::Slice& prefix,
+ std::size_t max_results,
+ Parser<T> parser) -> Result<T> {
+ leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
+ it->Seek(prefix);
+ return Query(it, max_results, parser);
+ }
+
+ template <typename T>
+ auto Query(leveldb::Iterator* it, std::size_t max_results, Parser<T> parser)
+ -> Result<T> {
+ auto results = std::make_unique<std::vector<T>>();
+ for (std::size_t i = 0; i < max_results && it->Valid(); i++) {
+ std::optional<T> r = std::invoke(parser, it->key(), it->value());
+ if (r) {
+ results->push_back(*r);
+ }
+ it->Next();
+ }
+ return {std::move(results), std::unique_ptr<leveldb::Iterator>(it)};
+ }
};
} // namespace database