aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--database.cc95
-rw-r--r--message.cc3
-rw-r--r--notmuch-private.h10
-rw-r--r--notmuch.c6
-rw-r--r--notmuch.h53
5 files changed, 158 insertions, 9 deletions
diff --git a/database.cc b/database.cc
index 442b850..7858f9d 100644
--- a/database.cc
+++ b/database.cc
@@ -484,6 +484,101 @@ notmuch_database_get_path (notmuch_database_t *notmuch)
return notmuch->path;
}
+notmuch_private_status_t
+find_timestamp_document (notmuch_database_t *notmuch, const char *db_key,
+ Xapian::Document *doc, unsigned int *doc_id)
+{
+ return find_unique_document (notmuch, "timestamp", db_key, doc, doc_id);
+}
+
+/* We allow the user to use arbitrarily long keys for timestamps,
+ * (they're for filesystem paths after all, which have no limit we
+ * know about). But we have a term-length limit. So if we exceed that,
+ * we'll use the SHA-1 of the user's key as the actual key for
+ * constructing a database term.
+ *
+ * Caution: This function returns a newly allocated string which the
+ * caller should free() when finished.
+ */
+static char *
+timestamp_db_key (const char *key)
+{
+ if (strlen (key) + 1 > NOTMUCH_TERM_MAX) {
+ return notmuch_sha1_of_string (key);
+ } else {
+ return strdup (key);
+ }
+}
+
+notmuch_status_t
+notmuch_database_set_timestamp (notmuch_database_t *notmuch,
+ const char *key, time_t timestamp)
+{
+ Xapian::Document doc;
+ unsigned int doc_id;
+ notmuch_private_status_t status;
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
+ char *db_key = NULL;
+
+ db_key = timestamp_db_key (key);
+
+ try {
+ status = find_timestamp_document (notmuch, db_key, &doc, &doc_id);
+
+ doc.add_value (0, Xapian::sortable_serialise (timestamp));
+
+ if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
+ char *term = talloc_asprintf (NULL, "%s%s",
+ _find_prefix ("timestamp"), db_key);
+ doc.add_term (term);
+ talloc_free (term);
+
+ notmuch->xapian_db->add_document (doc);
+ } else {
+ notmuch->xapian_db->replace_document (doc_id, doc);
+ }
+
+ } catch (Xapian::Error &error) {
+ fprintf (stderr, "A Xapian exception occurred: %s.\n",
+ error.get_msg().c_str());
+ ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+ if (db_key)
+ free (db_key);
+
+ return ret;
+}
+
+time_t
+notmuch_database_get_timestamp (notmuch_database_t *notmuch, const char *key)
+{
+ Xapian::Document doc;
+ unsigned int doc_id;
+ notmuch_private_status_t status;
+ char *db_key = NULL;
+ time_t ret = 0;
+
+ db_key = timestamp_db_key (key);
+
+ try {
+ status = find_timestamp_document (notmuch, db_key, &doc, &doc_id);
+
+ if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND)
+ goto DONE;
+
+ ret = Xapian::sortable_unserialise (doc.get_value (0));
+ } catch (Xapian::Error &error) {
+ goto DONE;
+ }
+
+ DONE:
+ if (db_key)
+ free (db_key);
+
+ return ret;
+}
+
notmuch_status_t
notmuch_database_add_message (notmuch_database_t *notmuch,
const char *filename)
diff --git a/message.cc b/message.cc
index ee0e8e1..c5a6273 100644
--- a/message.cc
+++ b/message.cc
@@ -82,7 +82,8 @@ prefix_t BOOLEAN_PREFIX[] = {
{ "attachment_extension", "O" },
{ "msgid", "Q" },
{ "thread", "H" },
- { "ref", "R" }
+ { "ref", "R" },
+ { "timestamp", "KTS" },
};
const char *
diff --git a/notmuch-private.h b/notmuch-private.h
index 5d0c1fa..88b01bd 100644
--- a/notmuch-private.h
+++ b/notmuch-private.h
@@ -21,15 +21,15 @@
#ifndef NOTMUCH_PRIVATE_H
#define NOTMUCH_PRIVATE_H
-#include "notmuch.h"
-
-NOTMUCH_BEGIN_DECLS
-
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* For getline */
#endif
-
#include <stdio.h>
+
+#include "notmuch.h"
+
+NOTMUCH_BEGIN_DECLS
+
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
diff --git a/notmuch.c b/notmuch.c
index 9b841b3..279d21a 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -18,11 +18,12 @@
* Author: Carl Worth <cworth@cworth.org>
*/
-#include "notmuch.h"
-
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* for getline */
#endif
+#include <stdio.h>
+
+#include "notmuch.h"
/* This is separate from notmuch-private.h because we're trying to
* keep notmuch.c from looking into any internals, (which helps us
@@ -30,7 +31,6 @@
*/
#include "xutil.h"
-#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <sys/stat.h>
diff --git a/notmuch.h b/notmuch.h
index f568bc0..2c290fd 100644
--- a/notmuch.h
+++ b/notmuch.h
@@ -31,6 +31,8 @@
NOTMUCH_BEGIN_DECLS
+#include <time.h>
+
#ifndef FALSE
#define FALSE 0
#endif
@@ -172,6 +174,57 @@ notmuch_database_default_path (void);
const char *
notmuch_database_get_path (notmuch_database_t *database);
+/* Store a timestamp within the database.
+ *
+ * The Notmuch database will not interpret this key nor the timestamp
+ * values at all. It will merely store them together and return the
+ * timestamp when notmuch_database_get_timestamp is called with the
+ * same value for 'key'.
+ *
+ * The intention is for the caller to use the timestamp to allow
+ * efficient identification of new messages to be added to the
+ * database. The recommended usage is as follows:
+ *
+ * o Read the mtime of a directory from the filesystem
+ *
+ * o Call add_message for all mail files in the directory
+ *
+ * o Call notmuch_database_set_timestamp with the path of the
+ * directory as 'key' and the originally read mtime as 'value'.
+ *
+ * Then, when wanting to check for updates to the directory in the
+ * future, the client can call notmuch_database_get_timestamp and know
+ * that it only needs to add files if the mtime of the directory and
+ * files are newer than the stored timestamp.
+ *
+ * Note: The notmuch_database_get_timestamp function does not allow
+ * the caller to distinguish a timestamp of 0 from a non-existent
+ * timestamp. So don't store a timestamp of 0 unless you are
+ * comfortable with that.
+ *
+ * Return value:
+ *
+ * NOTMUCH_STATUS_SUCCESS: Timestamp successfully stored in database.
+ *
+ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception
+ * occurred. Timestamp not stored.
+ */
+notmuch_status_t
+notmuch_database_set_timestamp (notmuch_database_t *database,
+ const char *key, time_t timestamp);
+
+/* Retrieve a timestamp from the database.
+ *
+ * Returns the timestamp value previously stored by calling
+ * notmuch_database_set_timestamp with the same value for 'key'.
+ *
+ * Returns 0 if no timestamp is stored for 'key' or if any error
+ * occurred querying the database.
+ */
+time_t
+notmuch_database_get_timestamp (notmuch_database_t *database,
+ const char *key);
+
/* Add a new message to the given notmuch database.
*
* Here,'filename' should be a path relative to the the path of