summaryrefslogtreecommitdiff
path: root/src/database/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/database/include')
-rw-r--r--src/database/include/database.hpp70
-rw-r--r--src/database/include/records.hpp32
-rw-r--r--src/database/include/song.hpp76
-rw-r--r--src/database/include/tag_processor.hpp16
4 files changed, 137 insertions, 57 deletions
diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp
index 61918d96..6cdaaca6 100644
--- a/src/database/include/database.hpp
+++ b/src/database/include/database.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <stdint.h>
#include <cstdint>
#include <future>
#include <memory>
@@ -13,46 +14,37 @@
#include "leveldb/iterator.h"
#include "leveldb/options.h"
#include "leveldb/slice.h"
+#include "records.hpp"
#include "result.hpp"
+#include "song.hpp"
namespace database {
-struct Artist {
- std::string name;
-};
-
-struct Album {
- std::string name;
-};
-
-typedef uint64_t SongId_t;
-
-struct Song {
- std::string title;
- uint64_t id;
-};
-
-struct SongMetadata {};
-
typedef std::unique_ptr<leveldb::Iterator> Continuation;
+/*
+ * 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.
+ */
template <typename T>
class Result {
public:
- auto values() -> std::unique_ptr<std::vector<T>> {
- return std::move(values_);
- }
+ auto values() -> std::vector<T>* { return values_.release(); }
auto continuation() -> Continuation { return std::move(c_); }
auto HasMore() -> bool { return c_->Valid(); }
+ Result(std::vector<T>* values, Continuation c)
+ : values_(values), c_(std::move(c)) {}
+
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_)) {}
+ : values_(move(other.values_)), c_(std::move(other.c_)) {}
Result operator=(Result&& other) {
- return Result(other.values(), other.continuation());
+ return Result(other.values(), std::move(other.continuation()));
}
Result(const Result&) = delete;
@@ -73,30 +65,16 @@ class Database {
~Database();
- auto Populate() -> std::future<void>;
-
- 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<Result<Album>>;
- auto GetMoreAlbums(std::size_t page_size, Continuation c)
- -> std::future<Result<Album>>;
+ auto Update() -> std::future<void>;
+ auto Destroy() -> std::future<void>;
auto GetSongs(std::size_t page_size) -> std::future<Result<Song>>;
- auto GetSongs(std::size_t page_size, std::optional<Artist> artist)
- -> std::future<Result<Song>>;
- auto GetSongs(std::size_t page_size,
- std::optional<Artist> artist,
- 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>>;
- auto GetSongFilePath(SongId_t id) -> std::future<std::optional<std::string>>;
- auto GetSongMetadata(SongId_t id) -> std::future<std::optional<SongMetadata>>;
+ auto GetDump(std::size_t page_size) -> std::future<Result<std::string>>;
+ auto GetMoreDump(std::size_t page_size, Continuation c)
+ -> std::future<Result<std::string>>;
Database(const Database&) = delete;
Database& operator=(const Database&) = delete;
@@ -107,6 +85,16 @@ class Database {
Database(leveldb::DB* db, leveldb::Cache* cache);
+ auto dbMintNewSongId() -> SongId;
+ auto dbEntomb(SongId song, uint64_t hash) -> void;
+
+ auto dbPutSongData(const SongData& s) -> void;
+ auto dbGetSongData(SongId id) -> std::optional<SongData>;
+ auto dbPutHash(const uint64_t& hash, SongId i) -> void;
+ auto dbGetHash(const uint64_t& hash) -> std::optional<SongId>;
+ auto dbPutSong(SongId id, const std::string& path, const uint64_t& hash)
+ -> void;
+
template <typename T>
using Parser = std::function<std::optional<T>(const leveldb::Slice& key,
const leveldb::Slice& value)>;
diff --git a/src/database/include/records.hpp b/src/database/include/records.hpp
new file mode 100644
index 00000000..22d2ca5b
--- /dev/null
+++ b/src/database/include/records.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <leveldb/db.h>
+#include <stdint.h>
+#include <string>
+
+#include "leveldb/slice.h"
+#include "song.hpp"
+
+namespace database {
+
+class OwningSlice {
+ public:
+ std::string data;
+ leveldb::Slice slice;
+
+ explicit OwningSlice(std::string d);
+};
+
+auto CreateDataPrefix() -> OwningSlice;
+auto CreateDataKey(const SongId& id) -> OwningSlice;
+auto CreateDataValue(const SongData& song) -> OwningSlice;
+auto ParseDataValue(const leveldb::Slice& slice) -> std::optional<SongData>;
+
+auto CreateHashKey(const uint64_t& hash) -> OwningSlice;
+auto ParseHashValue(const leveldb::Slice&) -> std::optional<SongId>;
+auto CreateHashValue(SongId id) -> OwningSlice;
+
+auto SongIdToBytes(SongId id) -> OwningSlice;
+auto BytesToSongId(const std::string& bytes) -> SongId;
+
+} // namespace database
diff --git a/src/database/include/song.hpp b/src/database/include/song.hpp
new file mode 100644
index 00000000..79b2160a
--- /dev/null
+++ b/src/database/include/song.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <stdint.h>
+#include <cstdint>
+#include <optional>
+#include <string>
+
+#include "leveldb/db.h"
+#include "span.hpp"
+
+namespace database {
+
+typedef uint32_t SongId;
+
+enum Encoding { ENC_UNSUPPORTED, ENC_MP3 };
+
+struct SongTags {
+ Encoding encoding;
+ std::optional<std::string> title;
+ std::optional<std::string> artist;
+ std::optional<std::string> album;
+ auto Hash() const -> uint64_t;
+};
+
+auto ReadAndParseTags(const std::string& path, SongTags* out) -> bool;
+
+class SongData {
+ private:
+ const SongId id_;
+ const std::string filepath_;
+ const uint64_t tags_hash_;
+ const uint32_t play_count_;
+ const bool is_tombstoned_;
+
+ public:
+ SongData(SongId id, const std::string& path, uint64_t hash)
+ : id_(id),
+ filepath_(path),
+ tags_hash_(hash),
+ play_count_(0),
+ is_tombstoned_(false) {}
+ SongData(SongId id,
+ const std::string& path,
+ uint64_t hash,
+ uint32_t play_count,
+ bool is_tombstoned)
+ : id_(id),
+ filepath_(path),
+ tags_hash_(hash),
+ play_count_(play_count),
+ is_tombstoned_(is_tombstoned) {}
+
+ auto id() const -> SongId { return id_; }
+ auto filepath() const -> std::string { return filepath_; }
+ auto play_count() const -> uint32_t { return play_count_; }
+ auto tags_hash() const -> uint64_t { return tags_hash_; }
+ auto is_tombstoned() const -> bool { return is_tombstoned_; }
+
+ auto UpdateHash(uint64_t new_hash) const -> SongData;
+ auto Entomb() const -> SongData;
+ auto Exhume(const std::string& new_path) const -> SongData;
+};
+
+class Song {
+ public:
+ Song(SongData data, SongTags tags) : data_(data), tags_(tags) {}
+
+ auto data() -> const SongData& { return data_; }
+ auto tags() -> const SongTags& { return tags_; }
+
+ private:
+ const SongData data_;
+ const SongTags tags_;
+};
+
+} // namespace database
diff --git a/src/database/include/tag_processor.hpp b/src/database/include/tag_processor.hpp
deleted file mode 100644
index eda88225..00000000
--- a/src/database/include/tag_processor.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include <string>
-
-namespace database {
-
-struct FileInfo {
- bool is_playable;
- std::string artist;
- std::string album;
- std::string title;
-};
-
-auto GetInfo(const std::string& path, FileInfo* out) -> bool;
-
-} // namespace database