cmd-server: Update to use the new Indexer

This commit is contained in:
Dirk-Jan C. Binnema
2020-06-27 11:50:57 +03:00
parent f9415caab7
commit ba13a62e90

View File

@ -24,6 +24,9 @@
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <thread>
#include <mutex>
#include <cstring> #include <cstring>
#include <glib.h> #include <glib.h>
#include <glib/gprintf.h> #include <glib/gprintf.h>
@ -33,7 +36,7 @@
#include "mu-cmd.hh" #include "mu-cmd.hh"
#include "mu-maildir.h" #include "mu-maildir.h"
#include "mu-query.h" #include "mu-query.h"
#include "mu-index.h" #include "index/mu-indexer.hh"
#include "mu-store.hh" #include "mu-store.hh"
#include "mu-msg-part.h" #include "mu-msg-part.h"
#include "mu-contacts.hh" #include "mu-contacts.hh"
@ -49,14 +52,9 @@ using namespace Sexp;
using DocId = unsigned; using DocId = unsigned;
static std::mutex OutputLock;
static std::atomic<bool> MuTerminate{false}; static std::atomic<bool> MuTerminate{false};
static void
sig_handler (int sig)
{
MuTerminate = true;
}
static void static void
install_sig_handler (void) install_sig_handler (void)
{ {
@ -65,7 +63,7 @@ install_sig_handler (void)
MuTerminate = false; MuTerminate = false;
action.sa_handler = sig_handler; action.sa_handler = [](int sig){ MuTerminate = true; };
sigemptyset(&action.sa_mask); sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESETHAND; action.sa_flags = SA_RESETHAND;
@ -86,6 +84,8 @@ install_sig_handler (void)
static void G_GNUC_PRINTF(1, 2) static void G_GNUC_PRINTF(1, 2)
print_expr (const char* frm, ...) print_expr (const char* frm, ...)
{ {
std::lock_guard<std::mutex> l {OutputLock};
char *expr, *expr_orig; char *expr, *expr_orig;
va_list ap; va_list ap;
ssize_t rv; ssize_t rv;
@ -208,6 +208,7 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
} }
/// @brief object to manage the server-context for all commands.
struct Context { struct Context {
Context(){} Context(){}
Context (const MuConfig *opts): Context (const MuConfig *opts):
@ -219,8 +220,8 @@ struct Context {
throw Error(Error::Code::Store, &gerr/*consumes*/, "failed to create query"); throw Error(Error::Code::Store, &gerr/*consumes*/, "failed to create query");
g_message ("opened store @ %s; maildir @ %s; debug-mode %s", g_message ("opened store @ %s; maildir @ %s; debug-mode %s",
store_->database_path().c_str(), store_->metadata().database_path.c_str(),
store_->root_maildir().c_str(), store_->metadata().root_maildir.c_str(),
opts->debug ? "yes" : "no"); opts->debug ? "yes" : "no");
} }
@ -236,9 +237,10 @@ struct Context {
throw Mu::Error (Error::Code::Internal, "no store"); throw Mu::Error (Error::Code::Internal, "no store");
return *store_.get(); return *store_.get();
} }
Indexer& indexer() { return store().indexer(); }
std::unique_ptr<Mu::Store> store_;
std::unique_ptr<Mu::Store> store_;
MuQuery *query{}; MuQuery *query{};
bool do_quit{}; bool do_quit{};
@ -343,7 +345,6 @@ compose_handler (Context& context, const Parameters& params)
Node::Seq compose_seq; Node::Seq compose_seq;
compose_seq.add_prop(":compose", Node::make_symbol(std::string(ctype))); compose_seq.add_prop(":compose", Node::make_symbol(std::string(ctype)));
// message optioss below checks extract-images / extract-encrypted
if (ctype == "reply" || ctype == "forward" || ctype == "edit" || ctype == "resend") { if (ctype == "reply" || ctype == "forward" || ctype == "edit" || ctype == "resend") {
GError *gerr{}; GError *gerr{};
@ -410,7 +411,6 @@ contacts_handler (Context& context, const Parameters& params)
seq.add_prop(":contacts", std::move(contacts)); seq.add_prop(":contacts", std::move(contacts));
seq.add_prop(":tstamp", Node::make_string(format("%" G_GINT64_FORMAT, seq.add_prop(":tstamp", Node::make_string(format("%" G_GINT64_FORMAT,
g_get_monotonic_time()))); g_get_monotonic_time())));
/* dump the contacts cache as a giant sexp */ /* dump the contacts cache as a giant sexp */
print_expr(std::move(seq)); print_expr(std::move(seq));
} }
@ -708,79 +708,35 @@ help_handler (Context& context, const Parameters& params)
} }
} }
static MuError static void
index_msg_cb (MuIndexStats *stats, void *user_data) print_stats (const Indexer::Progress& stats, const std::string& state)
{ {
if (MuTerminate)
return MU_STOP;
if (stats->_processed % 1000)
return MU_OK;
Node::Seq seq; Node::Seq seq;
seq.add_prop(":info", Node::make_symbol("index")); seq.add_prop(":info", Node::make_symbol("index"));
seq.add_prop(":status", Node::make_symbol("running")); seq.add_prop(":status", Node::make_symbol(std::string{state}));
seq.add_prop(":processed", stats->_processed); seq.add_prop(":processed", stats.processed);
seq.add_prop(":updated", stats->_updated); seq.add_prop(":updated", stats.updated);
seq.add_prop(":cleaned-up", stats.removed);
print_expr(std::move(seq)); print_expr(std::move(seq));
return MU_OK;
} }
static MuError
index_and_maybe_cleanup (MuIndex *index, bool cleanup, bool lazy_check)
{
MuIndexStats stats{}, stats2{};
mu_index_stats_clear (&stats);
auto rv = mu_index_run (index, FALSE, lazy_check, &stats,
index_msg_cb, NULL, NULL);
if (rv != MU_OK && rv != MU_STOP)
throw Error{Error::Code::Store, "indexing failed"};
mu_index_stats_clear (&stats2);
if (cleanup) {
GError *gerr{};
rv = mu_index_cleanup (index, &stats2, NULL, NULL, &gerr);
if (rv != MU_OK && rv != MU_STOP)
throw Error{Error::Code::Store, &gerr, "cleanup failed"};
}
Node::Seq seq;
seq.add_prop(":info", Node::make_symbol("index"));
seq.add_prop(":status", Node::make_symbol("complete"));
seq.add_prop(":processed", stats._processed);
seq.add_prop(":updated", stats._updated);
seq.add_prop(":cleaned-up", stats2._cleaned_up);
print_expr(std::move(seq));
return MU_OK;
}
static void static void
index_handler (Context& context, const Parameters& params) index_handler (Context& context, const Parameters& params)
{ {
GError *gerr{}; Mu::Indexer::Config conf{};
const auto cleanup{get_bool_or(params, ":cleanup")}; conf.cleanup = get_bool_or(params, ":cleanup");
const auto lazy_check{get_bool_or(params, ":lazy-check")}; conf.lazy_check = get_bool_or(params, ":lazy-check");
auto store_ptr = reinterpret_cast<MuStore*>(&context.store()); context.indexer().stop();
auto index{mu_index_new (store_ptr, &gerr)}; context.indexer().start(conf);
if (!index) while (context.indexer().is_running()) {
throw Error(Error::Code::Index, &gerr, "failed to create index object"); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
print_stats (context.indexer().progress(), "running");
try {
index_and_maybe_cleanup (index, cleanup, lazy_check);
} catch (...) {
mu_index_destroy(index);
throw;
} }
mu_index_destroy(index); print_stats (context.indexer().progress(), "complete");
mu_store_flush(store_ptr);
} }
static void static void
@ -953,6 +909,7 @@ ping_handler (Context& context, const Parameters& params)
const auto queries = get_string_vec (params, ":queries"); const auto queries = get_string_vec (params, ":queries");
Node::Seq qresults; Node::Seq qresults;
for (auto&& q: queries) { for (auto&& q: queries) {
const auto count{mu_query_count_run (context.query, q.c_str())}; const auto count{mu_query_count_run (context.query, q.c_str())};
const auto unreadq{format("flag:unread AND (%s)", q.c_str())}; const auto unreadq{format("flag:unread AND (%s)", q.c_str())};
const auto unread{mu_query_count_run (context.query, unreadq.c_str())}; const auto unread{mu_query_count_run (context.query, unreadq.c_str())};
@ -966,7 +923,7 @@ ping_handler (Context& context, const Parameters& params)
} }
Node::Seq addrs; Node::Seq addrs;
for (auto&& addr: context.store().personal_addresses()) for (auto&& addr: context.store().metadata().personal_addresses)
addrs.add(std::string(addr)); addrs.add(std::string(addr));
Node::Seq seq; Node::Seq seq;
@ -975,8 +932,8 @@ ping_handler (Context& context, const Parameters& params)
Node::Seq propseq; Node::Seq propseq;
propseq.add_prop(":version", VERSION); propseq.add_prop(":version", VERSION);
propseq.add_prop(":personal-addresses", std::move(addrs)); propseq.add_prop(":personal-addresses", std::move(addrs));
propseq.add_prop(":database-path", context.store().database_path()); propseq.add_prop(":database-path", context.store().metadata().database_path);
propseq.add_prop(":root-maildir", context.store().root_maildir()); propseq.add_prop(":root-maildir", context.store().metadata().root_maildir);
propseq.add_prop(":doccount", storecount); propseq.add_prop(":doccount", storecount);
propseq.add_prop(":queries", std::move(qresults)); propseq.add_prop(":queries", std::move(qresults));
seq.add_prop(":props", std::move(propseq)); seq.add_prop(":props", std::move(propseq));