NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
db.c File Reference

Notmuch database handling. More...

#include "config.h"
#include <limits.h>
#include <notmuch.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "adata.h"
#include "mdata.h"
#include "mutt_logging.h"
+ Include dependency graph for db.c:

Go to the source code of this file.

Functions

const char * nm_db_get_filename (struct Mailbox *m)
 Get the filename of the Notmuch database.
 
notmuch_database_t * nm_db_do_open (const char *filename, bool writable, bool verbose)
 Open a Notmuch database.
 
notmuch_database_t * nm_db_get (struct Mailbox *m, bool writable)
 Get the Notmuch database.
 
int nm_db_release (struct Mailbox *m)
 Close the Notmuch database.
 
void nm_db_free (notmuch_database_t *db)
 Decoupled way to close a Notmuch database.
 
int nm_db_trans_begin (struct Mailbox *m)
 Start a Notmuch database transaction.
 
int nm_db_trans_end (struct Mailbox *m)
 End a database transaction.
 
int nm_db_get_mtime (struct Mailbox *m, time_t *mtime)
 Get the database modification time.
 
bool nm_db_is_longrun (struct Mailbox *m)
 Is Notmuch in the middle of a long-running transaction.
 
void nm_db_longrun_init (struct Mailbox *m, bool writable)
 Start a long transaction.
 
void nm_db_longrun_done (struct Mailbox *m)
 Finish a long transaction.
 
void nm_db_debug_check (struct Mailbox *m)
 Check if the database is open.
 

Detailed Description

Notmuch database handling.

Authors
  • Richard Russon
  • Austin Ray
  • Ian Zimmerman
  • Karel Zak

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/.

Definition in file db.c.

Function Documentation

◆ nm_db_get_filename()

const char * nm_db_get_filename ( struct Mailbox m)

Get the filename of the Notmuch database.

Parameters
mMailbox
Return values
ptrFilename
Note
The return value is a pointer into the $nm_default_url global variable. If that variable changes, the result will be invalid. It must not be freed.

Definition at line 58 of file db.c.

59{
60 struct NmMboxData *mdata = nm_mdata_get(m);
61 const char *db_filename = NULL;
62
63 const char *const c_nm_default_url = cs_subset_string(NeoMutt->sub, "nm_default_url");
64 if (mdata && mdata->db_url && mdata->db_url->path)
65 db_filename = mdata->db_url->path;
66 else
67 db_filename = c_nm_default_url;
68
69 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
70 if (!db_filename && !c_folder)
71 return NULL;
72
73 if (!db_filename)
74 db_filename = c_folder;
75
76 if (nm_path_probe(db_filename, NULL) == MUTT_NOTMUCH)
77 db_filename += NmUrlProtocolLen;
78
79 mutt_debug(LL_DEBUG2, "nm: db filename '%s'\n", db_filename);
80 return db_filename;
81}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
enum MailboxType nm_path_probe(const char *path, const struct stat *st)
Is this a Notmuch Mailbox? - Implements MxOps::path_probe() -.
Definition: notmuch.c:2457
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:96
const int NmUrlProtocolLen
Length of NmUrlProtocol string.
Definition: notmuch.c:103
void * mdata
Driver specific data.
Definition: mailbox.h:132
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
Notmuch-specific Mailbox data -.
Definition: mdata.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_do_open()

notmuch_database_t * nm_db_do_open ( const char *  filename,
bool  writable,
bool  verbose 
)

Open a Notmuch database.

Parameters
filenameDatabase filename
writableRead/write?
verboseShow errors on failure?
Return values
ptrNotmuch database

Definition at line 115 of file db.c.

116{
117 notmuch_database_t *db = NULL;
118 int ct = 0;
119 notmuch_status_t st = NOTMUCH_STATUS_SUCCESS;
120 char *msg = NULL;
121
122 const short c_nm_open_timeout = cs_subset_number(NeoMutt->sub, "nm_open_timeout");
123 mutt_debug(LL_DEBUG1, "nm: db open '%s' %s (timeout %d)\n", filename,
124 writable ? "[WRITE]" : "[READ]", c_nm_open_timeout);
125
126 const notmuch_database_mode_t mode = writable ? NOTMUCH_DATABASE_MODE_READ_WRITE :
127 NOTMUCH_DATABASE_MODE_READ_ONLY;
128
129 do
130 {
131#if LIBNOTMUCH_CHECK_VERSION(5, 4, 0)
132 // notmuch 0.32-0.32.2 didn't bump libnotmuch version to 5.4.
133 const char *config_file = get_nm_config_file();
134 const char *const c_nm_config_profile = cs_subset_string(NeoMutt->sub, "nm_config_profile");
135
136 FREE(&msg);
137 st = notmuch_database_open_with_config(filename, mode, config_file,
138 c_nm_config_profile, &db, &msg);
139
140 // Attempt opening database without configuration file. Don't if the user specified no config.
141 if ((st == NOTMUCH_STATUS_NO_CONFIG) && !mutt_str_equal(config_file, ""))
142 {
143 mutt_debug(LL_DEBUG1, "nm: Could not find notmuch configuration file: %s\n", config_file);
144 mutt_debug(LL_DEBUG1, "nm: Attempting to open notmuch db without configuration file\n");
145
146 FREE(&msg);
147
148 st = notmuch_database_open_with_config(filename, mode, "", NULL, &db, &msg);
149 }
150 else if ((st == NOTMUCH_STATUS_NO_CONFIG) && !config_file)
151 {
152 FREE(&msg);
153 }
154#elif LIBNOTMUCH_CHECK_VERSION(4, 2, 0)
155 st = notmuch_database_open_verbose(filename, mode, &db, &msg);
156#elif defined(NOTMUCH_API_3)
157 st = notmuch_database_open(filename, mode, &db);
158#else
159 db = notmuch_database_open(filename, mode);
160#endif
161 if ((st == NOTMUCH_STATUS_FILE_ERROR) || db || !c_nm_open_timeout ||
162 ((ct / 2) > c_nm_open_timeout))
163 {
164 break;
165 }
166
167 if (verbose && ct && ((ct % 2) == 0))
168 mutt_error(_("Waiting for notmuch DB... (%d sec)"), ct / 2);
169 mutt_date_sleep_ms(500); /* Half a second */
170 ct++;
171 } while (true);
172
173 if (st != NOTMUCH_STATUS_SUCCESS)
174 {
175 db = NULL;
176 }
177
178 if (verbose)
179 {
180 if (!db)
181 {
182 if (msg)
183 {
184 mutt_error("%s", msg);
185 }
186 else
187 {
188 mutt_error(_("Can't open notmuch database: %s: %s"), filename,
189 st ? notmuch_status_to_string(st) : _("unknown reason"));
190 }
191 }
192 else if (ct > 1)
193 {
195 }
196 }
197
198 FREE(&msg);
199
200 return db;
201}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
#define mutt_error(...)
Definition: logging2.h:92
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define FREE(x)
Definition: memory.h:55
void mutt_date_sleep_ms(size_t ms)
Sleep for milliseconds.
Definition: date.c:983
#define _(a)
Definition: message.h:28
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_get()

notmuch_database_t * nm_db_get ( struct Mailbox m,
bool  writable 
)

Get the Notmuch database.

Parameters
mMailbox
writableRead/write?
Return values
ptrNotmuch database

Definition at line 209 of file db.c.

210{
211 struct NmAccountData *adata = nm_adata_get(m);
212
213 if (!adata)
214 return NULL;
215
216 // Use an existing open db if we have one.
217 if (adata->db)
218 return adata->db;
219
220 const char *db_filename = nm_db_get_filename(m);
221 if (db_filename)
222 adata->db = nm_db_do_open(db_filename, writable, true);
223
224 return adata->db;
225}
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: adata.c:69
notmuch_database_t * nm_db_do_open(const char *filename, bool writable, bool verbose)
Open a Notmuch database.
Definition: db.c:115
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition: db.c:58
void * adata
Private data (for Mailbox backends)
Definition: account.h:42
Notmuch-specific Account data -.
Definition: adata.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_release()

int nm_db_release ( struct Mailbox m)

Close the Notmuch database.

Parameters
mMailbox
Return values
0Success
-1Failure

Definition at line 233 of file db.c.

234{
235 struct NmAccountData *adata = nm_adata_get(m);
236 if (!adata || !adata->db || nm_db_is_longrun(m))
237 return -1;
238
239 mutt_debug(LL_DEBUG1, "nm: db close\n");
240 nm_db_free(adata->db);
241 adata->db = NULL;
242 adata->longrun = false;
243 return 0;
244}
bool nm_db_is_longrun(struct Mailbox *m)
Is Notmuch in the middle of a long-running transaction.
Definition: db.c:350
void nm_db_free(notmuch_database_t *db)
Decoupled way to close a Notmuch database.
Definition: db.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_free()

void nm_db_free ( notmuch_database_t *  db)

Decoupled way to close a Notmuch database.

Parameters
dbNotmuch database

Definition at line 250 of file db.c.

251{
252#ifdef NOTMUCH_API_3
253 notmuch_database_destroy(db);
254#else
255 notmuch_database_close(db);
256#endif
257}
+ Here is the caller graph for this function:

◆ nm_db_trans_begin()

int nm_db_trans_begin ( struct Mailbox m)

Start a Notmuch database transaction.

Parameters
mMailbox
Return values
<0error
1new transaction started
0already within transaction

Definition at line 266 of file db.c.

267{
268 struct NmAccountData *adata = nm_adata_get(m);
269 if (!adata || !adata->db)
270 return -1;
271
272 if (adata->trans)
273 return 0;
274
275 mutt_debug(LL_DEBUG2, "nm: db trans start\n");
276 if (notmuch_database_begin_atomic(adata->db))
277 return -1;
278 adata->trans = true;
279 return 1;
280}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_trans_end()

int nm_db_trans_end ( struct Mailbox m)

End a database transaction.

Parameters
mMailbox
Return values
0Success
-1Failure

Definition at line 288 of file db.c.

289{
290 struct NmAccountData *adata = nm_adata_get(m);
291 if (!adata || !adata->db)
292 return -1;
293
294 if (!adata->trans)
295 return 0;
296
297 mutt_debug(LL_DEBUG2, "nm: db trans end\n");
298 adata->trans = false;
299 if (notmuch_database_end_atomic(adata->db))
300 return -1;
301
302 return 0;
303}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_get_mtime()

int nm_db_get_mtime ( struct Mailbox m,
time_t *  mtime 
)

Get the database modification time.

Parameters
[in]mMailbox
[out]mtimeSave the modification time
Return values
0Success (result in mtime)
-1Error

Get the "mtime" (modification time) of the database file. This is the time of the last update.

Definition at line 315 of file db.c.

316{
317 if (!m || !mtime)
318 return -1;
319
320 struct stat st = { 0 };
321 char path[PATH_MAX] = { 0 };
322 const char *db_filename = nm_db_get_filename(m);
323
324 mutt_debug(LL_DEBUG2, "nm: checking database mtime '%s'\n", db_filename);
325
326 // See if the path we were given has a Xapian directory.
327 // After notmuch 0.32, a .notmuch folder isn't guaranteed.
328 snprintf(path, sizeof(path), "%s/xapian", db_filename);
329 if (stat(path, &st) == 0)
330 {
331 *mtime = st.st_mtime;
332 return 0;
333 }
334
335 // Otherwise, check for a .notmuch directory.
336 snprintf(path, sizeof(path), "%s/.notmuch/xapian", db_filename);
337
338 if (stat(path, &st) != 0)
339 return -1;
340
341 *mtime = st.st_mtime;
342 return 0;
343}
#define PATH_MAX
Definition: mutt.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_is_longrun()

bool nm_db_is_longrun ( struct Mailbox m)

Is Notmuch in the middle of a long-running transaction.

Parameters
mMailbox
Return values
trueNotmuch is in the middle of a long-running transaction

Definition at line 350 of file db.c.

351{
352 struct NmAccountData *adata = nm_adata_get(m);
353 if (!adata)
354 return false;
355
356 return adata->longrun;
357}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_longrun_init()

void nm_db_longrun_init ( struct Mailbox m,
bool  writable 
)

Start a long transaction.

Parameters
mMailbox
writableRead/write?

Definition at line 364 of file db.c.

365{
366 struct NmAccountData *adata = nm_adata_get(m);
367
368 if (!(adata && nm_db_get(m, writable)))
369 return;
370
371 adata->longrun = true;
372 mutt_debug(LL_DEBUG2, "nm: long run initialized\n");
373}
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:209
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_longrun_done()

void nm_db_longrun_done ( struct Mailbox m)

Finish a long transaction.

Parameters
mMailbox

Definition at line 379 of file db.c.

380{
381 struct NmAccountData *adata = nm_adata_get(m);
382
383 if (adata)
384 {
385 adata->longrun = false; /* to force nm_db_release() released DB */
386 if (nm_db_release(m) == 0)
387 mutt_debug(LL_DEBUG2, "nm: long run deinitialized\n");
388 else
389 adata->longrun = true;
390 }
391}
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:233
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nm_db_debug_check()

void nm_db_debug_check ( struct Mailbox m)

Check if the database is open.

Parameters
mMailbox

Definition at line 397 of file db.c.

398{
399 struct NmAccountData *adata = nm_adata_get(m);
400 if (!adata || !adata->db)
401 return;
402
403 mutt_debug(LL_DEBUG1, "nm: ERROR: db is open, closing\n");
404 nm_db_release(m);
405}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: