store: implement serialize method, use it

For triggering saving the contacts / labels caches.
This commit is contained in:
Dirk-Jan C. Binnema
2025-09-01 08:21:37 +03:00
committed by Seth Ladygo
parent 5ba4791add
commit bb399bc37a
4 changed files with 59 additions and 6 deletions

View File

@ -889,6 +889,7 @@ Server::Private::index_handler(const Command& cmd)
throw Error{Error::Code::Xapian, "indexer is already running"};
do_index(conf);
store().serialize();
}
void

View File

@ -17,7 +17,6 @@
**
*/
#ifndef MU_LABELS_CACHE_HH
#define MU_LABELS_CACHE_HH
@ -59,6 +58,7 @@ public:
label_map_.insert({label, 1});
else
++it->second;
dirty_ = true;
}
/**
* Remove a label occurrence from the cache
@ -73,6 +73,7 @@ public:
label_map_.erase(it);
else
--it->second;
dirty_ = true;
}
}
@ -107,13 +108,15 @@ public:
/**
* Serialize the cache into a string.
*
* Note: this also marks the cache a _non_ dirty;
*
* @return serialized cache
*/
std::string serialize() const {
[[nodiscard]] std::string serialize() const {
std::string s;
for (const auto&[label, n]: label_map_)
s += mu_format("{}{}{}\n", label, SepaChar2, n);
dirty_ = false;
return s;
}
@ -140,8 +143,20 @@ public:
return map;
}
/**
* Is the cache "dirty"?
*
* I.e. have there been changes since "serialize()" was called?
*
* @return true or false
*/
bool dirty() const {
return dirty_;
}
private:
Map label_map_;
mutable bool dirty_{};
};
class Store;

View File

@ -85,11 +85,11 @@ struct Store::Private {
}
~Private() try {
mu_debug("closing store @ {}", xapian_db_.path());
if (!xapian_db_.read_only()) {
contacts_cache_.serialize();
config_.set<Config::Id::Labels>(labels_cache_.serialize());
if (const auto res = serialize(); !res)
mu_critical("failed to serialize: {}", res.error().what());
}
mu_debug("closing store @ {}", xapian_db_.path());
} catch (...) {
mu_critical("caught exception in store dtor");
}
@ -119,6 +119,8 @@ struct Store::Private {
return Message::Options::None;
}
Result<void> serialize();
Option<Message> find_message_unlocked(Store::Id docid) const;
Store::IdVec find_duplicates_unlocked(const Store& store,
const std::string& message_id) const;
@ -145,6 +147,23 @@ struct Store::Private {
};
Result<void>
Store::Private::serialize()
{
if (xapian_db_.read_only())
return Err(Error::Code::Store, "store must be writable");
mu_debug("serialize data into store @ {}", xapian_db_.path());
contacts_cache_.serialize(); // does the 'dirty' check internally.
if (labels_cache_.dirty())
config_.set<Config::Id::Labels>(labels_cache_.serialize());
return Ok();
}
Result<Store::Id>
Store::Private::add_message_unlocked(Message& msg)
{
@ -335,6 +354,13 @@ Store::contacts_cache() const
return priv_->contacts_cache_;
}
Result<void>
Store::serialize()
{
std::lock_guard guard{priv_->lock_};
return priv_->serialize();
}
Indexer&
Store::indexer()
{

View File

@ -140,6 +140,17 @@ public:
*/
const ContactsCache& contacts_cache() const;
/**
* Serialize ephemeral information such as contacts, labels,
* in the database.
*
* Only available when using a writable database.
*
* @return Ok() or some error.
*/
Result<void> serialize();
/**
* Get the Indexer associated with this store. It is an error to call
* this on a read-only store.