From d87db8843266caf6b11c1f2f1874328830b23878 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 10 Nov 2010 23:26:31 -0800 Subject: [PATCH] lib: Add new implementation of notmuch_filenames_t The new implementation is simply a talloc-based list of strings. The former support (a list of database terms with a common prefix) is implemented by simply pre-iterating over the terms and populating the list. This should provide no performance disadvantage as callers of thigns like notmuch_directory_get_child_files are very likely to always iterate over all filenames anyway. This new implementation of notmuch_filenames_t is in preparation for adding API to query all of the filenames for a single message. --- lib/Makefile.local | 1 + lib/directory.cc | 107 ++++++++-------------------------------- lib/filenames.c | 111 ++++++++++++++++++++++++++++++++++++++++++ lib/messages.c | 3 +- lib/notmuch-private.h | 12 +++++ 5 files changed, 144 insertions(+), 90 deletions(-) create mode 100644 lib/filenames.c diff --git a/lib/Makefile.local b/lib/Makefile.local index 3d7de5ca..5ad0a4ca 100644 --- a/lib/Makefile.local +++ b/lib/Makefile.local @@ -47,6 +47,7 @@ extra_cflags += -I$(dir) -fPIC libnotmuch_c_srcs = \ $(notmuch_compat_srcs) \ + $(dir)/filenames.c \ $(dir)/libsha1.c \ $(dir)/message-file.c \ $(dir)/messages.c \ diff --git a/lib/directory.cc b/lib/directory.cc index 2540ca76..16492c0d 100644 --- a/lib/directory.cc +++ b/lib/directory.cc @@ -21,28 +21,6 @@ #include "notmuch-private.h" #include "database-private.h" -struct _notmuch_filenames { - Xapian::TermIterator iterator; - Xapian::TermIterator end; - int prefix_len; - char *filename; -}; - -/* We end up having to call the destructors explicitly because we had - * to use "placement new" in order to initialize C++ objects within a - * block that we allocated with talloc. So C++ is making talloc - * slightly less simple to use, (we wouldn't need - * talloc_set_destructor at all otherwise). - */ -static int -_notmuch_filenames_destructor (notmuch_filenames_t *filenames) -{ - filenames->iterator.~TermIterator (); - filenames->end.~TermIterator (); - - return 0; -} - /* Create an iterator to iterate over the basenames of files (or * directories) that all share a common parent directory. * @@ -51,79 +29,31 @@ _notmuch_filenames_destructor (notmuch_filenames_t *filenames) * prefix. */ static notmuch_filenames_t * -_notmuch_filenames_create (void *ctx, - notmuch_database_t *notmuch, - const char *prefix) +_create_filenames_for_terms_with_prefix (void *ctx, + notmuch_database_t *notmuch, + const char *prefix) { notmuch_filenames_t *filenames; + Xapian::TermIterator i, end; + int prefix_len = strlen (prefix); - filenames = talloc (ctx, notmuch_filenames_t); + filenames = _notmuch_filenames_create (ctx); if (unlikely (filenames == NULL)) return NULL; - new (&filenames->iterator) Xapian::TermIterator (); - new (&filenames->end) Xapian::TermIterator (); - - talloc_set_destructor (filenames, _notmuch_filenames_destructor); - - filenames->iterator = notmuch->xapian_db->allterms_begin (prefix); - filenames->end = notmuch->xapian_db->allterms_end (prefix); - - filenames->prefix_len = strlen (prefix); - - filenames->filename = NULL; - - return filenames; -} - -notmuch_bool_t -notmuch_filenames_valid (notmuch_filenames_t *filenames) -{ - if (filenames == NULL) - return NULL; - - return (filenames->iterator != filenames->end); -} - -const char * -notmuch_filenames_get (notmuch_filenames_t *filenames) -{ - if (filenames == NULL || filenames->iterator == filenames->end) - return NULL; - - if (filenames->filename == NULL) { - std::string term = *filenames->iterator; - - filenames->filename = talloc_strdup (filenames, - term.c_str () + - filenames->prefix_len); - } - - return filenames->filename; -} + end = notmuch->xapian_db->allterms_end (prefix); -void -notmuch_filenames_move_to_next (notmuch_filenames_t *filenames) -{ - if (filenames == NULL) - return; + for (i = notmuch->xapian_db->allterms_begin (prefix); i != end; i++) + { + std::string term = *i; - if (filenames->filename) { - talloc_free (filenames->filename); - filenames->filename = NULL; + _notmuch_filenames_add_filename (filenames, term.c_str () + + prefix_len); } - if (filenames->iterator != filenames->end) - filenames->iterator++; -} + _notmuch_filenames_move_to_first (filenames); -void -notmuch_filenames_destroy (notmuch_filenames_t *filenames) -{ - if (filenames == NULL) - return; - - talloc_free (filenames); + return filenames; } struct _notmuch_directory { @@ -304,8 +234,9 @@ notmuch_directory_get_child_files (notmuch_directory_t *directory) _find_prefix ("file-direntry"), directory->document_id); - child_files = _notmuch_filenames_create (directory, - directory->notmuch, term); + child_files = _create_filenames_for_terms_with_prefix (directory, + directory->notmuch, + term); talloc_free (term); @@ -322,8 +253,8 @@ notmuch_directory_get_child_directories (notmuch_directory_t *directory) _find_prefix ("directory-direntry"), directory->document_id); - child_directories = _notmuch_filenames_create (directory, - directory->notmuch, term); + child_directories = _create_filenames_for_terms_with_prefix (directory, + directory->notmuch, term); talloc_free (term); diff --git a/lib/filenames.c b/lib/filenames.c new file mode 100644 index 00000000..cff9e830 --- /dev/null +++ b/lib/filenames.c @@ -0,0 +1,111 @@ +/* filenames.c - Iterator for a list of filenames + * + * Copyright © 2010 Intel Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ . + * + * Author: Carl Worth + */ + +#include "notmuch-private.h" + +typedef struct _notmuch_filenames_node { + char *filename; + struct _notmuch_filenames_node *next; +} notmuch_filenames_node_t; + +struct _notmuch_filenames { + notmuch_filenames_node_t *head; + notmuch_filenames_node_t **tail; + notmuch_filenames_node_t *iterator; +}; + +/* Create a new notmuch_filenames_t object, with 'ctx' as its + * talloc owner. + * + * This function can return NULL in case of out-of-memory. + */ +notmuch_filenames_t * +_notmuch_filenames_create (const void *ctx) +{ + notmuch_filenames_t *filenames; + + filenames = talloc (ctx, notmuch_filenames_t); + if (unlikely (filenames == NULL)) + return NULL; + + filenames->head = NULL; + filenames->tail = &filenames->head; + + filenames->iterator = NULL; + + return filenames; +} + +/* Append a single 'node' to the end of 'filenames'. + */ +void +_notmuch_filenames_add_filename (notmuch_filenames_t *filenames, + const char *filename) +{ + /* Create and initialize new node. */ + notmuch_filenames_node_t *node = talloc (filenames, + notmuch_filenames_node_t); + + node->filename = talloc_strdup (node, filename); + node->next = NULL; + + /* Append the node to the list. */ + *(filenames->tail) = node; + filenames->tail = &node->next; +} + +notmuch_bool_t +notmuch_filenames_valid (notmuch_filenames_t *filenames) +{ + if (filenames == NULL) + return FALSE; + + return (filenames->iterator != NULL); +} + +const char * +notmuch_filenames_get (notmuch_filenames_t *filenames) +{ + if (filenames->iterator == NULL) + return NULL; + + return filenames->iterator->filename; +} + +void +_notmuch_filenames_move_to_first (notmuch_filenames_t *filenames) +{ + filenames->iterator = filenames->head; +} + +void +notmuch_filenames_move_to_next (notmuch_filenames_t *filenames) +{ + if (filenames->iterator == NULL) + return; + + filenames->iterator = filenames->iterator->next; +} + +void +notmuch_filenames_destroy (notmuch_filenames_t *filenames) +{ + talloc_free (filenames); +} diff --git a/lib/messages.c b/lib/messages.c index db2b7a16..120a48a9 100644 --- a/lib/messages.c +++ b/lib/messages.c @@ -42,8 +42,7 @@ _notmuch_message_list_create (const void *ctx) return list; } -/* Append 'node' (which can of course point to an arbitrarily long - * list of nodes) to the end of 'list'. +/* Append a single 'node' to the end of 'list'. */ void _notmuch_message_list_append (notmuch_message_list_t *list, diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 4c3d3eb8..6a9d5ddd 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -448,6 +448,18 @@ _notmuch_tags_add_tag (notmuch_tags_t *tags, const char *tag); void _notmuch_tags_prepare_iterator (notmuch_tags_t *tags); +/* filenames.c */ + +notmuch_filenames_t * +_notmuch_filenames_create (const void *ctx); + +void +_notmuch_filenames_add_filename (notmuch_filenames_t *filenames, + const char *filename); + +void +_notmuch_filenames_move_to_first (notmuch_filenames_t *filenames); + #pragma GCC visibility pop NOTMUCH_END_DECLS -- 2.26.2