diff options
author | Carl Worth <cworth@cworth.org> | 2009-12-21 08:23:26 -0800 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2010-01-06 10:32:05 -0800 |
commit | 6ca6c089e9df7affe6bee0392197509a24ab2546 (patch) | |
tree | 69eaca4254d5548d19da8ed989230d91a9088a9f /lib/message.cc | |
parent | 84742d86ab2fd3e5b5b601f073351454b993575e (diff) |
database: Store mail filename as a new 'direntry' term, not as 'data'.
Instead of storing the complete message filename in the data portion
of a mail document we now store a 'direntry' term that contains the
document ID of a directory document and also the basename of the
message filename within that directory. This will allow us to easily
store multple filenames for a single message, and will also allow us
to find mail documents for files that previously existed in a
directory but that have since been deleted.
Diffstat (limited to 'lib/message.cc')
-rw-r--r-- | lib/message.cc | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/lib/message.cc b/lib/message.cc index 7c7ea7a1..3f533423 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -392,11 +392,15 @@ notmuch_message_get_replies (notmuch_message_t *message) * * This change will not be reflected in the database until the next * call to _notmuch_message_set_sync. */ -void +notmuch_status_t _notmuch_message_set_filename (notmuch_message_t *message, const char *filename) { - const char *relative; + const char *relative, *directory, *basename; + char *term; + Xapian::docid directory_id; + notmuch_status_t status; + void *local = talloc_new (message); if (message->filename) { talloc_free (message->filename); @@ -407,26 +411,79 @@ _notmuch_message_set_filename (notmuch_message_t *message, INTERNAL_ERROR ("Message filename cannot be NULL."); relative = _notmuch_database_relative_path (message->notmuch, filename); - message->doc.set_data (relative); + + status = _notmuch_database_split_path (local, relative, + &directory, &basename); + if (status) + return status; + + status = _notmuch_database_find_directory_id (message->notmuch, directory, + &directory_id); + if (status) + return status; + + term = talloc_asprintf (local, "%s%u:%s", + _find_prefix ("direntry"), directory_id, basename); + + message->doc.add_term (term); + + talloc_free (local); + + return NOTMUCH_STATUS_SUCCESS; } const char * notmuch_message_get_filename (notmuch_message_t *message) { - std::string filename_str; - const char *db_path; + const char *prefix = _find_prefix ("direntry"); + int prefix_len = strlen (prefix); + Xapian::TermIterator i; + char *direntry, *colon; + const char *db_path, *directory, *basename; + unsigned int directory_id; + void *local = talloc_new (message); if (message->filename) return message->filename; - filename_str = message->doc.get_data (); + i = message->doc.termlist_begin (); + i.skip_to (prefix); + + if (i != message->doc.termlist_end ()) + direntry = talloc_strdup (local, (*i).c_str ()); + + if (i == message->doc.termlist_end () || + strncmp (direntry, prefix, prefix_len)) + { + INTERNAL_ERROR ("message with no filename"); + } + + direntry += prefix_len; + + directory_id = strtol (direntry, &colon, 10); + + if (colon == NULL || *colon != ':') + INTERNAL_ERROR ("malformed direntry"); + + basename = colon + 1; + + *colon = '\0'; + db_path = notmuch_database_get_path (message->notmuch); - if (filename_str[0] != '/') - message->filename = talloc_asprintf (message, "%s/%s", db_path, - filename_str.c_str ()); + directory = _notmuch_database_get_directory_path (local, + message->notmuch, + directory_id); + + if (strlen (directory)) + message->filename = talloc_asprintf (message, "%s/%s/%s", + db_path, directory, basename); else - message->filename = talloc_strdup (message, filename_str.c_str ()); + message->filename = talloc_asprintf (message, "%s/%s", + db_path, basename); + talloc_free ((void *) directory); + + talloc_free (local); return message->filename; } |