From 9967751b1d2b574c5bd39f48d24ed43ae3478d2f Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 23 Jan 2010 23:34:27 +0200 Subject: [PATCH] * rename MuMsgXapian => MuMsgIterXapian --- src/Makefile.am | 63 ++--- src/mu-cmd.c | 40 +-- ...ian-priv.hh => mu-msg-iter-xapian-priv.hh} | 15 +- src/mu-msg-iter-xapian.cc | 263 ++++++++++++++++++ src/{mu-msg-xapian.h => mu-msg-iter-xapian.h} | 76 ++--- src/mu-msg-xapian.cc | 262 ----------------- src/mu-query-xapian.cc | 8 +- src/mu-query-xapian.h | 13 +- 8 files changed, 377 insertions(+), 363 deletions(-) rename src/{mu-msg-xapian-priv.hh => mu-msg-iter-xapian-priv.hh} (64%) create mode 100644 src/mu-msg-iter-xapian.cc rename src/{mu-msg-xapian.h => mu-msg-iter-xapian.h} (58%) delete mode 100644 src/mu-msg-xapian.cc diff --git a/src/Makefile.am b/src/Makefile.am index d608a1ff..7e0aa225 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,37 +19,38 @@ INCLUDES=$(XAPIAN_CXXFLAGS) $(GMIME_CFLAGS) $(GLIB_CFLAGS) bin_PROGRAMS= \ mu -mu_SOURCES= \ - mu-cmd.h \ - mu-cmd.c \ - mu-config.h \ - mu-config.c \ - mu-index.c \ - mu-index.h \ - mu-log.c \ - mu-log.h \ - mu-maildir.c \ - mu-maildir.h \ - mu-msg-fields.c \ - mu-msg-fields.h \ - mu-msg-flags.c \ - mu-msg-flags.h \ - mu-msg-gmime.c \ - mu-msg-gmime.h \ - mu-msg-str.c \ - mu-msg-str.h \ - mu-msg-xapian.cc \ - mu-msg-xapian.h \ - mu-msg.h \ - mu-query-xapian.cc \ - mu-query-xapian.h \ - mu-result.h \ - mu-store-xapian.cc \ - mu-store-xapian.h \ - mu-util.h \ - mu-util.c \ - mu-util-xapian.cc \ - mu-util-xapian.h \ +mu_SOURCES= \ + mu-cmd.c \ + mu-cmd.h \ + mu-config.c \ + mu-config.h \ + mu-index.c \ + mu-index.h \ + mu-log.c \ + mu-log.h \ + mu-maildir.c \ + mu-maildir.h \ + mu-msg-fields.c \ + mu-msg-fields.h \ + mu-msg-flags.c \ + mu-msg-flags.h \ + mu-msg-gmime.c \ + mu-msg-gmime.h \ + mu-msg-iter-xapian-priv.hh \ + mu-msg-iter-xapian.cc \ + mu-msg-iter-xapian.h \ + mu-msg-str.c \ + mu-msg-str.h \ + mu-msg.h \ + mu-query-xapian.cc \ + mu-query-xapian.h \ + mu-result.h \ + mu-store-xapian.cc \ + mu-store-xapian.h \ + mu-util-xapian.cc \ + mu-util-xapian.h \ + mu-util.c \ + mu-util.h \ mu.c mu_LDADD= \ diff --git a/src/mu-cmd.c b/src/mu-cmd.c index fa19cdd3..ad24a9f7 100644 --- a/src/mu-cmd.c +++ b/src/mu-cmd.c @@ -28,7 +28,7 @@ #include "mu-maildir.h" #include "mu-index.h" #include "mu-query-xapian.h" -#include "mu-msg-xapian.h" +#include "mu-msg-iter-xapian.h" #include "mu-msg-str.h" #include "mu-cmd.h" #include "mu-util.h" @@ -87,34 +87,34 @@ print_query (MuQueryXapian *xapian, const gchar *query) static const gchar* -display_field (MuMsgXapian *row, const MuMsgField* field) +display_field (MuMsgIterXapian *row, const MuMsgField* field) { gint64 val; switch (mu_msg_field_type(field)) { case MU_MSG_FIELD_TYPE_STRING: - return mu_msg_xapian_get_field (row, field); + return mu_msg_iter_xapian_get_field (row, field); case MU_MSG_FIELD_TYPE_INT: if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_PRIORITY) { - val = mu_msg_xapian_get_field_numeric (row, field); + val = mu_msg_iter_xapian_get_field_numeric (row, field); return mu_msg_str_prio ((MuMsgPriority)val); } if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_FLAGS) { - val = mu_msg_xapian_get_field_numeric (row, field); + val = mu_msg_iter_xapian_get_field_numeric (row, field); return mu_msg_str_flags_s ((MuMsgPriority)val); } - return mu_msg_xapian_get_field (row, field); /* as string */ + return mu_msg_iter_xapian_get_field (row, field); /* as string */ case MU_MSG_FIELD_TYPE_TIME_T: - val = mu_msg_xapian_get_field_numeric (row, field); + val = mu_msg_iter_xapian_get_field_numeric (row, field); return mu_msg_str_date_s ((time_t)val); case MU_MSG_FIELD_TYPE_BYTESIZE: - val = mu_msg_xapian_get_field_numeric (row, field); + val = mu_msg_iter_xapian_get_field_numeric (row, field); return mu_msg_str_size_s ((time_t)val); default: g_return_val_if_reached (NULL); @@ -142,7 +142,7 @@ sort_field_from_string (const char* fieldstr) static gboolean print_rows (MuQueryXapian *xapian, const gchar *query, MuConfigOptions *opts) { - MuMsgXapian *row; + MuMsgIterXapian *row; const MuMsgField *sortfield; MU_WRITE_LOG ("query: '%s' (rows)", query); @@ -159,9 +159,9 @@ print_rows (MuQueryXapian *xapian, const gchar *query, MuConfigOptions *opts) if (!row) { g_printerr ("error: running query failed\n"); return FALSE; - } else if (mu_msg_xapian_is_done (row)) { + } else if (mu_msg_iter_xapian_is_done (row)) { g_printerr ("No matches found\n"); - mu_msg_xapian_destroy (row); + mu_msg_iter_xapian_destroy (row); return FALSE; } @@ -187,11 +187,11 @@ print_rows (MuQueryXapian *xapian, const gchar *query, MuConfigOptions *opts) if (printlen > 0) printf ("\n"); - mu_msg_xapian_next (row); + mu_msg_iter_xapian_next (row); - } while (!mu_msg_xapian_is_done (row)); + } while (!mu_msg_iter_xapian_is_done (row)); - mu_msg_xapian_destroy (row); + mu_msg_iter_xapian_destroy (row); return TRUE; } @@ -240,7 +240,7 @@ do_output_links (MuQueryXapian *xapian, MuConfigOptions* opts, { gchar *query; gboolean retval = TRUE; - MuMsgXapian *row; + MuMsgIterXapian *row; const MuMsgField *pathfield; if (!create_or_clear_linksdir_maybe (opts)) @@ -253,20 +253,20 @@ do_output_links (MuQueryXapian *xapian, MuConfigOptions* opts, if (!row) { g_printerr ("error: running query failed\n"); return FALSE; - } else if (mu_msg_xapian_is_done (row)) { + } else if (mu_msg_iter_xapian_is_done (row)) { g_printerr ("No matches found\n"); - mu_msg_xapian_destroy (row); + mu_msg_iter_xapian_destroy (row); return FALSE; } pathfield = mu_msg_field_from_id (MU_MSG_FIELD_ID_PATH); /* iterate over the found rows */ - for (; !mu_msg_xapian_is_done (row); mu_msg_xapian_next (row)) { + for (; !mu_msg_iter_xapian_is_done (row); mu_msg_iter_xapian_next (row)) { const char *path; - path = mu_msg_xapian_get_field (row, pathfield); + path = mu_msg_iter_xapian_get_field (row, pathfield); if (!path) continue; @@ -281,7 +281,7 @@ do_output_links (MuQueryXapian *xapian, MuConfigOptions* opts, break; } - mu_msg_xapian_destroy (row); + mu_msg_iter_xapian_destroy (row); g_free (query); return retval; diff --git a/src/mu-msg-xapian-priv.hh b/src/mu-msg-iter-xapian-priv.hh similarity index 64% rename from src/mu-msg-xapian-priv.hh rename to src/mu-msg-iter-xapian-priv.hh index 67306c58..7245dd55 100644 --- a/src/mu-msg-xapian-priv.hh +++ b/src/mu-msg-iter-xapian-priv.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2008 Dirk-Jan C. Binnema +** Copyright (C) 2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -22,6 +22,17 @@ #include -MuMsgXapian *mu_msg_xapian_new (const Xapian::Enquire& enq, size_t batchsize); + +/** + * create a new MuMsgIterXapian -- basically, an iterator over the search + * results + * + * @param enq a Xapian::Enquiry providing access to search results + * @param batchsize how many results to retrieve at once + * + * @return a new MuMsgIterXapian, or NULL in case of error + */ +MuMsgIterXapian *mu_msg_iter_xapian_new + (const Xapian::Enquire& enq, size_t batchsize)G_GNUC_WARN_UNUSED_RESULT; #endif /*__MU_MSG_XAPIAN_PRIV_HH__*/ diff --git a/src/mu-msg-iter-xapian.cc b/src/mu-msg-iter-xapian.cc new file mode 100644 index 00000000..ae94cf43 --- /dev/null +++ b/src/mu-msg-iter-xapian.cc @@ -0,0 +1,263 @@ +/* +** Copyright (C) 2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include +#include +#include + +#include "xapian.h" + +#include "mu-util.h" +#include "mu-msg-iter-xapian.h" + +struct _MuMsgIterXapian { + Xapian::Enquire *_enq; + Xapian::MSet _matches; + Xapian::MSet::const_iterator _cursor; + size_t _batchsize; + size_t _offset; + char* _str[MU_MSG_FIELD_ID_NUM]; +}; + + +/* FIXME: maybe use get_doccount() on the database object instead + * of specifying the batch size? */ +MuMsgIterXapian * +mu_msg_iter_xapian_new (const Xapian::Enquire& enq, size_t batchsize) +{ + MuMsgIterXapian *iter; + + try { + iter = new MuMsgIterXapian; + memset (iter->_str, 0, sizeof(iter->_str)); + + iter->_enq = new Xapian::Enquire(enq); + iter->_matches = iter->_enq->get_mset (0, batchsize); + if (!iter->_matches.empty()) + iter->_cursor = iter->_matches.begin(); + + iter->_batchsize = batchsize; + iter->_offset = 0; + + return iter; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} + +void +mu_msg_iter_xapian_destroy (MuMsgIterXapian *iter) +{ + if (iter) { + for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) + g_free (iter->_str[i]); + + try { + delete iter->_enq; + delete iter; + + } MU_XAPIAN_CATCH_BLOCK; + } +} + +static gboolean +message_is_readable (MuMsgIterXapian *iter) +{ + Xapian::Document doc (iter->_cursor.get_document()); + const std::string path(doc.get_value(MU_MSG_FIELD_ID_PATH)); + + if (access (path.c_str(), R_OK) != 0) { + g_debug ("cannot read %s: %s", path.c_str(), + strerror(errno)); + return FALSE; + } + + return TRUE; +} + + + +gboolean +mu_msg_iter_xapian_next (MuMsgIterXapian *iter) +{ + g_return_val_if_fail (iter, FALSE); + g_return_val_if_fail (!mu_msg_iter_xapian_is_done(iter), FALSE); + + try { + if (++iter->_cursor == iter->_matches.end()) + return FALSE; /* no more matches */ + + /* the message may not be readable / existing, e.g., because + * of the database not being fully up to date. in that case, + * we ignore the message. it might be nice to auto-delete + * these messages from the db, but that would might screw + * up the search; also, we only have read-only access to the + * db here */ + if (!message_is_readable (iter)) + return mu_msg_iter_xapian_next (iter); + + for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) { + g_free (iter->_str[i]); + iter->_str[i] = NULL; + } + + return TRUE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); +} + + +gboolean +mu_msg_iter_xapian_is_done (MuMsgIterXapian *iter) +{ + g_return_val_if_fail (iter, TRUE); + + if (iter->_matches.empty()) + return TRUE; + + if (iter->_cursor == iter->_matches.end()) + return TRUE; + + return FALSE; +} + + +const gchar* +mu_msg_iter_xapian_get_field (MuMsgIterXapian *iter, const MuMsgField *field) +{ + g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (!mu_msg_iter_xapian_is_done(iter), NULL); + g_return_val_if_fail (field, NULL); + + try { + MuMsgFieldId id; + + id = mu_msg_field_id (field); + if (!iter->_str[id]) { /* cache the value */ + Xapian::Document doc (iter->_cursor.get_document()); + iter->_str[id] = g_strdup (doc.get_value(id).c_str()); + } + + return iter->_str[id]; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} + + +gint64 +mu_msg_iter_xapian_get_field_numeric (MuMsgIterXapian *iter, + const MuMsgField *field) +{ + g_return_val_if_fail (mu_msg_field_is_numeric(field), -1); + + try { + return Xapian::sortable_unserialise( + mu_msg_iter_xapian_get_field(iter, field)); + } MU_XAPIAN_CATCH_BLOCK_RETURN(-1); +} + + + +static const gchar* +get_field (MuMsgIterXapian *iter, MuMsgFieldId id) +{ + return mu_msg_iter_xapian_get_field(iter, mu_msg_field_from_id (id)); +} + +static long +get_field_number (MuMsgIterXapian *iter, MuMsgFieldId id) +{ + const char* str = get_field (iter, id); + return str ? atol (str) : 0; +} + + + +/* hmmm.... is it impossible to get a 0 docid, or just very improbable? */ +unsigned int +mu_msg_iter_xapian_get_docid (MuMsgIterXapian *iter) +{ + g_return_val_if_fail (iter, 0); + + try { + return iter->_cursor.get_document().get_docid(); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (0); +} + + +const char* +mu_msg_iter_xapian_get_path (MuMsgIterXapian *iter) +{ + return get_field (iter, MU_MSG_FIELD_ID_PATH); +} + + +const char* +mu_msg_iter_xapian_get_from (MuMsgIterXapian *iter) +{ + return get_field (iter, MU_MSG_FIELD_ID_FROM); +} + +const char* +mu_msg_iter_xapian_get_to (MuMsgIterXapian *iter) +{ + return get_field (iter, MU_MSG_FIELD_ID_TO); +} + + +const char* +mu_msg_iter_xapian_get_cc (MuMsgIterXapian *iter) +{ + return get_field (iter, MU_MSG_FIELD_ID_CC); +} + + +const char* +mu_msg_iter_xapian_get_subject (MuMsgIterXapian *iter) +{ + return get_field (iter, MU_MSG_FIELD_ID_SUBJECT); +} + + +size_t +mu_msg_iter_xapian_get_size (MuMsgIterXapian *iter) +{ + return (size_t) get_field_number (iter, MU_MSG_FIELD_ID_SIZE); +} + + +time_t +mu_msg_iter_xapian_get_date (MuMsgIterXapian *iter) +{ + return (size_t) get_field_number (iter, MU_MSG_FIELD_ID_DATE); +} + + +MuMsgFlags +mu_msg_iter_xapian_get_flags (MuMsgIterXapian *iter) +{ + return (MuMsgFlags) get_field_number (iter, MU_MSG_FIELD_ID_FLAGS); +} + +MuMsgPriority +mu_msg_iter_xapian_get_priority (MuMsgIterXapian *iter) +{ + return (MuMsgPriority) get_field_number (iter, MU_MSG_FIELD_ID_PRIORITY); +} diff --git a/src/mu-msg-xapian.h b/src/mu-msg-iter-xapian.h similarity index 58% rename from src/mu-msg-xapian.h rename to src/mu-msg-iter-xapian.h index 8b6b6f6b..c83e3bb9 100644 --- a/src/mu-msg-xapian.h +++ b/src/mu-msg-iter-xapian.h @@ -17,169 +17,169 @@ ** */ -#ifndef __MU_MSG_XAPIAN_H__ -#define __MU_MSG_XAPIAN_H__ +#ifndef __MU_MSG_ITER_XAPIAN_H__ +#define __MU_MSG_ITER_XAPIAN_H__ #include "mu-msg.h" G_BEGIN_DECLS -struct _MuMsgXapian; -typedef struct _MuMsgXapian MuMsgXapian; +struct _MuMsgIterXapian; +typedef struct _MuMsgIterXapian MuMsgIterXapian; /** * get the next next message (which you got from * e.g. mu_query_xapian_run) * - * @param msg a valid MuMsgXapian message + * @param msg a valid MuMsgIterXapian message * * @return TRUE if it succeeded, FALSE otherwise (e.g., because there * are no more messages in the query result) */ -gboolean mu_msg_xapian_next (MuMsgXapian *msg); +gboolean mu_msg_iter_xapian_next (MuMsgIterXapian *iter); /** - * are there any message left? together with mu_msg_xapian_next, this + * are there any message left? together with mu_msg_iter_xapian_next, this * function can be used to iterate over query results. * - * @param msg a valid MuMsgXapian message + * @param msg a valid MuMsgIterXapian message * * @return TRUE if there are messages left, FALSE otherwise */ -gboolean mu_msg_xapian_is_done (MuMsgXapian *msg); +gboolean mu_msg_iter_xapian_is_done (MuMsgIterXapian *iter); /** * destroy the sequence of messages * - * @param msg a valid MuMsgXapian message or NULL + * @param msg a valid MuMsgIterXapian message or NULL */ -void mu_msg_xapian_destroy (MuMsgXapian *msg); +void mu_msg_iter_xapian_destroy (MuMsgIterXapian *iter); /** * get the document id for the current message * - * @param row a message + * @param iter a message * * @return the docid or 0 in case of error */ -unsigned int mu_msg_xapian_get_docid (MuMsgXapian *row); +unsigned int mu_msg_iter_xapian_get_docid (MuMsgIterXapian *iter); /** * get the directory path of the message * - * @param row a message + * @param iter a message * * @return the path, or NULL in case of error */ -const char* mu_msg_xapian_get_path (MuMsgXapian *row); +const char* mu_msg_iter_xapian_get_path (MuMsgIterXapian *iter); /** * get the size of the message * - * @param row a message + * @param iter a message * * @return the size, or 0 in case of error */ -size_t mu_msg_xapian_get_size (MuMsgXapian *row); +size_t mu_msg_iter_xapian_get_size (MuMsgIterXapian *iter); /** * get the timestamp (ctime) of the message file * - * @param row a message + * @param iter a message * * @return the size, or 0 in case of error */ -time_t mu_msg_xapian_get_timestamp (MuMsgXapian *row); +time_t mu_msg_iter_xapian_get_timestamp (MuMsgIterXapian *iter); /** * get the sent time of the message * - * @param row a message + * @param iter a message * * @return the time, or 0 in case of error */ -time_t mu_msg_xapian_get_date (MuMsgXapian *row); +time_t mu_msg_iter_xapian_get_date (MuMsgIterXapian *iter); /** * get the message sender(s) of the message * - * @param row a message + * @param iter a message * * @return the time, or 0 in case of error */ -const char* mu_msg_xapian_get_from (MuMsgXapian *row); +const char* mu_msg_iter_xapian_get_from (MuMsgIterXapian *iter); /** * get the message recipient (To:) of the message * - * @param row a message + * @param iter a message * * @return the To-recipient(s), or NULL in case of error */ -const char* mu_msg_xapian_get_to (MuMsgXapian *row); +const char* mu_msg_iter_xapian_get_to (MuMsgIterXapian *iter); /** * get the message recipient (Cc:) of the message * - * @param row a message + * @param iter a message * * @return the Cc-recipient(s), or NULL in case of error */ -const char* mu_msg_xapian_get_cc (MuMsgXapian *row); +const char* mu_msg_iter_xapian_get_cc (MuMsgIterXapian *iter); /** * get the subject of the message * - * @param row a message + * @param iter a message * * @return the subject, or NULL in case of error */ -const char* mu_msg_xapian_get_subject (MuMsgXapian *row); +const char* mu_msg_iter_xapian_get_subject (MuMsgIterXapian *iter); /** * get the message flags * - * @param row a message + * @param iter a message * * @return the message flags, or MU_MSG_FLAG_UNKNOWN */ -MuMsgFlags mu_msg_xapian_get_flags (MuMsgXapian *row); +MuMsgFlags mu_msg_iter_xapian_get_flags (MuMsgIterXapian *iter); /** * get the message priority * - * @param row a message + * @param iter a message * * @return the message priority, or MU_MSG_PRIORITY_NONE */ -MuMsgPriority mu_msg_xapian_get_priority (MuMsgXapian *row); +MuMsgPriority mu_msg_iter_xapian_get_priority (MuMsgIterXapian *iter); /** * get some message field * - * @param row a message + * @param iter a message * @param field the string field to retrieve * * @return the field value, or NULL */ -const gchar* mu_msg_xapian_get_field (MuMsgXapian *row, +const gchar* mu_msg_iter_xapian_get_field (MuMsgIterXapian *iter, const MuMsgField *field); /** * get some numeric message field * - * @param row a message + * @param iter a message * @param field the numeric field to retrieve * * @return the field value, or -1 in case of error */ -gint64 mu_msg_xapian_get_field_numeric (MuMsgXapian *row, +gint64 mu_msg_iter_xapian_get_field_numeric (MuMsgIterXapian *iter, const MuMsgField *field); G_END_DECLS -#endif /*__MU_MSG_XAPIAN_H__*/ +#endif /*__MU_MSG_ITER_XAPIAN_H__*/ diff --git a/src/mu-msg-xapian.cc b/src/mu-msg-xapian.cc deleted file mode 100644 index 67f3cd43..00000000 --- a/src/mu-msg-xapian.cc +++ /dev/null @@ -1,262 +0,0 @@ -/* -** Copyright (C) 2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#include -#include -#include -#include - -#include "xapian.h" - -#include "mu-util.h" -#include "mu-msg-xapian.h" - -struct _MuMsgXapian { - Xapian::Enquire *_enq; - Xapian::MSet _matches; - Xapian::MSet::const_iterator _cursor; - size_t _batchsize; - size_t _offset; - char* _str[MU_MSG_FIELD_ID_NUM]; -}; - - -/* FIXME: maybe use get_doccount() on the database object instead - * of specifying the batch size? */ -MuMsgXapian * -mu_msg_xapian_new (const Xapian::Enquire& enq, size_t batchsize) -{ - MuMsgXapian *msg; - - try { - msg = new MuMsgXapian; - memset (msg->_str, 0, sizeof(msg->_str)); - - msg->_enq = new Xapian::Enquire(enq); - msg->_matches = msg->_enq->get_mset (0, batchsize); - if (!msg->_matches.empty()) - msg->_cursor = msg->_matches.begin(); - - msg->_batchsize = batchsize; - msg->_offset = 0; - - return msg; - - } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); -} - -void -mu_msg_xapian_destroy (MuMsgXapian *msg) -{ - if (msg) { - for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) - g_free (msg->_str[i]); - - try { - delete msg->_enq; - delete msg; - - } MU_XAPIAN_CATCH_BLOCK; - } -} - -static gboolean -message_is_readable (MuMsgXapian *msg) -{ - Xapian::Document doc (msg->_cursor.get_document()); - const std::string path(doc.get_value(MU_MSG_FIELD_ID_PATH)); - - if (access (path.c_str(), R_OK) != 0) { - g_debug ("cannot read %s: %s", path.c_str(), - strerror(errno)); - return FALSE; - } - - return TRUE; -} - - - -gboolean -mu_msg_xapian_next (MuMsgXapian *msg) -{ - g_return_val_if_fail (msg, FALSE); - g_return_val_if_fail (!mu_msg_xapian_is_done(msg), FALSE); - - try { - if (++msg->_cursor == msg->_matches.end()) - return FALSE; /* no more matches */ - - /* the message may not be readable / existing, e.g., because - * of the database not being fully up to date. in that case, - * we ignore the message. it might be nice to auto-delete - * these messages from the db, but that would might screw - * up the search; also, we only have read-only access to the - * db here */ - if (!message_is_readable (msg)) - return mu_msg_xapian_next (msg); - - for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) { - g_free (msg->_str[i]); - msg->_str[i] = NULL; - } - - return TRUE; - - } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); -} - - -gboolean -mu_msg_xapian_is_done (MuMsgXapian *msg) -{ - g_return_val_if_fail (msg, TRUE); - - if (msg->_matches.empty()) - return TRUE; - - if (msg->_cursor == msg->_matches.end()) - return TRUE; - - return FALSE; -} - - -const gchar* -mu_msg_xapian_get_field (MuMsgXapian *row, const MuMsgField *field) -{ - g_return_val_if_fail (row, NULL); - g_return_val_if_fail (!mu_msg_xapian_is_done(row), NULL); - g_return_val_if_fail (field, NULL); - - try { - MuMsgFieldId id; - - id = mu_msg_field_id (field); - if (!row->_str[id]) { /* cache the value */ - Xapian::Document doc (row->_cursor.get_document()); - row->_str[id] = g_strdup (doc.get_value(id).c_str()); - } - - return row->_str[id]; - - } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); -} - - -gint64 -mu_msg_xapian_get_field_numeric (MuMsgXapian *row, const MuMsgField *field) -{ - g_return_val_if_fail (mu_msg_field_is_numeric(field), -1); - - try { - return Xapian::sortable_unserialise( - mu_msg_xapian_get_field(row, field)); - } MU_XAPIAN_CATCH_BLOCK_RETURN(-1); -} - - - -static const gchar* -get_field (MuMsgXapian *row, MuMsgFieldId id) -{ - return mu_msg_xapian_get_field(row, mu_msg_field_from_id (id)); -} - -static long -get_field_number (MuMsgXapian *row, MuMsgFieldId id) -{ - const char* str = get_field (row, id); - return str ? atol (str) : 0; -} - - - -/* hmmm.... is it impossible to get a 0 docid, or just very improbable? */ -unsigned int -mu_msg_xapian_get_docid (MuMsgXapian *row) -{ - g_return_val_if_fail (row, 0); - - try { - return row->_cursor.get_document().get_docid(); - - } MU_XAPIAN_CATCH_BLOCK_RETURN (0); -} - - -const char* -mu_msg_xapian_get_path (MuMsgXapian *row) -{ - return get_field (row, MU_MSG_FIELD_ID_PATH); -} - - -const char* -mu_msg_xapian_get_from (MuMsgXapian *row) -{ - return get_field (row, MU_MSG_FIELD_ID_FROM); -} - -const char* -mu_msg_xapian_get_to (MuMsgXapian *row) -{ - return get_field (row, MU_MSG_FIELD_ID_TO); -} - - -const char* -mu_msg_xapian_get_cc (MuMsgXapian *row) -{ - return get_field (row, MU_MSG_FIELD_ID_CC); -} - - -const char* -mu_msg_xapian_get_subject (MuMsgXapian *row) -{ - return get_field (row, MU_MSG_FIELD_ID_SUBJECT); -} - - -size_t -mu_msg_xapian_get_size (MuMsgXapian *row) -{ - return (size_t) get_field_number (row, MU_MSG_FIELD_ID_SIZE); -} - - -time_t -mu_msg_xapian_get_date (MuMsgXapian *row) -{ - return (size_t) get_field_number (row, MU_MSG_FIELD_ID_DATE); -} - - -MuMsgFlags -mu_msg_xapian_get_flags (MuMsgXapian *row) -{ - return (MuMsgFlags) get_field_number (row, MU_MSG_FIELD_ID_FLAGS); -} - -MuMsgPriority -mu_msg_xapian_get_priority (MuMsgXapian *row) -{ - return (MuMsgPriority) get_field_number (row, MU_MSG_FIELD_ID_PRIORITY); -} diff --git a/src/mu-query-xapian.cc b/src/mu-query-xapian.cc index a9b7b72c..9c6e7abb 100644 --- a/src/mu-query-xapian.cc +++ b/src/mu-query-xapian.cc @@ -25,8 +25,8 @@ #include "mu-query-xapian.h" -#include "mu-msg-xapian.h" -#include "mu-msg-xapian-priv.hh" +#include "mu-msg-iter-xapian.h" +#include "mu-msg-iter-xapian-priv.hh" #include "mu-util.h" #include "mu-util-xapian.h" @@ -167,7 +167,7 @@ mu_query_xapian_destroy (MuQueryXapian *self) } -MuMsgXapian* +MuMsgIterXapian* mu_query_xapian_run (MuQueryXapian *self, const char* searchexpr, const MuMsgField* sortfield, gboolean ascending) { @@ -187,7 +187,7 @@ mu_query_xapian_run (MuQueryXapian *self, const char* searchexpr, enq.set_query (q); enq.set_cutoff (0,0); - return mu_msg_xapian_new (enq, 10000); + return mu_msg_iter_xapian_new (enq, 10000); /* FIXME */ } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); } diff --git a/src/mu-query-xapian.h b/src/mu-query-xapian.h index 78585d8f..b9fa7327 100644 --- a/src/mu-query-xapian.h +++ b/src/mu-query-xapian.h @@ -21,7 +21,7 @@ #define __MU_QUERY_XAPIAN_H__ #include -#include "mu-msg-xapian.h" +#include "mu-msg-iter-xapian.h" G_BEGIN_DECLS /* @@ -68,13 +68,14 @@ char* mu_query_xapian_version (MuQueryXapian *store); * @param self a valid MuQueryXapian instance * @param expr the search expression * - * @return a MuMsgXapian instance you can iterate over, or NULL in + * @return a MuMsgIterXapian instance you can iterate over, or NULL in * case of error */ -MuMsgXapian* mu_query_xapian_run (MuQueryXapian *self, - const char* expr, - const MuMsgField* sortfield, - gboolean ascending) G_GNUC_WARN_UNUSED_RESULT; +MuMsgIterXapian* mu_query_xapian_run (MuQueryXapian *self, + const char* expr, + const MuMsgField* sortfield, + gboolean ascending) +G_GNUC_WARN_UNUSED_RESULT; /** * create a xapian query from list of expressions; for the syntax,