aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/message.cc
diff options
context:
space:
mode:
authorGravatar Carl Worth <cworth@cworth.org>2009-12-21 08:23:26 -0800
committerGravatar Carl Worth <cworth@cworth.org>2010-01-06 10:32:05 -0800
commit6ca6c089e9df7affe6bee0392197509a24ab2546 (patch)
tree69eaca4254d5548d19da8ed989230d91a9088a9f /lib/message.cc
parent84742d86ab2fd3e5b5b601f073351454b993575e (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.cc77
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;
}