mirror of https://github.com/djcb/mu.git
store: expose metadata()/set_metadata()
Allow for storing metadata in the database, and consider the cache.
This commit is contained in:
parent
3820118246
commit
3086238b33
|
@ -235,8 +235,7 @@ Indexer::Private::item_worker()
|
||||||
++progress_.updated;
|
++progress_.updated;
|
||||||
break;
|
break;
|
||||||
case WorkItem::Type::Dir:
|
case WorkItem::Type::Dir:
|
||||||
store_.set_dirstamp(item.full_path, ::time(NULL),
|
store_.set_dirstamp(item.full_path, ::time(NULL));
|
||||||
true /*use-transaction*/);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_warn_if_reached();
|
g_warn_if_reached();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -194,10 +195,10 @@ struct Store::Private {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
g_debug("committing transaction (n=%zu,%zu)",
|
g_debug("committing transaction (n=%zu,%zu)",
|
||||||
transaction_size_, metadatas_.size());
|
transaction_size_, metadata_cache_.size());
|
||||||
xapian_try([this] {
|
xapian_try([this] {
|
||||||
writable_db().commit_transaction();
|
writable_db().commit_transaction();
|
||||||
for (auto&& mdata : metadatas_)
|
for (auto&& mdata : metadata_cache_)
|
||||||
writable_db().set_metadata(mdata.first, mdata.second);
|
writable_db().set_metadata(mdata.first, mdata.second);
|
||||||
transaction_size_ = 0;
|
transaction_size_ = 0;
|
||||||
});
|
});
|
||||||
|
@ -276,8 +277,7 @@ struct Store::Private {
|
||||||
Xapian::Document new_doc_from_message(MuMsg* msg);
|
Xapian::Document new_doc_from_message(MuMsg* msg);
|
||||||
|
|
||||||
/* metadata to write as part of a transaction commit */
|
/* metadata to write as part of a transaction commit */
|
||||||
using StringPair = std::pair<std::string, std::string>;
|
std::unordered_map<std::string, std::string> metadata_cache_;
|
||||||
std::vector<StringPair> metadatas_;
|
|
||||||
|
|
||||||
const bool read_only_{};
|
const bool read_only_{};
|
||||||
std::unique_ptr<Xapian::Database> db_;
|
std::unique_ptr<Xapian::Database> db_;
|
||||||
|
@ -485,41 +485,54 @@ Store::remove_messages(const std::vector<Store::Id>& ids)
|
||||||
priv_->transaction_maybe_commit(true /*force*/);
|
priv_->transaction_maybe_commit(true /*force*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Store::metadata(const std::string& key) const
|
||||||
|
{
|
||||||
|
// get metadata either from the (uncommitted) cache or from the store.
|
||||||
|
|
||||||
|
std::lock_guard guard{priv_->lock_};
|
||||||
|
|
||||||
|
const auto it = priv_->metadata_cache_.find(key);
|
||||||
|
if (it != priv_->metadata_cache_.end())
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
return xapian_try([&] {
|
||||||
|
return priv_->db().get_metadata(key);
|
||||||
|
}, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Store::set_metadata(const std::string& key, const std::string& val)
|
||||||
|
{
|
||||||
|
// get metadata either from the (uncommitted) cache or from the store.
|
||||||
|
|
||||||
|
std::lock_guard guard{priv_->lock_};
|
||||||
|
|
||||||
|
priv_->metadata_cache_.erase(key);
|
||||||
|
priv_->metadata_cache_.emplace(key, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
Store::dirstamp(const std::string& path) const
|
Store::dirstamp(const std::string& path) const
|
||||||
{
|
{
|
||||||
std::lock_guard guard{priv_->lock_};
|
|
||||||
|
|
||||||
constexpr auto epoch = static_cast<time_t>(0);
|
constexpr auto epoch = static_cast<time_t>(0);
|
||||||
return xapian_try([&] {
|
const auto ts{metadata(path)};
|
||||||
const auto ts = priv_->db().get_metadata(path);
|
|
||||||
if (ts.empty())
|
if (ts.empty())
|
||||||
return epoch;
|
return epoch;
|
||||||
else
|
else
|
||||||
return static_cast<time_t>(strtoll(ts.c_str(), NULL, 16));
|
return static_cast<time_t>(strtoll(ts.c_str(), NULL, 16));
|
||||||
},
|
|
||||||
epoch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Store::set_dirstamp(const std::string& path, time_t tstamp, bool use_transaction)
|
Store::set_dirstamp(const std::string& path, time_t tstamp)
|
||||||
{
|
{
|
||||||
std::lock_guard guard{priv_->lock_};
|
|
||||||
|
|
||||||
std::array<char, 2 * sizeof(tstamp) + 1> data{};
|
std::array<char, 2 * sizeof(tstamp) + 1> data{};
|
||||||
|
|
||||||
const auto len = static_cast<size_t>(
|
const auto len = static_cast<size_t>(
|
||||||
g_snprintf(data.data(), data.size(), "%zx", tstamp));
|
g_snprintf(data.data(), data.size(), "%zx", tstamp));
|
||||||
|
|
||||||
/* set_metadata is not otherwise part of a "transaction" but we want it
|
set_metadata(path, std::string{data.data(), len});
|
||||||
* to be so, so a dirstamp _only_ gets updated when the messages in the
|
|
||||||
* dir are commited */
|
|
||||||
|
|
||||||
Private::StringPair item{path, std::string{data.data(), len}};
|
|
||||||
if (use_transaction)
|
|
||||||
priv_->metadatas_.emplace_back(std::move(item));
|
|
||||||
else
|
|
||||||
xapian_try([&] { priv_->writable_db().set_metadata(item.first, item.second); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MuMsg*
|
MuMsg*
|
||||||
|
|
|
@ -283,6 +283,25 @@ public:
|
||||||
*/
|
*/
|
||||||
size_t for_each_term(const std::string& field, ForEachTermFunc func) const;
|
size_t for_each_term(const std::string& field, ForEachTermFunc func) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the store metadata for @p key
|
||||||
|
*
|
||||||
|
* @param key the metadata key
|
||||||
|
*
|
||||||
|
* @return the metadata value or empty for none.
|
||||||
|
*/
|
||||||
|
std::string metadata(const std::string& key) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write metadata to the store.
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param val value
|
||||||
|
*/
|
||||||
|
void set_metadata(const std::string& key, const std::string& val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the timestamp for some message, or 0 if not found
|
* Get the timestamp for some message, or 0 if not found
|
||||||
*
|
*
|
||||||
|
@ -306,10 +325,8 @@ public:
|
||||||
*
|
*
|
||||||
* @param path a filesystem path
|
* @param path a filesystem path
|
||||||
* @param tstamp the timestamp for that path
|
* @param tstamp the timestamp for that path
|
||||||
* @param whether to do this as part of a transaction
|
|
||||||
*/
|
*/
|
||||||
void set_dirstamp(const std::string& path, time_t tstamp,
|
void set_dirstamp(const std::string& path, time_t tstamp);
|
||||||
bool use_transaction = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of documents in the document database
|
* Get the number of documents in the document database
|
||||||
|
|
Loading…
Reference in New Issue