mirror of https://github.com/djcb/mu.git
lib: replace CATCH_BLOCK macros with template magic
This commit is contained in:
parent
7156ff7fac
commit
49637dbc3a
|
@ -46,25 +46,22 @@ MuMsgDoc*
|
||||||
Mu::mu_msg_doc_new (XapianDocument *doc, GError **err)
|
Mu::mu_msg_doc_new (XapianDocument *doc, GError **err)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (doc, NULL);
|
g_return_val_if_fail (doc, NULL);
|
||||||
|
MuMsgDoc *mdoc = xapian_try([&]{
|
||||||
try {
|
|
||||||
return new MuMsgDoc ((Xapian::Document*)doc);
|
return new MuMsgDoc ((Xapian::Document*)doc);
|
||||||
|
}, (MuMsgDoc*)nullptr);
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, NULL);
|
if (!mdoc)
|
||||||
|
mu_util_g_set_error (err, MU_ERROR_INTERNAL,
|
||||||
return FALSE;
|
"failed to create message doc");
|
||||||
|
return mdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Mu::mu_msg_doc_destroy (MuMsgDoc *self)
|
Mu::mu_msg_doc_destroy (MuMsgDoc *self)
|
||||||
{
|
{
|
||||||
try {
|
xapian_try([&]{delete self;});
|
||||||
delete self;
|
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gchar*
|
gchar*
|
||||||
Mu::mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
Mu::mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
||||||
{
|
{
|
||||||
|
@ -78,14 +75,12 @@ Mu::mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
||||||
// have to convert to numbers first, esp. when it's a date
|
// have to convert to numbers first, esp. when it's a date
|
||||||
// time_t)
|
// time_t)
|
||||||
|
|
||||||
try {
|
return xapian_try([&]{
|
||||||
const std::string s (self->doc().get_value(mfid));
|
const std::string s (self->doc().get_value(mfid));
|
||||||
return s.empty() ? NULL : g_strdup (s.c_str());
|
return s.empty() ? NULL : g_strdup (s.c_str());
|
||||||
|
},(gchar*)nullptr);
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GSList*
|
GSList*
|
||||||
Mu::mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
Mu::mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
||||||
{
|
{
|
||||||
|
@ -93,12 +88,11 @@ Mu::mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
||||||
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL);
|
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL);
|
||||||
g_return_val_if_fail (mu_msg_field_is_string_list(mfid), NULL);
|
g_return_val_if_fail (mu_msg_field_is_string_list(mfid), NULL);
|
||||||
|
|
||||||
try {
|
return xapian_try([&]{
|
||||||
/* return a comma-separated string as a GSList */
|
/* return a comma-separated string as a GSList */
|
||||||
const std::string s (self->doc().get_value(mfid));
|
const std::string s (self->doc().get_value(mfid));
|
||||||
return s.empty() ? NULL : mu_str_to_list(s.c_str(),',',TRUE);
|
return s.empty() ? NULL : mu_str_to_list(s.c_str(),',',TRUE);
|
||||||
|
},(GSList*)nullptr);
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,17 +103,16 @@ Mu::mu_msg_doc_get_num_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
||||||
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), -1);
|
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), -1);
|
||||||
g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1);
|
g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1);
|
||||||
|
|
||||||
try {
|
return xapian_try([&]{
|
||||||
const std::string s (self->doc().get_value(mfid));
|
const std::string s (self->doc().get_value(mfid));
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
return 0;
|
return (gint64)0;
|
||||||
else if (mfid == MU_MSG_FIELD_ID_DATE ||
|
else if (mfid == MU_MSG_FIELD_ID_DATE ||
|
||||||
mfid == MU_MSG_FIELD_ID_SIZE)
|
mfid == MU_MSG_FIELD_ID_SIZE)
|
||||||
return strtol (s.c_str(), NULL, 10);
|
return static_cast<gint64>(strtol (s.c_str(), NULL, 10));
|
||||||
else {
|
else {
|
||||||
return static_cast<gint64>
|
return static_cast<gint64>
|
||||||
(Xapian::sortable_unserialise(s));
|
(Xapian::sortable_unserialise(s));
|
||||||
}
|
}
|
||||||
|
}, (gint64)-1);
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(-1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,12 +98,14 @@ struct MatchDecider : public Xapian::MatchDecider {
|
||||||
DeciderInfo & decider_info_;
|
DeciderInfo & decider_info_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Option<std::string> opt_string (const Xapian::Document &doc, MuMsgFieldId id) const noexcept
|
Option<std::string> opt_string (const Xapian::Document &doc, MuMsgFieldId id)
|
||||||
try {
|
const noexcept {
|
||||||
auto &&val{doc.get_value (id)};
|
std::string val = xapian_try([&]{ return doc.get_value (id);}, std::string{""});
|
||||||
return val.empty() ? Nothing : Some (val);
|
if (val.empty())
|
||||||
}
|
return Nothing;
|
||||||
MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing);
|
else
|
||||||
|
return Some(std::move(val));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MatchDeciderLeader final : public MatchDecider {
|
struct MatchDeciderLeader final : public MatchDecider {
|
||||||
|
|
|
@ -280,12 +280,14 @@ class QueryResultsIterator
|
||||||
*
|
*
|
||||||
* @return the value
|
* @return the value
|
||||||
*/
|
*/
|
||||||
Option<std::string> opt_string (MuMsgFieldId id) const noexcept
|
Option<std::string> opt_string (MuMsgFieldId id) const noexcept {
|
||||||
try {
|
std::string empty;
|
||||||
auto &&val{document().get_value (id)};
|
std::string val = xapian_try([&]{ return document().get_value (id);}, empty);
|
||||||
return val.empty() ? Nothing : Some (val);
|
if (val.empty())
|
||||||
}
|
return Nothing;
|
||||||
MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing);
|
else
|
||||||
|
return Some(std::move(val));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Query match info for this message.
|
* Get the Query match info for this message.
|
||||||
|
@ -306,27 +308,27 @@ class QueryResultsIterator
|
||||||
/**
|
/**
|
||||||
* get the corresponding MuMsg for this iter; this instance is owned by
|
* get the corresponding MuMsg for this iter; this instance is owned by
|
||||||
* @this, and becomes invalid when iterating to the next, or @this is
|
* @this, and becomes invalid when iterating to the next, or @this is
|
||||||
k * destroyed.; it's a 'floating' reference.
|
* destroyed.; it's a 'floating' reference.
|
||||||
*
|
*
|
||||||
* @return a MuMsg* or NUL in case of error
|
* @return a MuMsg* or NUL in case of error
|
||||||
*/
|
*/
|
||||||
MuMsg *floating_msg() G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT
|
MuMsg *floating_msg() G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT {
|
||||||
try {
|
return xapian_try([&]{
|
||||||
auto docp{reinterpret_cast<XapianDocument *> (new Xapian::Document (document()))};
|
auto docp{reinterpret_cast<XapianDocument *> (
|
||||||
GError *err{};
|
new Xapian::Document (document()))};
|
||||||
g_clear_pointer (&msg_, mu_msg_unref);
|
GError *err{};
|
||||||
if (!(msg_ = mu_msg_new_from_doc (docp, &err))) {
|
g_clear_pointer (&msg_, mu_msg_unref);
|
||||||
delete docp;
|
if (!(msg_ = mu_msg_new_from_doc (docp, &err))) {
|
||||||
g_warning ("failed to crate message for %s: %s",
|
delete docp;
|
||||||
path().value_or ("<none>").c_str(),
|
g_warning ("failed to crate message for %s: %s",
|
||||||
err ? err->message : "somethng went wrong");
|
path().value_or ("<none>").c_str(),
|
||||||
g_clear_error (&err);
|
err ? err->message : "somethng went wrong");
|
||||||
}
|
g_clear_error (&err);
|
||||||
|
}
|
||||||
return msg_;
|
return msg_;
|
||||||
}
|
}, (MuMsg*)NULL);
|
||||||
MU_XAPIAN_CATCH_BLOCK_RETURN (NULL);
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Xapian::MSetIterator mset_it_;
|
Xapian::MSetIterator mset_it_;
|
||||||
QueryMatches & query_matches_;
|
QueryMatches & query_matches_;
|
||||||
|
|
|
@ -174,10 +174,14 @@ Query::Private::run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Option<std::string>
|
static Option<std::string>
|
||||||
opt_string(const Xapian::Document& doc, MuMsgFieldId id) noexcept try {
|
opt_string (const Xapian::Document &doc, MuMsgFieldId id) noexcept
|
||||||
auto&& val{doc.get_value(id)};
|
{
|
||||||
return val.empty() ? Nothing : Some(val);
|
std::string val = xapian_try([&]{ return doc.get_value (id);}, std::string{""});
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing);
|
if (val.empty())
|
||||||
|
return Nothing;
|
||||||
|
else
|
||||||
|
return Some(std::move(val));
|
||||||
|
}
|
||||||
|
|
||||||
Option<QueryResults>
|
Option<QueryResults>
|
||||||
Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
|
@ -259,15 +263,15 @@ Query::run (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Query::count (const std::string& expr) const try
|
Query::count (const std::string& expr) const
|
||||||
{
|
{
|
||||||
const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})};
|
return xapian_try([&] {
|
||||||
auto mset{enq.get_mset(0, priv_->store_.size())};
|
const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})};
|
||||||
mset.fetch();
|
auto mset{enq.get_mset(0, priv_->store_.size())};
|
||||||
|
mset.fetch();
|
||||||
return mset.size();
|
return mset.size();
|
||||||
|
}, 0);
|
||||||
}MU_XAPIAN_CATCH_BLOCK_RETURN (0);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
167
lib/mu-store.cc
167
lib/mu-store.cc
|
@ -115,7 +115,7 @@ struct Store::Private {
|
||||||
contacts_{db().get_metadata(ContactsKey), mdata_.personal_addresses} {
|
contacts_{db().get_metadata(ContactsKey), mdata_.personal_addresses} {
|
||||||
|
|
||||||
if (!readonly)
|
if (!readonly)
|
||||||
writable_db().begin_transaction();
|
begin_transaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
Private (const std::string& path, const std::string& root_maildir,
|
Private (const std::string& path, const std::string& root_maildir,
|
||||||
|
@ -125,7 +125,7 @@ struct Store::Private {
|
||||||
mdata_{init_metadata(conf, path, root_maildir, personal_addresses)},
|
mdata_{init_metadata(conf, path, root_maildir, personal_addresses)},
|
||||||
contacts_{"", mdata_.personal_addresses} {
|
contacts_{"", mdata_.personal_addresses} {
|
||||||
|
|
||||||
writable_db().begin_transaction();
|
begin_transaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
Private (const std::string& root_maildir,
|
Private (const std::string& root_maildir,
|
||||||
|
@ -136,25 +136,32 @@ struct Store::Private {
|
||||||
contacts_{"", mdata_.personal_addresses} {
|
contacts_{"", mdata_.personal_addresses} {
|
||||||
}
|
}
|
||||||
|
|
||||||
~Private() try {
|
~Private() {
|
||||||
g_debug("closing store @ %s", mdata_.database_path.c_str());
|
g_debug("closing store @ %s", mdata_.database_path.c_str());
|
||||||
if (!read_only_) {
|
if (!read_only_) {
|
||||||
writable_db().set_metadata (ContactsKey, contacts_.serialize());
|
xapian_try([&]{
|
||||||
commit();
|
writable_db().set_metadata (ContactsKey, contacts_.serialize());
|
||||||
|
commit();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
}
|
||||||
|
|
||||||
std::unique_ptr<Xapian::Database> make_xapian_db (const std::string db_path, XapianOpts opts) try {
|
std::unique_ptr<Xapian::Database> make_xapian_db (
|
||||||
|
const std::string db_path, XapianOpts opts) try {
|
||||||
|
|
||||||
|
in_transaction_ = false;
|
||||||
|
|
||||||
switch (opts) {
|
switch (opts) {
|
||||||
case XapianOpts::ReadOnly:
|
case XapianOpts::ReadOnly:
|
||||||
return std::make_unique<Xapian::Database>(db_path);
|
return std::make_unique<Xapian::Database>(db_path);
|
||||||
case XapianOpts::Open:
|
case XapianOpts::Open:
|
||||||
return std::make_unique<Xapian::WritableDatabase>(db_path, Xapian::DB_OPEN);
|
return std::make_unique<Xapian::WritableDatabase>(db_path, Xapian::DB_OPEN);
|
||||||
case XapianOpts::CreateOverwrite:
|
case XapianOpts::CreateOverwrite:
|
||||||
return std::make_unique<Xapian::WritableDatabase>(db_path, Xapian::DB_CREATE_OR_OVERWRITE);
|
return std::make_unique<Xapian::WritableDatabase>(
|
||||||
|
db_path, Xapian::DB_CREATE_OR_OVERWRITE);
|
||||||
case XapianOpts::InMemory:
|
case XapianOpts::InMemory:
|
||||||
return std::make_unique<Xapian::WritableDatabase>(std::string{}, Xapian::DB_BACKEND_INMEMORY);
|
return std::make_unique<Xapian::WritableDatabase>(
|
||||||
|
std::string{}, Xapian::DB_BACKEND_INMEMORY);
|
||||||
default:
|
default:
|
||||||
throw std::logic_error ("invalid xapian options");
|
throw std::logic_error ("invalid xapian options");
|
||||||
}
|
}
|
||||||
|
@ -176,22 +183,32 @@ struct Store::Private {
|
||||||
return dynamic_cast<Xapian::WritableDatabase&>(*db_.get());
|
return dynamic_cast<Xapian::WritableDatabase&>(*db_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void dirty () try {
|
void dirty () {
|
||||||
if (++dirtiness_ > mdata_.batch_size)
|
if (++dirtiness_ > mdata_.batch_size)
|
||||||
commit();
|
xapian_try([this]{commit();});
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
}
|
||||||
|
|
||||||
void commit () try {
|
void begin_transaction() noexcept {
|
||||||
|
g_return_if_fail (!in_transaction_);
|
||||||
|
xapian_try([this]{
|
||||||
|
writable_db().begin_transaction();
|
||||||
|
in_transaction_ = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void commit () noexcept {
|
||||||
g_debug("committing %zu modification(s)", dirtiness_);
|
g_debug("committing %zu modification(s)", dirtiness_);
|
||||||
dirtiness_ = 0;
|
dirtiness_ = 0;
|
||||||
if (mdata_.in_memory)
|
if (mdata_.in_memory)
|
||||||
return; // not supported in the in-memory backend.
|
return; // not supported in the in-memory backend.
|
||||||
if (in_transaction_)
|
xapian_try([this]{
|
||||||
writable_db().commit_transaction();
|
if (in_transaction_)
|
||||||
writable_db().begin_transaction();
|
writable_db().commit_transaction();
|
||||||
in_transaction_ = true;
|
in_transaction_ = false;
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
begin_transaction();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void add_synonyms () {
|
void add_synonyms () {
|
||||||
mu_flags_foreach ((MuFlagsForeachFunc)add_synonym_for_flag,
|
mu_flags_foreach ((MuFlagsForeachFunc)add_synonym_for_flag,
|
||||||
&writable_db());
|
&writable_db());
|
||||||
|
@ -250,7 +267,7 @@ struct Store::Private {
|
||||||
return make_metadata(path);
|
return make_metadata(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Xapian::docid add_or_update_msg (Xapian::docid docid, MuMsg *msg, GError **err);
|
Xapian::docid add_or_update_msg (Xapian::docid docid, MuMsg *msg);
|
||||||
Xapian::Document new_doc_from_message (MuMsg *msg);
|
Xapian::Document new_doc_from_message (MuMsg *msg);
|
||||||
|
|
||||||
const bool read_only_{};
|
const bool read_only_{};
|
||||||
|
@ -404,11 +421,11 @@ Store::add_message (const std::string& path)
|
||||||
throw Error{Error::Code::Message, "failed to create message: %s",
|
throw Error{Error::Code::Message, "failed to create message: %s",
|
||||||
gerr ? gerr->message : "something went wrong"};
|
gerr ? gerr->message : "something went wrong"};
|
||||||
|
|
||||||
const auto docid{priv_->add_or_update_msg (0, msg, &gerr)};
|
const auto docid{priv_->add_or_update_msg (0, msg)};
|
||||||
mu_msg_unref (msg);
|
mu_msg_unref (msg);
|
||||||
if (G_UNLIKELY(docid == InvalidId))
|
|
||||||
throw Error{Error::Code::Message, "failed to add message: %s",
|
if (G_UNLIKELY(docid == InvalidId))
|
||||||
gerr ? gerr->message : "something went wrong"};
|
throw Error{Error::Code::Message, "failed to add message"};
|
||||||
|
|
||||||
g_debug ("added message @ %s; docid = %u", path.c_str(), docid);
|
g_debug ("added message @ %s; docid = %u", path.c_str(), docid);
|
||||||
priv_->dirty();
|
priv_->dirty();
|
||||||
|
@ -419,14 +436,12 @@ Store::add_message (const std::string& path)
|
||||||
bool
|
bool
|
||||||
Store::update_message (MuMsg *msg, unsigned docid)
|
Store::update_message (MuMsg *msg, unsigned docid)
|
||||||
{
|
{
|
||||||
GError *gerr{};
|
const auto docid2{priv_->add_or_update_msg (docid, msg)};
|
||||||
const auto docid2{priv_->add_or_update_msg (docid, msg, &gerr)};
|
|
||||||
|
|
||||||
if (G_UNLIKELY(docid != docid2))
|
if (G_UNLIKELY(docid != docid2))
|
||||||
throw Error{Error::Code::Internal, "failed to update message",
|
throw Error{Error::Code::Internal, "failed to update message"};
|
||||||
gerr ? gerr->message : "something went wrong"};
|
|
||||||
|
|
||||||
g_debug ("updated message @ %s; docid = %u",
|
g_debug ("updated message @ %s; docid = %u",
|
||||||
mu_msg_get_path(msg), docid);
|
mu_msg_get_path(msg), docid);
|
||||||
priv_->dirty();
|
priv_->dirty();
|
||||||
|
|
||||||
|
@ -437,33 +452,29 @@ Store::update_message (MuMsg *msg, unsigned docid)
|
||||||
bool
|
bool
|
||||||
Store::remove_message (const std::string& path)
|
Store::remove_message (const std::string& path)
|
||||||
{
|
{
|
||||||
LOCKED;
|
return xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
try {
|
|
||||||
const std::string term{(get_uid_term(path.c_str()))};
|
const std::string term{(get_uid_term(path.c_str()))};
|
||||||
priv_->writable_db().delete_document(term);
|
priv_->writable_db().delete_document(term);
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN (false);
|
g_debug ("deleted message @ %s from store", path.c_str());
|
||||||
|
priv_->dirty();
|
||||||
|
|
||||||
g_debug ("deleted message @ %s from store", path.c_str());
|
return true;
|
||||||
priv_->dirty();
|
}, false);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Store::remove_messages (const std::vector<Store::Id>& ids)
|
Store::remove_messages (const std::vector<Store::Id>& ids)
|
||||||
{
|
{
|
||||||
LOCKED;
|
xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
try {
|
|
||||||
for (auto&& id: ids) {
|
for (auto&& id: ids) {
|
||||||
priv_->writable_db().delete_document(id);
|
priv_->writable_db().delete_document(id);
|
||||||
priv_->dirty();
|
priv_->dirty();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
|
@ -494,9 +505,8 @@ Store::set_dirstamp (const std::string& path, time_t tstamp)
|
||||||
MuMsg*
|
MuMsg*
|
||||||
Store::find_message (unsigned docid) const
|
Store::find_message (unsigned docid) const
|
||||||
{
|
{
|
||||||
LOCKED;
|
return xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
try {
|
|
||||||
Xapian::Document *doc{new Xapian::Document{priv_->db().get_document (docid)}};
|
Xapian::Document *doc{new Xapian::Document{priv_->db().get_document (docid)}};
|
||||||
GError *gerr{};
|
GError *gerr{};
|
||||||
auto msg{mu_msg_new_from_doc (reinterpret_cast<XapianDocument*>(doc), &gerr)};
|
auto msg{mu_msg_new_from_doc (reinterpret_cast<XapianDocument*>(doc), &gerr)};
|
||||||
|
@ -505,48 +515,40 @@ Store::find_message (unsigned docid) const
|
||||||
"something went wrong");
|
"something went wrong");
|
||||||
g_clear_error(&gerr);
|
g_clear_error(&gerr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
|
}, (MuMsg*)nullptr);
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN (nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Store::contains_message (const std::string& path) const
|
Store::contains_message (const std::string& path) const
|
||||||
{
|
{
|
||||||
LOCKED;
|
return xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
try {
|
|
||||||
const std::string term (get_uid_term(path.c_str()));
|
const std::string term (get_uid_term(path.c_str()));
|
||||||
return priv_->db().term_exists (term);
|
return priv_->db().term_exists (term);
|
||||||
|
}, false);
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
Store::for_each_message_path (Store::ForEachMessageFunc func) const
|
Store::for_each_message_path (Store::ForEachMessageFunc msg_func) const
|
||||||
{
|
{
|
||||||
LOCKED;
|
size_t n{};
|
||||||
|
|
||||||
size_t n{};
|
xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
try {
|
Xapian::Enquire enq{priv_->db()};
|
||||||
Xapian::Enquire enq{priv_->db()};
|
|
||||||
|
|
||||||
enq.set_query (Xapian::Query::MatchAll);
|
enq.set_query (Xapian::Query::MatchAll);
|
||||||
enq.set_cutoff (0,0);
|
enq.set_cutoff (0,0);
|
||||||
|
|
||||||
Xapian::MSet matches(enq.get_mset (0, priv_->db().get_doccount()));
|
Xapian::MSet matches(enq.get_mset (0, priv_->db().get_doccount()));
|
||||||
|
|
||||||
for (auto&& it = matches.begin(); it != matches.end(); ++it, ++n)
|
for (auto&& it = matches.begin(); it != matches.end(); ++it, ++n)
|
||||||
if (!func (*it, it.get_document().get_value(MU_MSG_FIELD_ID_PATH)))
|
if (!msg_func (*it, it.get_document().get_value(MU_MSG_FIELD_ID_PATH)))
|
||||||
break;
|
break;
|
||||||
|
});
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
return n;
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MuMsgFieldId
|
static MuMsgFieldId
|
||||||
|
@ -570,36 +572,31 @@ field_id (const std::string& field)
|
||||||
std::size_t
|
std::size_t
|
||||||
Store::for_each_term (const std::string& field, Store::ForEachTermFunc func) const
|
Store::for_each_term (const std::string& field, Store::ForEachTermFunc func) const
|
||||||
{
|
{
|
||||||
LOCKED;
|
|
||||||
|
|
||||||
size_t n{};
|
size_t n{};
|
||||||
|
|
||||||
try {
|
xapian_try([&]{
|
||||||
|
LOCKED;
|
||||||
const auto id = field_id (field.c_str());
|
const auto id = field_id (field.c_str());
|
||||||
if (id == MU_MSG_FIELD_ID_NONE)
|
if (id == MU_MSG_FIELD_ID_NONE)
|
||||||
return {};
|
return;
|
||||||
|
|
||||||
char pfx[] = { mu_msg_field_xapian_prefix(id), '\0' };
|
char pfx[] = { mu_msg_field_xapian_prefix(id), '\0' };
|
||||||
|
|
||||||
std::vector<std::string> terms;
|
std::vector<std::string> terms;
|
||||||
for (auto it = priv_->db().allterms_begin(pfx);
|
for (auto it = priv_->db().allterms_begin(pfx);
|
||||||
it != priv_->db().allterms_end(pfx); ++it) {
|
it != priv_->db().allterms_end(pfx); ++it) {
|
||||||
if (!func(*it))
|
if (!func(*it))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Store::commit () try
|
Store::commit ()
|
||||||
{
|
{
|
||||||
LOCKED;
|
xapian_try([&]{ LOCKED; priv_->commit(); });
|
||||||
priv_->commit();
|
}
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_terms_values_date (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid)
|
add_terms_values_date (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid)
|
||||||
|
@ -1059,11 +1056,11 @@ update_threading_info (MuMsg *msg, Xapian::Document& doc)
|
||||||
|
|
||||||
|
|
||||||
Xapian::docid
|
Xapian::docid
|
||||||
Store::Private::add_or_update_msg (unsigned docid, MuMsg *msg, GError **err)
|
Store::Private::add_or_update_msg (unsigned docid, MuMsg *msg)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (msg, InvalidId);
|
g_return_val_if_fail (msg, InvalidId);
|
||||||
|
|
||||||
try {
|
return xapian_try([&]{
|
||||||
Xapian::Document doc (new_doc_from_message(msg));
|
Xapian::Document doc (new_doc_from_message(msg));
|
||||||
const std::string term (get_uid_term (mu_msg_get_path(msg)));
|
const std::string term (get_uid_term (mu_msg_get_path(msg)));
|
||||||
|
|
||||||
|
@ -1080,7 +1077,5 @@ Store::Private::add_or_update_msg (unsigned docid, MuMsg *msg, GError **err)
|
||||||
writable_db().replace_document (docid, doc);
|
writable_db().replace_document (docid, doc);
|
||||||
return docid;
|
return docid;
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK_G_ERROR (err, MU_ERROR_XAPIAN_STORE_FAILED);
|
}, InvalidId);
|
||||||
|
|
||||||
return InvalidId;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <xapian.h>
|
||||||
|
|
||||||
namespace Mu {
|
namespace Mu {
|
||||||
|
|
||||||
|
@ -64,8 +66,6 @@ std::string utf8_clean (const std::string& dirty);
|
||||||
std::string remove_ctrl (const std::string& str);
|
std::string remove_ctrl (const std::string& str);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split a string in parts
|
* Split a string in parts
|
||||||
*
|
*
|
||||||
|
@ -245,78 +245,31 @@ private:
|
||||||
const bool color_;
|
const bool color_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
template <typename Func> void xapian_try(Func&& func) noexcept try {
|
||||||
*
|
func();
|
||||||
* don't repeat these catch blocks everywhere...
|
} catch (const Xapian::Error &xerr) {
|
||||||
*
|
g_critical ("%s: xapian error '%s'",
|
||||||
*/
|
__func__, xerr.get_msg().c_str());
|
||||||
|
} catch (const std::runtime_error& re) {
|
||||||
#define MU_XAPIAN_CATCH_BLOCK \
|
g_critical ("%s: error: %s", __func__, re.what());
|
||||||
catch (const Xapian::Error &xerr) { \
|
} catch (...) {
|
||||||
g_critical ("%s: xapian error '%s'", \
|
g_critical ("%s: caught exception", __func__);
|
||||||
__func__, xerr.get_msg().c_str()); \
|
}
|
||||||
} catch (const std::runtime_error& re) { \
|
|
||||||
g_critical ("%s: error: %s", __func__, re.what()); \
|
|
||||||
} catch (...) { \
|
|
||||||
g_critical ("%s: caught exception", __func__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MU_XAPIAN_CATCH_BLOCK_G_ERROR(GE,E) \
|
|
||||||
catch (const Xapian::DatabaseLockError &xerr) { \
|
|
||||||
mu_util_g_set_error ((GE), \
|
|
||||||
MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, \
|
|
||||||
"%s: xapian error '%s'", \
|
|
||||||
__func__, xerr.get_msg().c_str()); \
|
|
||||||
} catch (const Xapian::DatabaseError &xerr) { \
|
|
||||||
mu_util_g_set_error ((GE),MU_ERROR_XAPIAN, \
|
|
||||||
"%s: xapian error '%s'", \
|
|
||||||
__func__, xerr.get_msg().c_str()); \
|
|
||||||
} catch (const Xapian::Error &xerr) { \
|
|
||||||
mu_util_g_set_error ((GE),(E), \
|
|
||||||
"%s: xapian error '%s'", \
|
|
||||||
__func__, xerr.get_msg().c_str()); \
|
|
||||||
} catch (const std::runtime_error& ex) { \
|
|
||||||
mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \
|
|
||||||
"%s: error: %s", __func__, ex.what()); \
|
|
||||||
\
|
|
||||||
} catch (...) { \
|
|
||||||
mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \
|
|
||||||
"%s: caught exception", __func__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define MU_XAPIAN_CATCH_BLOCK_RETURN(R) \
|
|
||||||
catch (const Xapian::Error &xerr) { \
|
|
||||||
g_critical ("%s: xapian error '%s'", \
|
|
||||||
__func__, xerr.get_msg().c_str()); \
|
|
||||||
return (R); \
|
|
||||||
} catch (const std::runtime_error& ex) { \
|
|
||||||
g_critical("%s: error: %s", __func__, ex.what()); \
|
|
||||||
return (R); \
|
|
||||||
} catch (...) { \
|
|
||||||
g_critical ("%s: caught exception", __func__); \
|
|
||||||
return (R); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(GE,E,R) \
|
|
||||||
catch (const Xapian::Error &xerr) { \
|
|
||||||
mu_util_g_set_error ((GE),(E), \
|
|
||||||
"%s: xapian error '%s'", \
|
|
||||||
__func__, xerr.get_msg().c_str()); \
|
|
||||||
return (R); \
|
|
||||||
} catch (const std::runtime_error& ex) { \
|
|
||||||
mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \
|
|
||||||
"%s: error: %s", __func__, ex.what()); \
|
|
||||||
return (R); \
|
|
||||||
} catch (...) { \
|
|
||||||
if ((GE)&&!(*(GE))) \
|
|
||||||
mu_util_g_set_error ((GE), \
|
|
||||||
(MU_ERROR_INTERNAL), \
|
|
||||||
"%s: caught exception", __func__); \
|
|
||||||
return (R); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Func, typename Default=std::invoke_result<Func>>
|
||||||
|
auto xapian_try(Func&& func, Default&& def) noexcept -> std::decay_t<decltype(func())> try {
|
||||||
|
return func();
|
||||||
|
} catch (const Xapian::Error &xerr) {
|
||||||
|
g_critical ("%s: xapian error '%s'",
|
||||||
|
__func__, xerr.get_msg().c_str());
|
||||||
|
return static_cast<Default>(def);
|
||||||
|
} catch (const std::runtime_error& re) {
|
||||||
|
g_critical ("%s: error: %s", __func__, re.what());
|
||||||
|
return static_cast<Default>(def);
|
||||||
|
} catch (...) {
|
||||||
|
g_critical ("%s: caught exception", __func__);
|
||||||
|
return static_cast<Default>(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Allow using enum structs as bitflags
|
/// Allow using enum structs as bitflags
|
||||||
|
|
Loading…
Reference in New Issue