fix some leveldb errors on transition to standby

turns out you gotta free the iterators. wow!!
custom
jacqueline 2 years ago
parent e8a972cc7f
commit 64d9cec8b0
  1. 48
      src/database/database.cpp

@ -46,19 +46,6 @@ static const char kTrackIdKey[] = "next_track_id";
static std::atomic<bool> sIsDbOpen(false); static std::atomic<bool> sIsDbOpen(false);
template <typename Parser>
auto IterateAndParse(leveldb::Iterator* it, std::size_t limit, Parser p)
-> void {
for (int i = 0; i < limit; i++) {
if (!it->Valid()) {
delete it;
break;
}
std::invoke(p, it->key(), it->value());
it->Next();
}
}
auto Database::Open(IFileGatherer& gatherer, ITagParser& parser) auto Database::Open(IFileGatherer& gatherer, ITagParser& parser)
-> cpp::result<Database*, DatabaseError> { -> cpp::result<Database*, DatabaseError> {
// TODO(jacqueline): Why isn't compare_and_exchange_* available? // TODO(jacqueline): Why isn't compare_and_exchange_* available?
@ -66,8 +53,11 @@ auto Database::Open(IFileGatherer& gatherer, ITagParser& parser)
return cpp::fail(DatabaseError::ALREADY_OPEN); return cpp::fail(DatabaseError::ALREADY_OPEN);
} }
leveldb::sBackgroundThread.reset( if (!leveldb::sBackgroundThread) {
tasks::Worker::Start<tasks::Type::kDatabaseBackground>()); leveldb::sBackgroundThread.reset(
tasks::Worker::Start<tasks::Type::kDatabaseBackground>());
}
std::shared_ptr<tasks::Worker> worker( std::shared_ptr<tasks::Worker> worker(
tasks::Worker::Start<tasks::Type::kDatabase>()); tasks::Worker::Start<tasks::Type::kDatabase>());
return worker return worker
@ -120,8 +110,6 @@ Database::~Database() {
delete db_; delete db_;
delete cache_; delete cache_;
leveldb::sBackgroundThread.reset();
sIsDbOpen.store(false); sIsDbOpen.store(false);
} }
@ -136,7 +124,7 @@ auto Database::Update() -> std::future<void> {
// indexes, but my brain hurts. // indexes, but my brain hurts.
ESP_LOGI(kTag, "dropping stale indexes"); ESP_LOGI(kTag, "dropping stale indexes");
{ {
leveldb::Iterator* it = db_->NewIterator(read_options); std::unique_ptr<leveldb::Iterator> it{db_->NewIterator(read_options)};
OwningSlice prefix = EncodeAllIndexesPrefix(); OwningSlice prefix = EncodeAllIndexesPrefix();
it->Seek(prefix.slice); it->Seek(prefix.slice);
while (it->Valid() && it->key().starts_with(prefix.slice)) { while (it->Valid() && it->key().starts_with(prefix.slice)) {
@ -151,7 +139,7 @@ auto Database::Update() -> std::future<void> {
.stage = event::UpdateProgress::Stage::kVerifyingExistingTracks, .stage = event::UpdateProgress::Stage::kVerifyingExistingTracks,
}); });
{ {
leveldb::Iterator* it = db_->NewIterator(read_options); std::unique_ptr<leveldb::Iterator> it{db_->NewIterator(read_options)};
OwningSlice prefix = EncodeDataPrefix(); OwningSlice prefix = EncodeDataPrefix();
it->Seek(prefix.slice); it->Seek(prefix.slice);
while (it->Valid() && it->key().starts_with(prefix.slice)) { while (it->Valid() && it->key().starts_with(prefix.slice)) {
@ -200,7 +188,6 @@ auto Database::Update() -> std::future<void> {
it->Next(); it->Next();
} }
delete it;
} }
// Stage 2: search for newly added files. // Stage 2: search for newly added files.
@ -302,7 +289,8 @@ auto Database::GetBulkTracks(std::vector<TrackId> ids)
std::vector<TrackId> sorted_ids = ids; std::vector<TrackId> sorted_ids = ids;
std::sort(sorted_ids.begin(), sorted_ids.end()); std::sort(sorted_ids.begin(), sorted_ids.end());
leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions{}); std::unique_ptr<leveldb::Iterator> it{
db_->NewIterator(leveldb::ReadOptions{})};
for (const TrackId& id : sorted_ids) { for (const TrackId& id : sorted_ids) {
OwningSlice key = EncodeDataKey(id); OwningSlice key = EncodeDataKey(id);
it->Seek(key.slice); it->Seek(key.slice);
@ -476,7 +464,8 @@ auto Database::dbCreateIndexesForTrack(Track track) -> void {
template <typename T> template <typename T>
auto Database::dbGetPage(const Continuation<T>& c) -> Result<T>* { auto Database::dbGetPage(const Continuation<T>& c) -> Result<T>* {
// Work out our starting point. Sometimes this will already done. // Work out our starting point. Sometimes this will already done.
leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions()); std::unique_ptr<leveldb::Iterator> it{
db_->NewIterator(leveldb::ReadOptions{})};
it->Seek(c.start_key); it->Seek(c.start_key);
// Fix off-by-one if we just changed direction. // Fix off-by-one if we just changed direction.
@ -509,11 +498,8 @@ auto Database::dbGetPage(const Continuation<T>& c) -> Result<T>* {
} }
} }
std::unique_ptr<leveldb::Iterator> iterator(it); if (!it->Valid() || !it->key().starts_with(c.prefix)) {
if (iterator != nullptr) { it.reset();
if (!iterator->Valid() || !it->key().starts_with(c.prefix)) {
iterator.reset();
}
} }
// Put results into canonical order if we were iterating backwards. // Put results into canonical order if we were iterating backwards.
@ -524,9 +510,9 @@ auto Database::dbGetPage(const Continuation<T>& c) -> Result<T>* {
// Work out the new continuations. // Work out the new continuations.
std::optional<Continuation<T>> next_page; std::optional<Continuation<T>> next_page;
if (c.forward) { if (c.forward) {
if (iterator != nullptr) { if (it != nullptr) {
// We were going forward, and now we want the next page. // We were going forward, and now we want the next page.
std::string key = iterator->key().ToString(); std::string key = it->key().ToString();
next_page = Continuation<T>{ next_page = Continuation<T>{
.prefix = c.prefix, .prefix = c.prefix,
.start_key = key, .start_key = key,
@ -561,9 +547,9 @@ auto Database::dbGetPage(const Continuation<T>& c) -> Result<T>* {
.page_size = c.page_size, .page_size = c.page_size,
}; };
} else { } else {
if (iterator != nullptr) { if (it != nullptr) {
// We were going backwards, and we still want to go backwards. // We were going backwards, and we still want to go backwards.
std::string key = iterator->key().ToString(); std::string key = it->key().ToString();
prev_page = Continuation<T>{ prev_page = Continuation<T>{
.prefix = c.prefix, .prefix = c.prefix,
.start_key = key, .start_key = key,

Loading…
Cancel
Save