NeoMutt  2020-09-25
Teaching an old dog new tricks
DOXYGEN
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 "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "mutt_globals.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. More...
 
notmuch_database_t * nm_db_do_open (const char *filename, bool writable, bool verbose)
 Open a Notmuch database. More...
 
notmuch_database_t * nm_db_get (struct Mailbox *m, bool writable)
 Get the Notmuch database. More...
 
int nm_db_release (struct Mailbox *m)
 Close the Notmuch database. More...
 
void nm_db_free (notmuch_database_t *db)
 decoupled way to close a Notmuch database More...
 
int nm_db_trans_begin (struct Mailbox *m)
 Start a Notmuch database transaction. More...
 
int nm_db_trans_end (struct Mailbox *m)
 End a database transaction. More...
 
int nm_db_get_mtime (struct Mailbox *m, time_t *mtime)
 Get the database modification time. More...
 
bool nm_db_is_longrun (struct Mailbox *m)
 Is Notmuch in the middle of a long-running transaction. More...
 
void nm_db_longrun_init (struct Mailbox *m, bool writable)
 Start a long transaction. More...
 
void nm_db_longrun_done (struct Mailbox *m)
 Finish a long transaction. More...
 
void nm_db_debug_check (struct Mailbox *m)
 Check if the database is open. More...
 

Detailed Description

Notmuch database handling.

Authors
  • Richard Russon

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 C_NmDefaultUrl global variable. If that variable changes, the result will be invalid. It must not be freed.

Definition at line 53 of file db.c.

54 {
55  struct NmMboxData *mdata = nm_mdata_get(m);
56  char *db_filename = NULL;
57 
58  if (mdata && mdata->db_url && mdata->db_url->path)
59  db_filename = mdata->db_url->path;
60  else
61  db_filename = C_NmDefaultUrl;
62 
63  if (!db_filename && !C_Folder)
64  return NULL;
65 
66  if (!db_filename)
67  db_filename = C_Folder;
68 
69  if (nm_path_probe(db_filename, NULL) == MUTT_NOTMUCH)
70  db_filename += NmUrlProtocolLen;
71 
72  mutt_debug(LL_DEBUG2, "nm: db filename '%s'\n", db_filename);
73  return db_filename;
74 }
Log at debug level 2.
Definition: logging.h:41
Notmuch-specific Mailbox data -.
Definition: private.h:69
char * C_NmDefaultUrl
Config: (notmuch) Path to the Notmuch database.
Definition: config.c:38
void * mdata
Driver specific data.
Definition: mailbox.h:136
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
enum MailboxType nm_path_probe(const char *path, const struct stat *st)
Is this a Notmuch Mailbox? - Implements MxOps::path_probe()
Definition: notmuch.c:2610
struct Url * db_url
Parsed view url of the Notmuch database.
Definition: private.h:71
char * path
Path.
Definition: url.h:73
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: notmuch.c:235
const int NmUrlProtocolLen
Definition: notmuch.c:82
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ 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 83 of file db.c.

84 {
85  notmuch_database_t *db = NULL;
86  int ct = 0;
87  notmuch_status_t st = NOTMUCH_STATUS_SUCCESS;
88 #if LIBNOTMUCH_CHECK_VERSION(4, 2, 0)
89  char *msg = NULL;
90 #endif
91 
92  mutt_debug(LL_DEBUG1, "nm: db open '%s' %s (timeout %d)\n", filename,
93  writable ? "[WRITE]" : "[READ]", C_NmOpenTimeout);
94 
95  const notmuch_database_mode_t mode =
96  writable ? NOTMUCH_DATABASE_MODE_READ_WRITE : NOTMUCH_DATABASE_MODE_READ_ONLY;
97 
98  do
99  {
100 #if LIBNOTMUCH_CHECK_VERSION(4, 2, 0)
101  st = notmuch_database_open_verbose(filename, mode, &db, &msg);
102 #elif defined(NOTMUCH_API_3)
103  st = notmuch_database_open(filename, mode, &db);
104 #else
105  db = notmuch_database_open(filename, mode);
106 #endif
107  if ((st == NOTMUCH_STATUS_FILE_ERROR) || db || !C_NmOpenTimeout || ((ct / 2) > C_NmOpenTimeout))
108  break;
109 
110  if (verbose && ct && ((ct % 2) == 0))
111  mutt_error(_("Waiting for notmuch DB... (%d sec)"), ct / 2);
112  mutt_date_sleep_ms(500000); /* Half a second */
113  ct++;
114  } while (true);
115 
116  if (verbose)
117  {
118  if (!db)
119  {
120 #if LIBNOTMUCH_CHECK_VERSION(4, 2, 0)
121  if (msg)
122  {
123  mutt_error(msg);
124  FREE(&msg);
125  }
126  else
127 #endif
128  {
129  mutt_error(_("Can't open notmuch database: %s: %s"), filename,
130  st ? notmuch_status_to_string(st) : _("unknown reason"));
131  }
132  }
133  else if (ct > 1)
134  {
136  }
137  }
138  return db;
139 }
int C_NmOpenTimeout
Config: (notmuch) Database timeout.
Definition: config.c:41
#define _(a)
Definition: message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool verbose
Display status messages?
Definition: mailbox.h:118
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void mutt_date_sleep_ms(size_t ms)
Sleep for milliseconds.
Definition: date.c:693
+ 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 147 of file db.c.

148 {
149  struct NmAccountData *adata = nm_adata_get(m);
150 
151  if (!adata)
152  return NULL;
153 
154  // Use an existing open db if we have one.
155  if (adata->db)
156  return adata->db;
157 
158  const char *db_filename = nm_db_get_filename(m);
159  if (db_filename)
160  adata->db = nm_db_do_open(db_filename, writable, true);
161 
162  return adata->db;
163 }
notmuch_database_t * nm_db_do_open(const char *filename, bool writable, bool verbose)
Open a Notmuch database.
Definition: db.c:83
notmuch_database_t * db
Definition: private.h:50
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Notmuch-specific Account data -.
Definition: private.h:48
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition: db.c:53
+ 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 171 of file db.c.

172 {
173  struct NmAccountData *adata = nm_adata_get(m);
174  if (!adata || !adata->db || nm_db_is_longrun(m))
175  return -1;
176 
177  mutt_debug(LL_DEBUG1, "nm: db close\n");
178  nm_db_free(adata->db);
179  adata->db = NULL;
180  adata->longrun = false;
181  return 0;
182 }
bool longrun
A long-lived action is in progress.
Definition: private.h:51
notmuch_database_t * db
Definition: private.h:50
bool nm_db_is_longrun(struct Mailbox *m)
Is Notmuch in the middle of a long-running transaction.
Definition: db.c:275
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void nm_db_free(notmuch_database_t *db)
decoupled way to close a Notmuch database
Definition: db.c:188
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 188 of file db.c.

189 {
190 #ifdef NOTMUCH_API_3
191  notmuch_database_destroy(db);
192 #else
193  notmuch_database_close(db);
194 #endif
195 }
notmuch_database_t * db
Definition: private.h:50
+ 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 204 of file db.c.

205 {
206  struct NmAccountData *adata = nm_adata_get(m);
207  if (!adata || !adata->db)
208  return -1;
209 
210  if (adata->trans)
211  return 0;
212 
213  mutt_debug(LL_DEBUG2, "nm: db trans start\n");
214  if (notmuch_database_begin_atomic(adata->db))
215  return -1;
216  adata->trans = true;
217  return 1;
218 }
notmuch_database_t * db
Definition: private.h:50
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
Log at debug level 2.
Definition: logging.h:41
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
bool trans
Atomic transaction in progress.
Definition: private.h:52
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 226 of file db.c.

227 {
228  struct NmAccountData *adata = nm_adata_get(m);
229  if (!adata || !adata->db)
230  return -1;
231 
232  if (!adata->trans)
233  return 0;
234 
235  mutt_debug(LL_DEBUG2, "nm: db trans end\n");
236  adata->trans = false;
237  if (notmuch_database_end_atomic(adata->db))
238  return -1;
239 
240  return 0;
241 }
notmuch_database_t * db
Definition: private.h:50
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
Log at debug level 2.
Definition: logging.h:41
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
bool trans
Atomic transaction in progress.
Definition: private.h:52
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 253 of file db.c.

254 {
255  if (!m || !mtime)
256  return -1;
257 
258  char path[PATH_MAX];
259  snprintf(path, sizeof(path), "%s/.notmuch/xapian", nm_db_get_filename(m));
260  mutt_debug(LL_DEBUG2, "nm: checking '%s' mtime\n", path);
261 
262  struct stat st;
263  if (stat(path, &st) != 0)
264  return -1;
265 
266  *mtime = st.st_mtime;
267  return 0;
268 }
Log at debug level 2.
Definition: logging.h:41
#define PATH_MAX
Definition: mutt.h:44
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
const char * nm_db_get_filename(struct Mailbox *m)
Get the filename of the Notmuch database.
Definition: db.c:53
+ 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
trueif it is

Definition at line 275 of file db.c.

276 {
277  struct NmAccountData *adata = nm_adata_get(m);
278  if (!adata)
279  return false;
280 
281  return adata->longrun;
282 }
bool longrun
A long-lived action is in progress.
Definition: private.h:51
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 289 of file db.c.

290 {
291  struct NmAccountData *adata = nm_adata_get(m);
292 
293  if (!(adata && nm_db_get(m, writable)))
294  return;
295 
296  adata->longrun = true;
297  mutt_debug(LL_DEBUG2, "nm: long run initialized\n");
298 }
bool longrun
A long-lived action is in progress.
Definition: private.h:51
notmuch_database_t * nm_db_get(struct Mailbox *m, bool writable)
Get the Notmuch database.
Definition: db.c:147
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
Log at debug level 2.
Definition: logging.h:41
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 304 of file db.c.

305 {
306  struct NmAccountData *adata = nm_adata_get(m);
307 
308  if (adata)
309  {
310  adata->longrun = false; /* to force nm_db_release() released DB */
311  if (nm_db_release(m) == 0)
312  mutt_debug(LL_DEBUG2, "nm: long run deinitialized\n");
313  else
314  adata->longrun = true;
315  }
316 }
bool longrun
A long-lived action is in progress.
Definition: private.h:51
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
Log at debug level 2.
Definition: logging.h:41
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:171
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ 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 322 of file db.c.

323 {
324  struct NmAccountData *adata = nm_adata_get(m);
325  if (!adata || !adata->db)
326  return;
327 
328  mutt_debug(LL_DEBUG1, "nm: ERROR: db is open, closing\n");
329  nm_db_release(m);
330 }
notmuch_database_t * db
Definition: private.h:50
struct NmAccountData * nm_adata_get(struct Mailbox *m)
Get the Notmuch Account data.
Definition: notmuch.c:168
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Log at debug level 1.
Definition: logging.h:40
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:171
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Notmuch-specific Account data -.
Definition: private.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function: