index/store: simplify transaction handling
only have transactions for indexing, and make it opportunistic. All other ops do not use transactions.
This commit is contained in:
@ -72,11 +72,13 @@ struct Indexer::Private {
|
||||
[this](auto&& path, auto&& statbuf, auto&& info) {
|
||||
return handler(path, statbuf, info);
|
||||
}},
|
||||
max_message_size_{store_.metadata().max_message_size}
|
||||
max_message_size_{store_.metadata().max_message_size},
|
||||
batch_size_{store_.metadata().batch_size}
|
||||
{
|
||||
g_message("created indexer for %s -> %s",
|
||||
g_message("created indexer for %s -> %s (batch-size: %zu)",
|
||||
store.metadata().root_maildir.c_str(),
|
||||
store.metadata().database_path.c_str());
|
||||
store.metadata().database_path.c_str(),
|
||||
batch_size_);
|
||||
}
|
||||
|
||||
~Private() { stop(); }
|
||||
@ -104,8 +106,10 @@ struct Indexer::Private {
|
||||
|
||||
AsyncQueue<std::string> fq_;
|
||||
|
||||
Progress progress_;
|
||||
IndexState state_;
|
||||
Progress progress_;
|
||||
IndexState state_;
|
||||
const size_t batch_size_; /**< Max number of messages added before
|
||||
* committing */
|
||||
|
||||
std::mutex lock_, wlock_;
|
||||
};
|
||||
@ -192,6 +196,11 @@ Indexer::Private::worker()
|
||||
|
||||
g_debug("started worker");
|
||||
|
||||
/* note that transaction starting/committing is opportunistic,
|
||||
* and are NOPs if we are already/not in a transaction */
|
||||
|
||||
store_.begin_transaction();
|
||||
|
||||
while (state_ == IndexState::Scanning || !fq_.empty()) {
|
||||
if (!fq_.pop(item, 250ms))
|
||||
continue;
|
||||
@ -200,15 +209,24 @@ Indexer::Private::worker()
|
||||
++progress_.processed;
|
||||
|
||||
try {
|
||||
std::unique_lock lock{lock_};
|
||||
|
||||
store_.add_message(item);
|
||||
++progress_.updated;
|
||||
|
||||
if (progress_.updated % batch_size_ == 0) {
|
||||
store_.commit_transaction();
|
||||
store_.begin_transaction();
|
||||
}
|
||||
|
||||
} catch (const Mu::Error& er) {
|
||||
g_warning("error adding message @ %s: %s", item.c_str(), er.what());
|
||||
}
|
||||
|
||||
maybe_start_worker();
|
||||
}
|
||||
|
||||
store_.commit_transaction();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -230,9 +248,14 @@ Indexer::Private::cleanup()
|
||||
return state_ == IndexState::Cleaning;
|
||||
});
|
||||
|
||||
g_debug("remove %zu message(s) from store", orphans.size());
|
||||
store_.remove_messages(orphans);
|
||||
progress_.removed += orphans.size();
|
||||
// No need for transactions here, remove_messages does that for us.
|
||||
if (orphans.empty())
|
||||
g_debug("nothing to clean up");
|
||||
else {
|
||||
g_debug("removing up %zu stale message(s) from store", orphans.size());
|
||||
store_.remove_messages(orphans);
|
||||
progress_.removed += orphans.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -280,14 +303,11 @@ Indexer::Private::start(const Indexer::Config& conf)
|
||||
cleanup();
|
||||
g_debug("cleanup finished");
|
||||
}
|
||||
|
||||
store_.commit();
|
||||
leave:
|
||||
state_.change_to(IndexState::Idle);
|
||||
});
|
||||
|
||||
g_debug("started indexer");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user