mirror of https://github.com/djcb/mu.git
* lib/: a the thread-id field, store it in the database
This commit is contained in:
parent
58f5e39d34
commit
a625371da2
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue