Commit graph

441 commits

Author SHA1 Message Date
Austin Clements
98ee460eaa lib: API to retrieve database revision and UUID
This exposes the committed database revision to library users along
with a UUID that can be used to detect when revision numbers are no
longer comparable (e.g., because the database has been replaced).
2015-08-13 23:52:51 +02:00
Austin Clements
7f57b747b9 lib: Add per-message last modification tracking
This adds a new document value that stores the revision of the last
modification to message metadata, where the revision number increases
monotonically with each database commit.

An alternative would be to store the wall-clock time of the last
modification of each message.  In principle this is simpler and has
the advantage that any process can determine the current timestamp
without support from libnotmuch.  However, even assuming a computer's
clock never goes backward and ignoring clock skew in networked
environments, this has a fatal flaw.  Xapian uses (optimistic)
snapshot isolation, which means reads can be concurrent with writes.
Given this, consider the following time line with a write and two read
transactions:

   write  |-X-A--------------|
   read 1       |---B---|
   read 2                      |---|

The write transaction modifies message X and records the wall-clock
time of the modification at A.  The writer hangs around for a while
and later commits its change.  Read 1 is concurrent with the write, so
it doesn't see the change to X.  It does some query and records the
wall-clock time of its results at B.  Transaction read 2 later starts
after the write commits and queries for changes since wall-clock time
B (say the reads are performing an incremental backup).  Even though
read 1 could not see the change to X, read 2 is told (correctly) that
X has not changed since B, the time of the last read.  In fact, X
changed before wall-clock time A, but the change was not visible until
*after* wall-clock time B, so read 2 misses the change to X.

This is tricky to solve in full-blown snapshot isolation, but because
Xapian serializes writes, we can use a simple, monotonically
increasing database revision number.  Furthermore, maintaining this
revision number requires no more IO than a wall-clock time solution
because Xapian already maintains statistics on the upper (and lower)
bound of each value stream.
2015-08-13 23:52:51 +02:00
David Bremner
765556c1f1 build: extract library versions from notmuch.h
- Make lib/notmuch.h the canonical location for the library versioning
information.

- Since the release-check should never fail now, remove it to reduce
complexity.

- Make the version numbers in notmuch.h consistent with the (now
  deleted) ones in lib/Makefile.local
2015-08-10 13:53:55 +02:00
David Bremner
6b440a0adf lib: add public accessor for database from query
This is to make it easier for clients of the library to update to the
new error code returning versions of notmuch_query_search_messages
2015-08-04 09:11:34 +02:00
David Bremner
4fed7047b2 lib: deprecate notmuch_query_search_{threads, messages}
The CLI (and bindings) code should really be updated to use the new
status-code-returning versions. Here are some warnings to prod us (and
other clients) to do so.
2015-08-04 09:11:25 +02:00
David Bremner
7e2d0ef105 lib: define NOTMUCH_DEPRECATED macro, document its use.
This has been tested with gcc and clang.
2015-08-04 09:11:17 +02:00
Austin Clements
e6ad3a5dd4 lib: Only sync modified message documents
Previously, we updated the database copy of a message on every call to
_notmuch_message_sync, even if nothing had changed.  In particular,
this always happens on a thaw, so a freeze/thaw pair with no
modifications between still caused a database update.

We only modify message documents in a handful of places, so keep track
of whether the document has been modified and only sync it when
necessary.  This will be particularly important when we add message
revision tracking.
2015-08-04 08:54:46 +02:00
David Bremner
882ccb7e49 build: add "set -eu" to version script generation
It turns out that on certain systems like FreeBSD, c++filt is not
installed by default. It's basically OK if we fail the build in that
case, but what's really not OK is for the build to continue and
generate bad binaries.
2015-07-28 21:34:01 +02:00
David Bremner
53035dafe0 lib, ruby: make use of -Wl,--no-undefined configurable
In particular this is supposed to help build on systems (presumably
using a non-gnu ld) where this flag is not available.
2015-06-13 17:52:48 +02:00
David Bremner
32fd74b7aa lib: reject relative paths in n_d_{create,open}_verbose
There are many places in the notmuch code where the path is assumed to be absolute. If someone (TM) wants a project, one could remove these assumptions. In the mean time, prevent users from shooting themselves in the foot.

Update test suite mark tests for this error as no longer broken, and
also convert some tests that used relative paths for nonexistent
directories.
2015-06-12 07:34:50 +02:00
David Bremner
b59ad1a9cc lib: add NOTMUCH_STATUS_PATH_ERROR
The difference with FILE_ERROR is that this is for things that are
wrong with the path before looking at the disk.

Add some 3 tests; two broken as a reminder to actually use this new
code.
2015-06-12 07:34:47 +02:00
J. Lewis Muir
d08af93c65 cli: change "setup" to "set up" where used as a verb
The word "setup" is a noun, not a verb.  Change occurrences of "setup"
where used as a verb to "set up".
2015-05-31 19:14:42 +02:00
David Bremner
9d192da683 lib: eliminate fprintf from _notmuch_message_file_open
You may wonder why _notmuch_message_file_open_ctx has two parameters.
This is because we need sometime to use a ctx which is a
notmuch_message_t. While we could get the database from this, there is
no easy way in C to tell type we are getting.
2015-03-29 00:34:15 +01:00
David Bremner
736ac26407 lib: replace almost all fprintfs in library with _n_d_log
This is not supposed to change any functionality from an end user
point of view. Note that it will eliminate some output to stderr. The
query debugging output is left as is; it doesn't really fit with the
current primitive logging model. The remaining "bad" fprintf will need
an internal API change.
2015-03-29 00:34:15 +01:00
David Bremner
9b73a8bcc9 lib: add private function to extract the database for a message.
This is needed by logging in functions outside message.cc that take
only a notmuch_message_t object.
2015-03-29 00:34:15 +01:00
David Bremner
b53e1a2da7 lib: add a log function with output to a string in notmuch_database_t
In principle in the future this could do something fancier than
asprintf.
2015-03-29 00:34:15 +01:00
David Bremner
84d3b15d25 lib: add "verbose" versions of notmuch_database_{open,create}
The compatibility wrapper ensures that clients calling
notmuch_database_open will receive consistent output for now.

The changes to notmuch-{new,search} and test/symbol-test are just to
make the test suite pass.

The use of IGNORE_RESULT is justified by two things. 1) I don't know
what else to do.  2) asprintf guarantees the output string is NULL if
an error occurs, so at least we are not passing garbage back.
2015-03-29 00:34:15 +01:00
Jani Nikula
6d44e5ac47 lib: make notmuch_query_count_messages explicitely exact
The default is actually exact if no checkatleast parameter is
specified. This change makes that explicit, mainly for documentation,
but also to be safe in the unlikely event of a change of default.

[ commit message rewritten by db based on id:87lho0nlkk.fsf@nikula.org
]
2015-03-13 07:58:55 +01:00
David Bremner
90886f3640 lib: bump library minor version
This should have happened in commit 326e18856, but it didn't.
2015-03-07 20:15:06 +01:00
J. Lewis Muir
ee2d490280 lib: make notmuch shared library install_name be full path on Mac OS X
The install_name of libnotmuch.dylib on Mac OS X is what is written
into a program that links against it.  If it is just the name of the
shared library file, as opposed to the full path, the program won't be
able to find it when it runs and will abort.  Instead, the install_name
should be the full path to the shared library (in its final installed
location).

Why does Notmuch work without this patch when installed via Homebrew?
The answer is twofold.  One, /usr/local/lib is a special location in
which the dynamic linker will look by default to find shared libraries.
Homebrew highly recommends installing to /usr/local, and, assuming it
has been configured this way, the Notmuch library will end up installed
in /usr/local/lib, and the dynamic linker will find it.  Two, Homebrew
globally corrects all install names in dynamically shared libraries and
binaries for each package it installs.  So, even if the install names in
a package's binaries and libraries are incorrect, Homebrew corrects them
automatically, and no one ever knows.

Why does Notmuch work without this patch when installed via MacPorts?
The answer is that MacPorts applies a patch just like this patch to fix
the same problem.
2015-03-06 08:00:18 +01:00
David Bremner
326e188564 lib: bump SONAME minor version
This indicates upwardly compatible changes, namely adding new symbols.

Although we don't formally need to do this until the next release,
there is no hard in doing it now, as long as we don't bump the minor
version for every addition between now and the release.
2015-03-01 08:49:14 +01:00
David Bremner
7a0fc10367 lib: add new status reporting API for notmuch_query_search_{m,t}
This at least allows distinguishing between out of memory and Xapian
exceptions. Adding finer grained status codes would allow different
Xapian exceptions to be preserved.

Adding wrappers allows people to transition gradually to the new API,
at the cost of bloating the library API a bit.
2015-03-01 08:49:14 +01:00
Jani Nikula
08757767de lib: fix clang build warnings
Fix the following warning produced by clang 3.5.0:

lib/message.cc:899:4: warning: comparison of constant 64 with expression of type 'notmuch_message_flag_t' (aka '_notmuch_message_flag') is always true [-Wtautological-constant-out-of-range-compare]
        ! NOTMUCH_TEST_BIT (message->lazy_flags, flag))
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./lib/notmuch-private.h:70:6: note: expanded from macro 'NOTMUCH_TEST_BIT'
    (_NOTMUCH_VALID_BIT(bit) ? !!((val) & (1ull << (bit))) : 0)
     ^~~~~~~~~~~~~~~~~~~~~~~
./lib/notmuch-private.h:68:26: note: expanded from macro '_NOTMUCH_VALID_BIT'
    ((bit) >= 0 && (bit) < CHAR_BIT * sizeof (unsigned long long))
                   ~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2015-02-25 23:09:39 +01:00
Jani Nikula
41b870fba5 lib: abstract bit validity check in bit test/set/clear macros
Reduce duplication in the bit test/set/clear macros. No functional
changes.
2015-02-25 23:08:35 +01:00
Todd
b04bc967f9 Add indexing for the mimetype term
This adds the indexing support for the "mimetype:" term and removes
the broken test flag.  The indexing is probablistic in Xapian terms,
which gives a better experience to end users.  Standard content-types
of the form "foo/bar" are automatically interpreted as phrases in
Xapian due to the embedded slash.

Assume, separate messages with application/pdf and application/x-pdf
are indexed, then:

- mimetype:application/x-pdf will find only the application/x-pdf
- mimetype:application/pdf will find only the application/pdf
- mimetype:pdf will find both of the messages
2015-01-24 16:47:59 +01:00
Todd
0de999aab5 Add the NOTMUCH_FEATURE_INDEXED_MIMETYPES database feature
This feature will exist in all newly created databases, but there is
no upgrade provided for it.  If this flag exists, it indicates that
the database was created after the indexed MIME-types feature was
added.
2015-01-24 16:47:47 +01:00
Todd
ef5b4947d8 lib: Fix use after free
_thread_set_subject_from_message sometimes replaces the subject, making the
cur_subject point to free'd memory

==6550== ERROR: AddressSanitizer: heap-use-after-free on address 0x601a0000bec0 at pc 0x4464a4 bp 0x7fffa40be910 sp 0x7fffa40be908
READ of size 1 at 0x601a0000bec0 thread T0
    #0 0x4464a3 in _thread_add_matched_message /home/todd/.apps/notmuch/lib/thread.cc:369
    #1 0x443c2c in notmuch_threads_get /home/todd/.apps/notmuch/lib/query.cc:496
    #2 0x41d947 in do_search_threads /home/todd/.apps/notmuch/notmuch-search.c:131
    #3 0x40a3fe in main /home/todd/.apps/notmuch/notmuch.c:345
    #4 0x7f4e535b4ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/libc-start.c:287
    #5 0x40abe6 in _start ??:?
0x601a0000bec0 is located 96 bytes inside of 134-byte region [0x601a0000be60,0x601a0000bee6)
freed by thread T0 here:
    #0 0x7f4e54e6933a in __interceptor_free ??:?
    #1 0x7f4e54482fab in _talloc_free ??:?
previously allocated by thread T0 here:
    #0 0x7f4e54e6941a in malloc ??:?
    #1 0x7f4e54485b5d in talloc_strdup ??:?
2015-01-19 08:15:14 +01:00
Todd
0fc7884602 lib: Fix potential invalid read past an empty string
==22884== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x601600008291 at pc 0x7ff6295680e5 bp 0x7fff4ab9aa40 sp 0x7fff4ab9aa08
READ of size 1 at 0x601600008291 thread T0
    #0 0x7ff6295680e4 in __interceptor_strcmp ??:?
    #1 0x44763b in _thread_add_message /home/todd/.apps/notmuch/lib/thread.cc:255
    #2 0x4459e8 in notmuch_threads_get /home/todd/.apps/notmuch/lib/query.cc:496
    #3 0x41e2a7 in do_search_threads /home/todd/.apps/notmuch/notmuch-search.c:131
    #4 0x40a408 in main /home/todd/.apps/notmuch/notmuch.c:345
    #5 0x7ff627cb9ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/libc-start.c:287
    #6 0x40abf3 in _start ??:?
0x601600008291 is located 0 bytes to the right of 97-byte region [0x601600008230,0x601600008291)
allocated by thread T0 here:
    #0 0x7ff62956e41a in malloc ??:?
    #1 0x7ff628b8ab5d in talloc_strdup ??:?
2015-01-19 08:15:05 +01:00
Jesse Rosenthal
67e368ac7b thread.cc: Avoid empty thread names if possible.
Currently the thread is named based on either the oldest or newest
matching message (depending on the search order). If this message has
an empty subject, though, the thread will show up with an empty
subject in the search results. (See the thread starting with
`id:1412371140-21051-1-git-send-email-david@tethera.net` for an
example.)

This changes the behavior so it will use a non-empty name for the
thread if possible. We name threads based on (a) non-empty matches for
the query, and (b) the search order. If the search order is
oldest-first (as in the default inbox) it chooses the oldest matching
non-empty message as the subject. If the search order is newest-first
it chooses the newest one.
2015-01-17 13:48:26 +01:00
David Bremner
105537a809 lib: convert two "iterator copy strings" into references.
Apparently this is a supported and even idiomatic way of keeping a
temporary object (e.g. like that returned from an operator
dereference) alive.
2015-01-02 17:18:42 +01:00
David Bremner
3d978a0d61 lib: another iterator-temporary/stale-pointer bug
Tamas Szakaly points out [1] that the bug fixed in 51b073c still
exists in at least one place. This change follows the suggestion of
[2] and creates a block scope temporary std::string to avoid the rules
of iterators temporaries.

[1]: id:20141226113755.GA64154@pamparam
[2]: id:20141226230655.GA41992@pamparam
2015-01-02 17:10:37 +01:00
Jani Nikula
c82a1745ac lib: drop the deprecation message for single-message mbox files
We generally do not support mbox files, but for historical reasons
we've supported single-message mbox files, with a deprecation
message. We've tried dropping the support altogether, but backed out
of it because we'd need to stop indexing them, while keeping support
for previously indexed files. This would be more complicated than
simply supporting single-message mbox files. Therefore, drop the
deprecation message, and just silently accept single-message mboxes.
2015-01-01 16:47:47 +01:00
Jesse Rosenthal
4135a1f8da lib: Use email address instead of empty real name.
Currently, if a From-header is of the form:

    "" <address@example.com>

the empty string will be treated as a valid real-name, and the entry
in the search results will be empty.

The new behavior here is that we treat an empty real-name field as if
it were null, so that the email address will be used in the search
results instead.

Signed-off-by: Jesse Rosenthal <jrosenthal@jhu.edu>
2014-12-07 13:36:08 +01:00
David Bremner
74bd4ea2ed lib: bump LIBNOTMUCH_MAJOR_VERSION to 4
This should have been done at the same time as the SONAME bump.
2014-11-06 00:10:03 +01:00
Austin Clements
70f15b37fb lib: Remove unnecessary thread linking steps when using ghost messages
Previously, it was necessary to link new messages to children to work
around some (though not all) problems with the old metadata-based
approach to stored thread IDs.  With ghost messages, this is no longer
necessary, so don't bother with child linking when ghost messages are
in use.
2014-10-25 19:46:19 +02:00
Austin Clements
ee476f1e76 lib: Enable ghost messages feature
This fixes the broken thread order test.
2014-10-25 19:31:27 +02:00
Austin Clements
d1e8c80b72 lib: Implement upgrade to ghost messages feature
Somehow this is the first upgrade pass that actually does *any* error
checking, so this also adds the bit of necessary infrastructure to
handle that.
2014-10-25 19:30:08 +02:00
Austin Clements
58a4277d3b lib: Implement ghost-based thread linking
This updates the thread linking code to use ghost messages instead of
user metadata to link messages into threads.

In contrast with the old approach, this is actually correct.
Previously, thread merging updated only the thread IDs of message
documents, not thread IDs stored in user metadata.  As originally
diagnosed by Mark Walters [1] and as demonstrated by the broken
T260-thread-order test, this can cause notmuch to fail to link
messages even though they're in the same thread.  In principle the old
approach could have been fixed by updating the user metadata thread
IDs as well, but these are not indexed and hence this would have
required a full scan of all stored thread IDs.  Ghost messages solve
this problem naturally by reusing the exact same thread ID and message
ID representation and indexing as regular messages.

Furthermore, thanks to this greater symmetry, ghost messages are also
algorithmically simpler.  We continue to support the old user metadata
format, so this patch can't delete any code, but when we do remove
support for the old format, several functions can simply be deleted.

[1] id:8738h7kv2q.fsf@qmul.ac.uk
2014-10-25 19:27:07 +02:00
Austin Clements
bc9c50602d lib: Internal support for querying and creating ghost messages
This updates the message abstraction to support ghost messages: it
adds a message flag that distinguishes regular messages from ghost
messages, and an internal function for initializing a newly created
(blank) message as a ghost message.
2014-10-25 19:26:54 +02:00
Austin Clements
d99491f274 lib: Introduce macros for bit operations
These macros help clarify basic bit-twiddling code and are written to
be robust against C undefined behavior of shift operators.
2014-10-25 19:26:43 +02:00
Austin Clements
d9f5da00bb lib: Update database schema doc for ghost messages
This describes the structure of ghost mail documents.  Ghost messages
are not yet implemented.
2014-10-25 19:26:03 +02:00
Austin Clements
1cdb96d3c4 lib: Add a ghost messages database feature
This will be implemented over the next several patches.  The feature
is not yet "enabled" (this does not add it to
NOTMUCH_FEATURES_CURRENT).
2014-10-25 19:25:54 +02:00
Austin Clements
7487e2e221 lib: Handle empty date value
In the interest of robustness, avoid undefined behavior of
sortable_unserialise if the date value is missing.  This shouldn't
happen now, but ghost messages will have blank date values.
2014-10-11 07:10:12 +02:00
Austin Clements
46b1b035a5 lib: Refactor _notmuch_database_link_message
This moves the code to retrieve and clear the metadata thread ID out
of _notmuch_database_link_message into its own function.  This will
simplify future changes.
2014-10-11 07:10:02 +02:00
Austin Clements
54ec8a0fd8 lib: Move message ID compression to _notmuch_message_create_for_message_id
Previously, this was performed by notmuch_database_add_message.  This
happens to be the only caller currently (which is why this was safe),
but we're about to introduce more callers, and it makes more sense to
put responsibility for ID compression in the lower-level function
rather than requiring each caller to handle it.
2014-10-11 07:09:54 +02:00
Austin Clements
cec601c4dd lib: Simplify close and codify aborting atomic section
In Xapian, closing a database implicitly aborts any outstanding
transaction and commits changes.  For historical reasons,
notmuch_database_close had grown to almost, but not quite duplicate
this behavior.  Before closing the database, it would explicitly (and
unnecessarily) commit it.  However, if there was an outstanding
transaction (ie atomic section), commit would throw a Xapian
exception, which notmuch_database_close would unnecessarily print to
stderr, even though notmuch_database_close would ultimately abort the
transaction anyway when it called close.

This patch simplifies notmuch_database_close to explicitly abort any
outstanding transaction and then just call Database::close.  This
works for both read-only and read/write databases, takes care of
committing changes, unifies the exception handling path, and codifies
aborting outstanding transactions.  This is currently the only way to
abort an atomic section (and may remain so, since it would be
difficult to roll back things we may have cached from rolled-back
modifications).
2014-10-03 08:58:58 +02:00
Jani Nikula
f42e2e43a0 lib: actually return failures from notmuch_message_tags_to_maildir_flags
The function takes great care to preserve the first error status it
encounters, yet fails to return that status to the caller. Fix it.
2014-09-24 20:19:34 +02:00
Peter Wang
6754ad9f9e lib: bump soname
Adding return values to notmuch_database_close and
notmuch_database_destroy may require bumping the soname.
2014-09-16 20:16:31 +02:00
Gaute Hope
2c9e120e0a notmuch_thread_get_authors: document match grouping with |
as stated in thread.cc:115

/* Construct an authors string from matched_authors_array and
 * authors_array. The string contains matched authors first, then
 * non-matched authors (with the two groups separated by '|'). Within
 * each group, authors are listed in date order. */

this is, however, not reflected in the public API documentation in
notmuch.h:970. This patch a paragraph explaining how | separates the
group of authors of messages matching the query and those of messages
that do not, but are still contained in the thread.
2014-09-13 08:43:35 +02:00
Austin Clements
cca05ac10e lib: Fix endless upgrade problem
48db8c8 introduced a disagreement between when
notmuch_database_needs_upgrade returned TRUE and when
notmuch_database_upgrade actually performed an upgrade.  As a result,
if a database had a version less than 3, but no new features were
required, notmuch new would call notmuch_database_upgrade to perform
an upgrade, but notmuch_database_upgrade would return immediately
without updating the database version.  Hence, the next notmuch new
would do the same, and so on.

Fix this by ensuring that the upgrade-required logic is identical
between the two.
2014-09-01 23:06:51 -07:00