summaryrefslogtreecommitdiff
path: root/lib
AgeCommit message (Collapse)Author
2023-07-22lib/n_d_remove_message: do not remove unique filenameDavid Bremner
It is wasteful to remove a filename term when the whole message document is about to be removed from the database. Profiling with perf shows this takes a significant portion of the time when cleaning up removed files in the database. The logic of n_d_remove_message becomes a bit more convoluted here in order to make the change minimal. It is possible that this function can be further optimized, since the expansion of filename terms into filenames is probably not needed here.
2023-07-22lib/message: check message type before deleting documentDavid Bremner
It isn't really clear how this worked before. Traversing the terms of a document after deleting it from the database seems likely to be undefined behaviour at best
2023-07-09doc/lib: clarify ownership for notmuch_database_get_revisionDavid Bremner
The ownership is implicit in the const declaration (I think!), but that does not show up in the doxygen generated API docs.
2023-04-02lib: index attachments with mime types matching index.as_textDavid Bremner
Instead of skipping indexing all attachments, we check of a (user configured) mime type that is indexable as text.
2023-04-02lib: parse index.as_textDavid Bremner
We pre-parse into a list of compiled regular expressions to avoid calling regexc on the hot (indexing) path. As explained in the code comment, this cannot be done lazily with reasonable error reporting, at least not without touching a lot of the code in index.cc.
2023-04-02lib: add config key INDEX_AS_TEXTDavid Bremner
Higher level processing as a list of regular expressions and documentation will follow.
2023-03-31lib: replace some uses of Query::MatchAll with a thread-safe alternativeKevin Boulain
This replaces two instances of Xapian::Query::MatchAll with the equivalent but thread-safe alternative Xapian::Query(std::string()). Xapian::Query::MatchAll maintains an internal pointer to a refcounted Xapian::Internal::QueryTerm. None of this is thread-safe but that wouldn't be an issue if Xapian::Query::MatchAll wasn't static. Because it's static, the refcounting goes awry when Notmuch is called from multiple threads. This is actually documented by Xapian: https://github.com/xapian/xapian/blob/4715de3a9fcee741587439dc3cc1d2ff01ffeaf2/xapian-core/include/xapian/query.h#L65 While static, Xapian::Query::MatchNothing is safe because it doesn't maintain an internal object and as such, doesn't use references. Two best-effort tests making use of TSan were added to showcase the issue (I couldn't figure out a way to deterministically reproduce it without making an unmaintainable mess). First, when two databases are created in parallel, a query that uses Xapian::Query::MatchAll is made (lib/query.cc), resulting in the following backtrace on a segfault: #0 0x00007ffff76822af in Xapian::Query::get_terms_begin (this=0x7fffe80137f0) at api/query.cc:141 #1 0x00007ffff7f933f5 in _notmuch_query_cache_terms (query=0x7fffe80137c0) at lib/query.cc:176 #2 0x00007ffff7f93784 in _notmuch_query_ensure_parsed_xapian (query=0x7fffe80137c0) at lib/query.cc:225 #3 0x00007ffff7f9381a in _notmuch_query_ensure_parsed (query=0x7fffe80137c0) at lib/query.cc:260 #4 0x00007ffff7f93bfe in _notmuch_query_search_documents (query=0x7fffe80137c0, type=0x7ffff7fa9b1e "mail", out=0x7ffff666da18) at lib/query.cc:361 #5 0x00007ffff7f93ba4 in notmuch_query_search_messages (query=0x7fffe80137c0, out=0x7ffff666da18) at lib/query.cc:349 #6 0x00007ffff7f83d98 in notmuch_database_upgrade (notmuch=0x7fffe8000bd0, progress_notify=0x0, closure=0x0) at lib/database.cc:934 #7 0x00007ffff7fa110f in notmuch_database_create_with_config (database_path=0x7ffff666dcb0 "/tmp/notmuch.MZ2AGr", config_path=0x7ffff7faab3c "", profile=0x0, database=0x0, status_string=0x7ffff666dc90) at lib/open.cc:754 #8 0x00007ffff7fa0d6f in notmuch_database_create_verbose (path=0x7ffff666dcb0 "/tmp/notmuch.MZ2AGr", database=0x0, status_string=0x7ffff666dc90) at lib/open.cc:653 #9 0x00007ffff7fa0ceb in notmuch_database_create (path=0x7ffff666dcb0 "/tmp/notmuch.MZ2AGr", database=0x0) at lib/open.cc:637 ... Second, some queries would make use of Xapian::Query::MatchAll (lib/regexp-fields.cc), resulting in the following backtrace on a segfault: #0 0x00007f629828b690 in Xapian::Internal::QueryBranch::gather_terms (this=0x7f628800def0, void_terms=0x7f629726d5a0) at api/queryinternal.cc:1245 #1 0x00007f629828c260 in Xapian::Internal::QueryScaleWeight::gather_terms (this=0x7f628800df70, void_terms=0x7f629726d5a0) at api/queryinternal.cc:1434 #2 0x00007f629828b69f in Xapian::Internal::QueryBranch::gather_terms (this=0x7f628800dd90, void_terms=0x7f629726d5a0) at api/queryinternal.cc:1245 #3 0x00007f6298282571 in Xapian::Query::get_unique_terms_begin (this=0x7f628800dcd8) at api/query.cc:166 #4 0x00007f629841a59b in Xapian::Weight::Internal::accumulate_stats (this=0x7f628800dca0, subdb=..., rset=...) at weight/weightinternal.cc:86 #5 0x00007f62983c15ba in LocalSubMatch::prepare_match (this=0x7f628800df20, nowait=true, total_stats=...) at matcher/localsubmatch.cc:172 #6 0x00007f62983c8fcc in prepare_sub_matches (leaves=std::vector of length 1, capacity 1 = {...}, stats=...) at matcher/multimatch.cc:237 #7 0x00007f62983c98a3 in MultiMatch::MultiMatch (this=0x7f629726d9a0, db_=..., query_=..., qlen=3, omrset=0x0, collapse_max_=0, collapse_key_=4294967295, percent_cutoff_=0, weight_cutoff_=0, order_=Xapian::Enquire::ASCENDING, sort_key_=0, sort_by_=Xapian::Enquire::Internal::VAL, sort_value_forward_=true, time_limit_=0, stats=..., weight_=0x7f6288008d50, matchspies_=std::vector of length 0, capacity 0, have_sorter=false, have_mdecider=false) at matcher/multimatch.cc:353 #8 0x00007f629826fcba in Xapian::Enquire::Internal::get_mset (this=0x7f628800e0b0, first=0, maxitems=0, check_at_least=0, rset=0x0, mdecider=0x0) at api/omenquire.cc:569 #9 0x00007f629827181c in Xapian::Enquire::get_mset (this=0x7f629726db80, first=0, maxitems=0, check_at_least=0, rset=0x0, mdecider=0x0) at api/omenquire.cc:937 #10 0x00007f6298be529a in _notmuch_query_search_documents (query=0x7f6288009750, type=0x7f6298bfaafe "mail", out=0x7f629726dcc0) at lib/query.cc:447 #11 0x00007f6298be4ae8 in notmuch_query_search_messages (query=0x7f6288009750, out=0x7f629726dcc0) at lib/query.cc:349 ... Printing Xapian::Query::MatchAll->internal.px->_refs in these circumstances can help quickly identifying this scenario. This is motivated by some test frameworks (like Rust's Cargo) that runs unit tests in parallel and would easily encounter this issue, unless client code gates every call to Notmuch behind a lock. This is what can be expected from the tests when they fail: == stderr == +================== +WARNING: ThreadSanitizer: data race (pid=207931) + Read of size 1 at 0x7b10000001a0 by thread T2: + #0 memcpy <null> (libtsan.so.2+0x62506) + #1 void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag) [clone .isra.0] <null> (libxapian.so.30+0x872b3) + + Previous write of size 8 at 0x7b10000001a0 by thread T1: + #0 operator new(unsigned long) <null> (libtsan.so.2+0x8ba83) + #1 Xapian::Query::Query(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, unsigned int) <null> (libxapian.so.30+0x855cd) ...
2023-03-30lib/message-property: sync removed properties to the databaseKevin Boulain
_notmuch_message_remove_all_properties wasn't syncing the message back to the database but was still invalidating the metadata, giving the impression the properties had actually been removed. Also move the metadata invalidation to _notmuch_message_remove_terms to be closer to what's done in _notmuch_message_modify_property and _notmuch_message_remove_term.
2023-03-30lib/message-property: catch xapian exceptionsKevin Boulain
Since libnotmuch exposes a C interface there's no way for clients to catch this. Inspired by what's done for tags (see notmuch_message_remove_tag).
2023-02-27lib/notmuch: update exampleKevin Boulain
Likely missed in 86cbd215e, when notmuch_query_search_messages_st was renamed to notmuch_query_search_messages.
2023-02-20lib: add better diagnostics for over long filenames.David Bremner
Previously we just crashed with an internal error. With this change, the caller can handle it better. Update notmuch-new so that it doesn't crash with "unknown error code" because of this change.
2022-12-27lib/message: move xapian call inside try/catch block in _n_m_deleteDavid Bremner
The call to delete_document can throw exceptions (and can happen in practice [1]), so catch the exception and extract the error message. As a side effect, also move the call to _n_m_has_term inside the try/catch. This should not change anything as that function already traps any Xapian exceptions. [1]: id:wwuk039sk2p.fsf@chaotikum.eu
2022-12-27lib/database: propagate status code from _notmuch_message_deleteDavid Bremner
_notmuch_message_delete can return (at least) NOTMUCH_STATUS_XAPIAN_EXCEPTION, which we should not ignore.
2022-09-03lib: add field processor for lastmod: prefixDavid Bremner
By sharing the existing logic used by the sexp query parser, this allows negative lastmod revisions to be interpreted as relative to the most recent revision.
2022-09-03lib: factor out lastmod range handling from sexp parser.David Bremner
This will permit the re-use of the same logic in the infix query parser. The location of the shared code in the infix side is for consistency with the other shared parsing logic. It will make more sense when a Xapian field processor is added for the lastmod prefix.
2022-09-03lib/sexp: provide relative lastmod queriesDavid Bremner
Test the relatively trivial logic changes for the sexp query parser first before refactoring that logic to share with the infix query parser.
2022-09-03lib/open: create database path in some casesDavid Bremner
There is some duplication of code here, but not all of the locations valid to find a database make sense to create. Furthermore we nead two passes, so the control flow in _choose_database_path would get a bit convoluted.
2022-09-03lib/open: return non-SUCCESS on missing database pathDavid Bremner
This simplifies the logic of creating the directory path when it doesn't exist.
2022-09-03lib/open: refactor call to mkdir into functionDavid Bremner
This makes the error handling available for re-use. Using g_mkdir_with_parents also handles the case of a pre-existing directory. This introduces new functionality, namely creating the parent directories, which will be useful for creating directories like '.local/share/notmuch/default'.
2022-07-01lib/sexp: add parameter expansion for regex and wildcardDavid Bremner
Fix the bug reported at [1]. The parameter expansion for regex and wildcard modifiers has to be done a bit differently, because their arguments are not s-expressions defining complete Xapian queries. [1]: id:87o7yxqxy6.fsf@code.pm
2022-06-25lib/sexp: allow * as alias for "" in range searches.David Bremner
It can be tedious to use "" inside of a string, e.g. in a shell script.
2022-06-25lib/sexp: special case "" as an argument in lastmod ranges.David Bremner
Support this syntax for constincy with (data from to) ranges.
2022-06-25lib: check for writable db in n_m_tags_maildir_flagsDavid Bremner
The database needs to be writable because the list of stored file names will change in general.
2022-06-25lib: add NOTMUCH_STATUS_CLOSED_DATABASE, use in _n_d_ensure_writableDavid Bremner
In order for a database to actually be writeable, it must be the case that it is open, not just the correct type of Xapian object. By explicitely checking, we are able to provide better error reporting, in particular for the previously broken test in T566-lib-message.
2022-06-25lib: Add missing private status values.David Bremner
These were missed when the corresponding status codes were added.
2022-06-25lib/tag: handle NULL argument to notmuch_tags_validDavid Bremner
Make the behaviour when passed NULL consistent with notmuch_filenames_valid. The library already passes the result of notmuch_message_get_tags without checking for NULL, so it should be handled.
2022-06-25lib/message: check return status from _n_m_add_{path,folder}_termsDavid Bremner
Mainly to propagate information about Xapian exceptions.
2022-06-25lib/message: check return status of _n_m_{add,remove}_termDavid Bremner
Xapian exceptions are not something that can be ignored, in general.
2022-06-25lib: define macro NODISCARDDavid Bremner
In either C++17 (or later) mode, or when running cppcheck, this can be used to selectively generate warnings about discarded return values.
2022-06-25lib/message: drop _notmuch_message_get_thread_id_onlyDavid Bremner
This function has been unused since commit 4083fd8.
2022-06-25lib/message: catch exceptions in _n_m_add_termDavid Bremner
Some code movement is needed to make sure the cache is only invalidated when the Xapian operation succeeds.
2022-05-26lib/message: use false from stdbool.hDavid Bremner
As far as I know, this is just a style / consistency thing, unless notmuch code starts defining FALSE inconsistently with false.
2022-05-26lib: fix uninitialized field in message objects.David Bremner
Initially reported by Eliza Vasquez [1] (via valgrind). [1]: id:87o7zxj086.fsf@eliza.
2022-04-15fix build without sfsexpMichael J Gruber
a1d139de ("lib: add sexp: prefix to Xapian (infix) query parser.", 2022-04-09) introduced sfsexp infix queries. This requires the infix preprocessor to be built in in a way which does not require sfsexp when notmuch is built without it. Make the preprocessor throw a Xapian error in this case (and fix the build). Signed-off-by: Michael J Gruber <git@grubix.eu>
2022-04-15lib: add sexp: prefix to Xapian (infix) query parser.David Bremner
This is analogous to the "infix" prefix provided by the s-expression based query parser.
2022-03-19lib: do not phrase parse prefixed bracketed subexpressionsDavid Bremner
Since Xapian does not preserve quotes when passing the subquery to a field processor, we have to make a guess as to what the user intended. Here the added assumption is that a string surrounded by parens is not intended to be a phrase.
2022-01-29lib: bump minor version to 6.David Bremner
One new status value and one configuration value added.
2022-01-27lib: strip trailing '/' from pathnames (sexp queries).David Bremner
This changes makes the sexp query parser consistent with the infix one in ignoring trailing '/'. Here we do a bit better and ignore any number of trailing '/'.
2022-01-27lib: drop trailing slash for path and folder searches (infix)David Bremner
This resolves an old bug reported by David Edmondson in 2014. The fix is only needed for the "boolean" case, as probabilistic / phrase searching already ignores punctuation. This fix is only for the infix (xapian provided) query parser. [1]: id:cunoasuolcv.fsf@gargravarr.hh.sledj.net
2022-01-26lib/parse-sexp: handle lastmod queries.David Bremner
This particular choice of converting strings to integers requires C++11.
2022-01-26lib/parse-sexp: support actual date queries.David Bremner
The default argument processing overlaps somewhat with what is already done in _notmuch_date_strings_to_query, but we can give more specific error messages for the s-expression context. The extra generality of _sexp_parse_range will be useful when we implement additional range prefixes (at least 'lastmod' is needed).
2022-01-26lib/date: factor out date range parsing.David Bremner
This will allow re-using the same logic in the s-expression parser.
2022-01-26lib/parse-sexp: support zero argument date queriesDavid Bremner
These are not too practical, although they may simplify some user query generation code. Mainly this adds a new prefix keyword to the parser.
2022-01-22lib/database: delete stemmer on destroyDavid Bremner
Commit [0] left the stemmer object accessible, but did not add de-allocation code to notmuch_database_destroy. This commit corrects that oversight. Leak originally reported by Austin Ray [1]. [0]: 3202e0d1feba1ab955ba1c07098c00208f8f0ada [1]: id:20220105224538.m36lnjn7rf3ieonc@athena
2022-01-22lib/config: move g_key_File_get_string before continueDavid Bremner
In [1] Austin Ray reported some memory leaks in notmuch_database_open. One of those leaks is caused by jumping to the next key without freeing val. This change avoids that leak. [1]: id:20220105224538.m36lnjn7rf3ieonc@athena
2022-01-18lib/config: add known config key "show.extra_headers"David Bremner
Used in a following commit to enable including extra headers beyond the default in structured output.
2022-01-15lib/open: no default mail root in split configurationsDavid Bremner
If we know the configuration is split, but there is no mail root defined, this indicates a (lack of) configuration error. Currently this can only arise in XDG configurations.
2022-01-15lib/config: make sure the config map exists when loading defaultsDavid Bremner
We should not rely on one of the other "_notmuch_config_load_*" functions being called before this one.
2022-01-15lib/open: use notmuch->params to track split statusDavid Bremner
Persisting this status will allow us to use the information in other compilation units, in particular when setting configuration defaults.
2022-01-15lib/open: use db struct as talloc ctx for choose_database_pathDavid Bremner
The extra talloc struct "local" was left over from before the notmuch struct was allocated earlier. Having the notmuch struct available in this function will allow more flexibility to track the configuration variations (e.g. split vs. non-split).