* 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_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,

View File

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

View File

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

View File

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

View File

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