From a625371da28109d46da84420f6b6243a6fa1866e Mon Sep 17 00:00:00 2001 From: djcb Date: Tue, 25 Dec 2012 16:43:34 +0200 Subject: [PATCH] * lib/: a the thread-id field, store it in the database --- lib/mu-msg-fields.c | 10 +++++- lib/mu-msg-fields.h | 1 + lib/mu-store-priv.hh | 4 +-- lib/mu-store-read.cc | 27 +++------------ lib/mu-store-write.cc | 80 ++++++++++++++++++++++++++----------------- 5 files changed, 64 insertions(+), 58 deletions(-) diff --git a/lib/mu-msg-fields.c b/lib/mu-msg-fields.c index 543798ab..962a736e 100644 --- a/lib/mu-msg-fields.c +++ b/lib/mu-msg-fields.c @@ -103,7 +103,7 @@ static const MuMsgField FIELD_DATA[] = { { MU_MSG_FIELD_ID_BODY_HTML, MU_MSG_FIELD_TYPE_STRING, - "bodyhtml", 'h', 0, + "bodyhtml", 0, 0, FLAG_GMIME | FLAG_DONT_CACHE }, @@ -236,6 +236,14 @@ static const MuMsgField FIELD_DATA[] = { FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_ESCAPE }, + + { /* remember which thread this message is in */ + MU_MSG_FIELD_ID_THREAD_ID, + MU_MSG_FIELD_TYPE_STRING, + "thread", 0, 'W', + FLAG_XAPIAN_TERM + }, + { MU_MSG_FIELD_ID_TO, MU_MSG_FIELD_TYPE_STRING, diff --git a/lib/mu-msg-fields.h b/lib/mu-msg-fields.h index d203e1ec..0f9a3293 100644 --- a/lib/mu-msg-fields.h +++ b/lib/mu-msg-fields.h @@ -57,6 +57,7 @@ enum _MuMsgFieldId { /* add new ones here... */ MU_MSG_FIELD_ID_MAILING_LIST, /* mailing list */ + MU_MSG_FIELD_ID_THREAD_ID, MU_MSG_FIELD_ID_NUM diff --git a/lib/mu-store-priv.hh b/lib/mu-store-priv.hh index 37a1fc58..e055ea55 100644 --- a/lib/mu-store-priv.hh +++ b/lib/mu-store-priv.hh @@ -165,9 +165,7 @@ public: mu_contacts_clear (_contacts); } - /* get a unique id for this message; note, this function returns a - * static buffer -- not reentrant */ - const char *get_uid_term (const char *path); + std::string get_uid_term (const char *path); MuContacts* contacts() { return _contacts; } diff --git a/lib/mu-store-read.cc b/lib/mu-store-read.cc index eb332eba..15b0a41b 100644 --- a/lib/mu-store-read.cc +++ b/lib/mu-store-read.cc @@ -44,18 +44,13 @@ // note: not re-entrant -const char* +std::string _MuStore::get_uid_term (const char* path) { - // combination of DJB, BKDR hash functions to get a 64 bit - // value - unsigned djbhash, bkdrhash, bkdrseed; - unsigned u; - char real_path[PATH_MAX + 1]; - static char hex[18]; - static const char uid_prefix = - mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); + + static const std::string uid_prefix ( + 1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID)); /* check profile to see if realpath is expensive; we need * realpath here (and in mu-msg-file) to ensure that the same @@ -66,19 +61,7 @@ _MuStore::get_uid_term (const char* path) if (!realpath (path, real_path)) strcpy (real_path, path); - djbhash = 5381; - bkdrhash = 0; - bkdrseed = 1313; - - for(u = 0; real_path[u]; ++u) { - djbhash = ((djbhash << 5) + djbhash) + real_path[u]; - bkdrhash = bkdrhash * bkdrseed + real_path[u]; - } - - snprintf (hex, sizeof(hex), "%c%08x%08x", - uid_prefix, djbhash, bkdrhash); - - return hex; + return std::string (uid_prefix + mu_util_get_hash (real_path)); } diff --git a/lib/mu-store-write.cc b/lib/mu-store-write.cc index eab3e977..6291a94b 100644 --- a/lib/mu-store-write.cc +++ b/lib/mu-store-write.cc @@ -560,6 +560,7 @@ add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc) break; /////////////////////////////////////////// + case MU_MSG_FIELD_ID_THREAD_ID: case MU_MSG_FIELD_ID_UID: break; /* already taken care of elsewhere */ default: @@ -682,9 +683,33 @@ new_doc_from_message (MuStore *store, MuMsg *msg) return doc; } +static void +update_threading_info (Xapian::WritableDatabase* db, + MuMsg *msg, Xapian::Document& doc) +{ + const GSList *refs; + + // refs contains a list of parent messages, with the oldest + // one first until the last one, which is the direct parent of + // the current message. of course, it may be empty. + // + // NOTE: there may be cases where the the list is truncated; + // we happily ignore that case. + refs = mu_msg_get_references (msg); + + std::string thread_id; + if (refs) + thread_id = mu_util_get_hash ((const char*)refs->data); + else + thread_id = mu_util_get_hash (mu_msg_get_msgid (msg)); + + doc.add_term (prefix(MU_MSG_FIELD_ID_THREAD_ID) + thread_id); + doc.add_value((Xapian::valueno)MU_MSG_FIELD_ID_THREAD_ID, thread_id); +} + unsigned -mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err) +add_or_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) { g_return_val_if_fail (store, MU_STORE_INVALID_DOCID); g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); @@ -692,18 +717,23 @@ mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err) try { Xapian::docid id; Xapian::Document doc (new_doc_from_message(store, msg)); - const std::string term (store->get_uid_term - (mu_msg_get_path(msg))); + const std::string term (store->get_uid_term (mu_msg_get_path(msg))); if (!store->in_transaction()) store->begin_transaction(); doc.add_term (term); - // MU_WRITE_LOG ("adding: %s", term.c_str()); + // update the threading info if this message has a message id + if (mu_msg_get_msgid (msg)) + update_threading_info (store->db_writable(), msg, doc); - /* note, this will replace any other messages for this path */ - id = store->db_writable()->replace_document (term, doc); + if (docid == 0) + id = store->db_writable()->replace_document (term, doc); + else { + store->db_writable()->replace_document (docid, doc); + id = docid; + } if (store->inc_processed() % store->batch_size() == 0) store->commit_transaction(); @@ -719,6 +749,16 @@ mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err) } + +unsigned +mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err) +{ + g_return_val_if_fail (store, MU_STORE_INVALID_DOCID); + g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); + + return add_or_update_msg (store, 0, msg, err); +} + unsigned mu_store_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) { @@ -726,33 +766,9 @@ mu_store_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); g_return_val_if_fail (docid != 0, MU_STORE_INVALID_DOCID); - try { - Xapian::Document doc (new_doc_from_message(store, msg)); - - if (!store->in_transaction()) - store->begin_transaction(); - - const std::string term - (store->get_uid_term(mu_msg_get_path(msg))); - doc.add_term (term); - - store->db_writable()->replace_document (docid, doc); - - if (store->inc_processed() % store->batch_size() == 0) - store->commit_transaction(); - - return docid; - - } MU_XAPIAN_CATCH_BLOCK_G_ERROR (err, MU_ERROR_XAPIAN_STORE_FAILED); - - if (store->in_transaction()) - store->rollback_transaction(); - - return MU_STORE_INVALID_DOCID; + return add_or_update_msg (store, docid, msg, err); } - - unsigned mu_store_add_path (MuStore *store, const char *path, const char *maildir, GError **err) @@ -767,7 +783,7 @@ mu_store_add_path (MuStore *store, const char *path, const char *maildir, if (!msg) return MU_STORE_INVALID_DOCID; - docid = mu_store_add_msg (store, msg, err); + docid = add_or_update_msg (store, 0, msg, err); mu_msg_unref (msg); return docid;