The majority of filenames will fit within PATH_MAX [4096] (because
that's a hard limit imposed by the filesystems) so we can avoid an
allocation per lookup and thereby eliminate a large proportion of the
overhead of scanning a maildir.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 notmuch-new.c |   75 ++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 0dd2784..13559d1 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -107,6 +107,7 @@ add_files_recursive (notmuch_database_t *notmuch,
                     add_files_state_t *state)
 {
     DIR *dir = NULL;
+    char buf[4096];
     struct dirent *entry = NULL;
     char *next = NULL;
     time_t path_mtime, path_dbtime;
@@ -114,6 +115,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     notmuch_message_t *message = NULL;
     struct dirent **namelist = NULL;
     int num_entries;
+    int path_len, dname_len;

     /* If we're told to, we bail out on encountering a read-only
      * directory, (with this being a clear clue from the user to
@@ -140,6 +142,12 @@ add_files_recursive (notmuch_database_t *notmuch,

     int i=0;

+    path_len = strlen (path);
+    if (path_len + 2 < (int) sizeof (buf)) {
+       memcpy (buf, path, path_len);
+       buf[path_len] = '/';
+    }
+
     while (!interrupted) {
        if (i == num_entries)
            break;
@@ -164,37 +172,42 @@ add_files_recursive (notmuch_database_t *notmuch,
            continue;
        }

-       next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
+       dname_len = strlen (entry->d_name);
+       if (path_len + dname_len + 2 < (int) sizeof (buf)) {
+           memcpy (buf + path_len + 1, entry->d_name, dname_len);
+           buf[path_len + dname_len + 1] = '\0';
+           next = buf;
+       } else {
+           next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
+       }

        if (stat (next, st)) {
            fprintf (stderr, "Error reading %s: %s\n",
                     next, strerror (errno));
            ret = NOTMUCH_STATUS_FILE_ERROR;
-           continue;
-       }
-
-       if (S_ISREG (st->st_mode)) {
-           /* If the file hasn't been modified since the last
-            * add_files, then we need not look at it. */
-           if (path_dbtime == 0 || st->st_mtime > path_dbtime) {
-               state->processed_files++;
-
-               status = notmuch_database_add_message (notmuch, next, &message);
-               switch (status) {
-                   /* success */
+       } else {
+           if (S_ISREG (st->st_mode)) {
+               /* If the file hasn't been modified since the last
+                * add_files, then we need not look at it. */
+               if (path_dbtime == 0 || st->st_mtime > path_dbtime) {
+                   state->processed_files++;
+
+                   status = notmuch_database_add_message (notmuch, next, 
&message);
+                   switch (status) {
+                       /* success */
                    case NOTMUCH_STATUS_SUCCESS:
                        state->added_messages++;
                        tag_inbox_and_unread (message);
                        break;
-                   /* Non-fatal issues (go on to next file) */
+                       /* Non-fatal issues (go on to next file) */
                    case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
-                       /* Stay silent on this one. */
+                       /* Stay silent on this one. */
                        break;
                    case NOTMUCH_STATUS_FILE_NOT_EMAIL:
                        fprintf (stderr, "Note: Ignoring non-mail file: %s\n",
                                 next);
                        break;
-                   /* Fatal issues. Don't process anymore. */
+                       /* Fatal issues. Don't process anymore. */
                    case NOTMUCH_STATUS_READONLY_DATABASE:
                    case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
                    case NOTMUCH_STATUS_OUT_OF_MEMORY:
@@ -210,25 +223,27 @@ add_files_recursive (notmuch_database_t *notmuch,
                    case NOTMUCH_STATUS_LAST_STATUS:
                        INTERNAL_ERROR ("add_message returned unexpected value: 
%d",  status);
                        goto DONE;
-               }
+                   }

-               if (message) {
-                   notmuch_message_destroy (message);
-                   message = NULL;
-               }
+                   if (message) {
+                       notmuch_message_destroy (message);
+                       message = NULL;
+                   }

-               if (do_add_files_print_progress) {
-                   do_add_files_print_progress = 0;
-                   add_files_print_progress (state);
+                   if (do_add_files_print_progress) {
+                       do_add_files_print_progress = 0;
+                       add_files_print_progress (state);
+                   }
                }
+           } else if (S_ISDIR (st->st_mode)) {
+               status = add_files_recursive (notmuch, next, st, state);
+               if (status && ret == NOTMUCH_STATUS_SUCCESS)
+                   ret = status;
            }
-       } else if (S_ISDIR (st->st_mode)) {
-           status = add_files_recursive (notmuch, next, st, state);
-           if (status && ret == NOTMUCH_STATUS_SUCCESS)
-               ret = status;
        }

-       talloc_free (next);
+       if (next != buf)
+           talloc_free (next);
        next = NULL;
     }

@@ -237,7 +252,7 @@ add_files_recursive (notmuch_database_t *notmuch,
        ret = status;

   DONE:
-    if (next)
+    if (next != buf)
        talloc_free (next);
     if (entry)
        free (entry);
-- 
1.6.5.3

Reply via email to