lib: replace CATCH_BLOCK macros with template magic

This commit is contained in:
Dirk-Jan C. Binnema 2021-10-18 12:22:26 +03:00
parent 7156ff7fac
commit 49637dbc3a
6 changed files with 172 additions and 223 deletions

View File

@ -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);
} }

View File

@ -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 {

View File

@ -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_;

View File

@ -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); }

View File

@ -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;
} }

View File

@ -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