* lib/: a the thread-id field, store it in the database

This commit is contained in:
djcb 2012-12-25 16:43:34 +02:00
parent 58f5e39d34
commit a625371da2
5 changed files with 64 additions and 58 deletions

View File

@ -103,7 +103,7 @@ static const MuMsgField FIELD_DATA[] = {
{ {
MU_MSG_FIELD_ID_BODY_HTML, MU_MSG_FIELD_ID_BODY_HTML,
MU_MSG_FIELD_TYPE_STRING, MU_MSG_FIELD_TYPE_STRING,
"bodyhtml", 'h', 0, "bodyhtml", 0, 0,
FLAG_GMIME | FLAG_DONT_CACHE FLAG_GMIME | FLAG_DONT_CACHE
}, },
@ -236,6 +236,14 @@ static const MuMsgField FIELD_DATA[] = {
FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_ESCAPE 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_ID_TO,
MU_MSG_FIELD_TYPE_STRING, MU_MSG_FIELD_TYPE_STRING,

View File

@ -57,6 +57,7 @@ enum _MuMsgFieldId {
/* add new ones here... */ /* add new ones here... */
MU_MSG_FIELD_ID_MAILING_LIST, /* mailing list */ MU_MSG_FIELD_ID_MAILING_LIST, /* mailing list */
MU_MSG_FIELD_ID_THREAD_ID,
MU_MSG_FIELD_ID_NUM MU_MSG_FIELD_ID_NUM

View File

@ -165,9 +165,7 @@ public:
mu_contacts_clear (_contacts); mu_contacts_clear (_contacts);
} }
/* get a unique id for this message; note, this function returns a std::string get_uid_term (const char *path);
* static buffer -- not reentrant */
const char *get_uid_term (const char *path);
MuContacts* contacts() { return _contacts; } MuContacts* contacts() { return _contacts; }

View File

@ -44,18 +44,13 @@
// note: not re-entrant // note: not re-entrant
const char* std::string
_MuStore::get_uid_term (const char* path) _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]; char real_path[PATH_MAX + 1];
static char hex[18];
static const char uid_prefix = static const std::string uid_prefix (
mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); 1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID));
/* check profile to see if realpath is expensive; we need /* check profile to see if realpath is expensive; we need
* realpath here (and in mu-msg-file) to ensure that the same * 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)) if (!realpath (path, real_path))
strcpy (real_path, path); strcpy (real_path, path);
djbhash = 5381; return std::string (uid_prefix + mu_util_get_hash (real_path));
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;
} }

View File

@ -560,6 +560,7 @@ add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc)
break; break;
/////////////////////////////////////////// ///////////////////////////////////////////
case MU_MSG_FIELD_ID_THREAD_ID:
case MU_MSG_FIELD_ID_UID: case MU_MSG_FIELD_ID_UID:
break; /* already taken care of elsewhere */ break; /* already taken care of elsewhere */
default: default:
@ -682,9 +683,33 @@ new_doc_from_message (MuStore *store, MuMsg *msg)
return doc; 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 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 (store, MU_STORE_INVALID_DOCID);
g_return_val_if_fail (msg, 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 { try {
Xapian::docid id; Xapian::docid id;
Xapian::Document doc (new_doc_from_message(store, msg)); Xapian::Document doc (new_doc_from_message(store, msg));
const std::string term (store->get_uid_term const std::string term (store->get_uid_term (mu_msg_get_path(msg)));
(mu_msg_get_path(msg)));
if (!store->in_transaction()) if (!store->in_transaction())
store->begin_transaction(); store->begin_transaction();
doc.add_term (term); 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 */ if (docid == 0)
id = store->db_writable()->replace_document (term, doc); 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) if (store->inc_processed() % store->batch_size() == 0)
store->commit_transaction(); 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 unsigned
mu_store_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) 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 (msg, MU_STORE_INVALID_DOCID);
g_return_val_if_fail (docid != 0, MU_STORE_INVALID_DOCID); g_return_val_if_fail (docid != 0, MU_STORE_INVALID_DOCID);
try { return add_or_update_msg (store, docid, msg, err);
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;
} }
unsigned unsigned
mu_store_add_path (MuStore *store, const char *path, const char *maildir, mu_store_add_path (MuStore *store, const char *path, const char *maildir,
GError **err) GError **err)
@ -767,7 +783,7 @@ mu_store_add_path (MuStore *store, const char *path, const char *maildir,
if (!msg) if (!msg)
return MU_STORE_INVALID_DOCID; 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); mu_msg_unref (msg);
return docid; return docid;