NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
hcache.c File Reference

Header cache multiplexor. More...

#include "config.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "email/lib.h"
#include "lib.h"
#include "hcache/hcversion.h"
#include "muttlib.h"
#include "serialize.h"
#include "compress/lib.h"
#include "store/lib.h"
+ Include dependency graph for hcache.c:

Go to the source code of this file.

Data Structures

struct  RealKey
 

Macros

#define hcache_get_ops()   store_get_backend_ops(C_HeaderCacheBackend)
 
#define compr_get_ops()   compress_get_ops(C_HeaderCacheCompressMethod)
 

Functions

static size_t header_size (void)
 Compute the size of the header with uuid validity and crc. More...
 
static void * dump (header_cache_t *hc, const struct Email *e, int *off, uint32_t uidvalidity)
 Serialise an Email object. More...
 
static struct Emailrestore (const unsigned char *d)
 Restore an Email from data retrieved from the cache. More...
 
static struct RealKeyrealkey (const char *key, size_t keylen)
 Compute the real key used in the backend, taking into account the compression method. More...
 
static bool create_hcache_dir (const char *path)
 Create parent dirs for the hcache database. More...
 
static void hcache_per_folder (struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
 Generate the hcache pathname. More...
 
static char * get_foldername (const char *folder)
 Where should the cache be stored? More...
 
header_cache_tmutt_hcache_open (const char *path, const char *folder, hcache_namer_t namer)
 Multiplexor for StoreOps::open. More...
 
void mutt_hcache_close (header_cache_t *hc)
 Multiplexor for StoreOps::close. More...
 
struct HCacheEntry mutt_hcache_fetch (header_cache_t *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Multiplexor for StoreOps::fetch. More...
 
void * mutt_hcache_fetch_raw (header_cache_t *hc, const char *key, size_t keylen, size_t *dlen)
 Fetch a message's header from the cache. More...
 
void mutt_hcache_free_raw (header_cache_t *hc, void **data)
 Multiplexor for StoreOps::free. More...
 
int mutt_hcache_store (header_cache_t *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Multiplexor for StoreOps::store. More...
 
int mutt_hcache_store_raw (header_cache_t *hc, const char *key, size_t keylen, void *data, size_t dlen)
 store a key / data pair More...
 
int mutt_hcache_delete_header (header_cache_t *hc, const char *key, size_t keylen)
 Multiplexor for StoreOps::delete_header. More...
 

Variables

static unsigned int hcachever = 0x0
 

Detailed Description

Header cache multiplexor.

Authors
  • Thomas Glanzmann
  • Tobias Werth
  • Brian Fundakowski Feldman
  • Pietro Cerutti
  • Tino Reichardt

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 hcache.c.

Macro Definition Documentation

◆ hcache_get_ops

#define hcache_get_ops ( )    store_get_backend_ops(C_HeaderCacheBackend)

Definition at line 63 of file hcache.c.

◆ compr_get_ops

#define compr_get_ops ( )    compress_get_ops(C_HeaderCacheCompressMethod)

Definition at line 66 of file hcache.c.

Function Documentation

◆ header_size()

static size_t header_size ( void  )
static

Compute the size of the header with uuid validity and crc.

Definition at line 73 of file hcache.c.

74 {
75  return sizeof(int) + sizeof(uint32_t);
76 }
+ Here is the caller graph for this function:

◆ dump()

static void* dump ( header_cache_t hc,
const struct Email e,
int *  off,
uint32_t  uidvalidity 
)
static

Serialise an Email object.

Parameters
hcHeader cache handle
eEmail to serialise
offSize of the binary blob
uidvalidityIMAP server identifier
Return values
ptrBinary blob representing the Email

This function transforms an Email into a binary string so that it can be saved to a database.

Definition at line 89 of file hcache.c.

90 {
91  struct Email e_dump;
92  bool convert = !CharsetIsUtf8;
93 
94  *off = 0;
95  unsigned char *d = mutt_mem_malloc(4096);
96 
97  d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch(), d, off);
98  d = serial_dump_int(hc->crc, d, off);
99 
100  assert((size_t) *off == header_size());
101 
102  lazy_realloc(&d, *off + sizeof(struct Email));
103  memcpy(&e_dump, e, sizeof(struct Email));
104 
105  /* some fields are not safe to cache */
106  e_dump.tagged = false;
107  e_dump.changed = false;
108  e_dump.threaded = false;
109  e_dump.recip_valid = false;
110  e_dump.searched = false;
111  e_dump.matched = false;
112  e_dump.collapsed = false;
113  e_dump.limited = false;
114  e_dump.num_hidden = 0;
115  e_dump.recipient = 0;
116  e_dump.pair = 0;
117  e_dump.attach_valid = false;
118  e_dump.path = NULL;
119  e_dump.tree = NULL;
120  e_dump.thread = NULL;
121  STAILQ_INIT(&e_dump.tags);
122 #ifdef MIXMASTER
123  STAILQ_INIT(&e_dump.chain);
124 #endif
125  e_dump.edata = NULL;
126 
127  memcpy(d + *off, &e_dump, sizeof(struct Email));
128  *off += sizeof(struct Email);
129 
130  d = serial_dump_envelope(e_dump.env, d, off, convert);
131  d = serial_dump_body(e_dump.content, d, off, convert);
132  d = serial_dump_char(e_dump.maildir_flags, d, off, convert);
133 
134  return d;
135 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
The envelope/body of an email.
Definition: email.h:37
unsigned char * serial_dump_envelope(struct Envelope *env, unsigned char *d, int *off, bool convert)
Pack an Envelope into a binary blob.
Definition: serialize.c:487
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:73
unsigned char * serial_dump_uint32_t(uint32_t s, unsigned char *d, int *off)
Pack a uint32_t into a binary blob.
Definition: serialize.c:81
#define STAILQ_INIT(head)
Definition: queue.h:369
unsigned int crc
Definition: lib.h:88
unsigned char * serial_dump_int(unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition: serialize.c:65
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
unsigned char * serial_dump_char(char *c, unsigned char *d, int *off, bool convert)
Pack a variable-length string into a binary blob.
Definition: serialize.c:163
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:63
void lazy_realloc(void *ptr, size_t size)
Reallocate some memory.
Definition: serialize.c:48
unsigned char * serial_dump_body(struct Body *c, unsigned char *d, int *off, bool convert)
Pack an Body into a binary blob.
Definition: serialize.c:421
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ restore()

static struct Email* restore ( const unsigned char *  d)
static

Restore an Email from data retrieved from the cache.

Parameters
dData retrieved using mutt_hcache_dump
Return values
ptrSuccess, the restored header (can't be NULL)
Note
The returned Email must be free'd by caller code with email_free()

Definition at line 145 of file hcache.c.

146 {
147  int off = 0;
148  struct Email *e = email_new();
149  bool convert = !CharsetIsUtf8;
150 
151  /* skip validate */
152  off += sizeof(uint32_t);
153 
154  /* skip crc */
155  off += sizeof(unsigned int);
156 
157  memcpy(e, d + off, sizeof(struct Email));
158  off += sizeof(struct Email);
159 
160  STAILQ_INIT(&e->tags);
161 #ifdef MIXMASTER
162  STAILQ_INIT(&e->chain);
163 #endif
164 
165  e->env = mutt_env_new();
166  serial_restore_envelope(e->env, d, &off, convert);
167 
168  e->content = mutt_body_new();
169  serial_restore_body(e->content, d, &off, convert);
170 
171  serial_restore_char(&e->maildir_flags, d, &off, convert);
172 
173  return e;
174 }
The envelope/body of an email.
Definition: email.h:37
void serial_restore_body(struct Body *c, const unsigned char *d, int *off, bool convert)
Unpack a Body from a binary blob.
Definition: serialize.c:461
struct Body * content
List of MIME parts.
Definition: email.h:90
void serial_restore_char(char **c, const unsigned char *d, int *off, bool convert)
Unpack a variable-length string from a binary blob.
Definition: serialize.c:175
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
#define STAILQ_INIT(head)
Definition: queue.h:369
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
struct TagList tags
For drivers that support server tagging.
Definition: email.h:102
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:63
char * maildir_flags
Unknown maildir flags.
Definition: email.h:104
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
void serial_restore_envelope(struct Envelope *env, const unsigned char *d, int *off, bool convert)
Unpack an Envelope from a binary blob.
Definition: serialize.c:535
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ realkey()

static struct RealKey* realkey ( const char *  key,
size_t  keylen 
)
static

Compute the real key used in the backend, taking into account the compression method.

Parameters
keyOriginal key
keylenLength of original key
Return values
ptrStatic location holding data and length of the real key

Definition at line 188 of file hcache.c.

189 {
190  static struct RealKey rk;
191 #ifdef USE_HCACHE_COMPRESSION
193  {
194  rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, compr_get_ops()->name);
195  }
196  else
197 #endif
198  {
199  memcpy(rk.key, key, keylen + 1); // Including NUL byte
200  rk.len = keylen;
201  }
202  return &rk;
203 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
size_t len
Definition: hcache.c:179
char key[1024]
Definition: hcache.c:178
#define compr_get_ops()
Definition: hcache.c:66
+ Here is the caller graph for this function:

◆ create_hcache_dir()

static bool create_hcache_dir ( const char *  path)
static

Create parent dirs for the hcache database.

Parameters
pathDatabase filename
Return values
trueSuccess
falseFailure (errno set)

Definition at line 211 of file hcache.c.

212 {
213  char *dir = mutt_str_dup(path);
214  if (!dir)
215  return false;
216 
217  char *p = strrchr(dir, '/');
218  if (!p)
219  {
220  FREE(&dir);
221  return true;
222  }
223 
224  *p = '\0';
225 
226  int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
227  if (rc != 0)
228  mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
229 
230  FREE(&dir);
231  return (rc == 0);
232 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:875
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_per_folder()

static void hcache_per_folder ( struct Buffer hcpath,
const char *  path,
const char *  folder,
hcache_namer_t  namer 
)
static

Generate the hcache pathname.

Parameters
hcpathBuffer for the result
pathBase directory, from $header_cache
folderMailbox name (including protocol)
namerCallback to generate database filename - Implements hcache_namer_t
Return values
ptrFull pathname to the database (to be generated) (path must be freed by the caller)

Generate the pathname for the hcache database, it will be of the form: BASE/FOLDER/NAME

  • BASE: Base directory (path)
  • FOLDER: Mailbox name (folder)
  • NAME: Create by namer, or md5sum of folder

This function will create any parent directories needed, so the caller just needs to create the database file.

If path exists and is a directory, it is used. If path has a trailing '/' it is assumed to be a directory. Otherwise path is assumed to be a file.

Definition at line 257 of file hcache.c.

259 {
260  struct stat sb;
261 
262  int plen = mutt_str_len(path);
263  int rc = stat(path, &sb);
264  bool slash = (path[plen - 1] == '/');
265 
266  if (((rc == 0) && !S_ISDIR(sb.st_mode)) || ((rc == -1) && !slash))
267  {
268  /* An existing file or a non-existing path not ending with a slash */
269  mutt_encode_path(hcpath, path);
270  return;
271  }
272 
273  /* We have a directory - no matter whether it exists, or not */
274  struct Buffer *hcfile = mutt_buffer_pool_get();
275  if (namer)
276  {
277  namer(folder, hcfile);
278  mutt_buffer_concat_path(hcpath, path, mutt_b2s(hcfile));
279  }
280  else
281  {
282  unsigned char m[16]; /* binary md5sum */
283  struct Buffer *name = mutt_buffer_pool_get();
284 #ifdef USE_HCACHE_COMPRESSION
285  const char *cm = C_HeaderCacheCompressMethod;
286  mutt_buffer_printf(name, "%s|%s%s", hcache_get_ops()->name, folder, cm ? cm : "");
287 #else
288  mutt_buffer_printf(name, "%s|%s", hcache_get_ops()->name, folder);
289 #endif
290  mutt_md5(mutt_b2s(name), m);
291  mutt_buffer_reset(name);
292  mutt_md5_toascii(m, name->data);
293  mutt_buffer_printf(hcpath, "%s%s%s", path, slash ? "" : "/", mutt_b2s(name));
295  }
296 
297  mutt_encode_path(hcpath, mutt_b2s(hcpath));
298  create_hcache_dir(mutt_b2s(hcpath));
299  mutt_buffer_pool_release(&hcfile);
300 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:211
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:456
#define mutt_b2s(buf)
Definition: buffer.h:41
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NULL-terminated string.
Definition: md5.c:317
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
#define hcache_get_ops()
Definition: hcache.c:63
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to &#39;us-ascii&#39;.
Definition: muttlib.c:1474
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_foldername()

static char* get_foldername ( const char *  folder)
static

Where should the cache be stored?

Parameters
folderPath to be canonicalised
Return values
ptrNew string with canonical path

Definition at line 307 of file hcache.c.

308 {
309  /* if the folder is local, canonify the path to avoid
310  * to ensure equivalent paths share the hcache */
311  char *p = mutt_mem_malloc(PATH_MAX + 1);
312  if (!realpath(folder, p))
313  mutt_str_replace(&p, folder);
314 
315  return p;
316 }
#define PATH_MAX
Definition: mutt.h:44
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_open()

header_cache_t* mutt_hcache_open ( const char *  path,
const char *  folder,
hcache_namer_t  namer 
)

Multiplexor for StoreOps::open.

open the connection to the header cache

Definition at line 321 of file hcache.c.

322 {
323  const struct StoreOps *ops = hcache_get_ops();
324  if (!ops)
325  return NULL;
326 
328 
329  /* Calculate the current hcache version from dynamic configuration */
330  if (hcachever == 0x0)
331  {
332  union
333  {
334  unsigned char charval[16];
335  unsigned int intval;
336  } digest;
337  struct Md5Ctx md5ctx;
338 
339  hcachever = HCACHEVER;
340 
341  mutt_md5_init_ctx(&md5ctx);
342 
343  /* Seed with the compiled-in header structure hash */
344  mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &md5ctx);
345 
346  /* Mix in user's spam list */
347  struct Replace *sp = NULL;
348  STAILQ_FOREACH(sp, &SpamList, entries)
349  {
350  mutt_md5_process(sp->regex->pattern, &md5ctx);
351  mutt_md5_process(sp->templ, &md5ctx);
352  }
353 
354  /* Mix in user's nospam list */
355  struct RegexNode *np = NULL;
356  STAILQ_FOREACH(np, &NoSpamList, entries)
357  {
358  mutt_md5_process(np->regex->pattern, &md5ctx);
359  }
360 
361  /* Get a hash and take its bytes as an (unsigned int) hash version */
362  mutt_md5_finish_ctx(&md5ctx, digest.charval);
363  hcachever = digest.intval;
364  }
365 
366 #ifdef USE_HCACHE_COMPRESSION
368  {
369  const struct ComprOps *cops = compr_get_ops();
370 
371  hc->cctx = cops->open(C_HeaderCacheCompressLevel);
372  if (!hc->cctx)
373  {
374  FREE(&hc);
375  return NULL;
376  }
377 
378  /* remember the buffer of database backend */
379  mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
380  }
381 #endif
382 
383  hc->folder = get_foldername(folder);
384  hc->crc = hcachever;
385 
386  if (!path || (path[0] == '\0'))
387  {
388  FREE(&hc->folder);
389  FREE(&hc);
390  return NULL;
391  }
392 
393  struct Buffer *hcpath = mutt_buffer_pool_get();
394  hcache_per_folder(hcpath, path, hc->folder, namer);
395 
396  hc->ctx = ops->open(mutt_b2s(hcpath));
397  if (!hc->ctx)
398  {
399  /* remove a possibly incompatible version */
400  if (unlink(mutt_b2s(hcpath)) == 0)
401  {
402  hc->ctx = ops->open(mutt_b2s(hcpath));
403  if (!hc->ctx)
404  {
405  FREE(&hc->folder);
406  FREE(&hc);
407  }
408  }
409  }
410 
411  mutt_buffer_pool_release(&hcpath);
412  return hc;
413 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
char * templ
Template to match.
Definition: regex3.h:112
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Cursor for the MD5 hashing.
Definition: md5.h:36
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-terminated string.
Definition: md5.c:355
String manipulation buffer.
Definition: buffer.h:33
char * folder
Definition: lib.h:87
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:262
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:307
Key Value Store API.
Definition: lib.h:61
const char * name
Compression name.
Definition: lib.h:57
List of regular expressions.
Definition: regex3.h:108
void * cctx
Definition: lib.h:90
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:110
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:286
short C_HeaderCacheCompressLevel
Config: (hcache) Level of compression for method.
Definition: config.c:40
void *(* open)(const char *path)
Open a connection to a Store.
Definition: lib.h:75
unsigned int crc
Definition: lib.h:88
#define mutt_b2s(buf)
Definition: buffer.h:41
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:43
static void hcache_per_folder(struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
Generate the hcache pathname.
Definition: hcache.c:257
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:100
static unsigned int hcachever
Definition: hcache.c:61
void *(* open)(short level)
Open a compression context.
Definition: lib.h:67
void * ctx
Definition: lib.h:89
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
List of regular expressions.
Definition: regex3.h:98
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:44
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:373
Header Cache Compression API.
Definition: lib.h:55
#define FREE(x)
Definition: memory.h:40
#define compr_get_ops()
Definition: hcache.c:66
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
char * pattern
printable version
Definition: regex3.h:90
header cache structure
Definition: lib.h:85
#define hcache_get_ops()
Definition: hcache.c:63
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_close()

void mutt_hcache_close ( header_cache_t hc)

Multiplexor for StoreOps::close.

close the connection to the header cache

Definition at line 418 of file hcache.c.

419 {
420  const struct StoreOps *ops = hcache_get_ops();
421  if (!hc || !ops)
422  return;
423 
424 #ifdef USE_HCACHE_COMPRESSION
426  compr_get_ops()->close(&hc->cctx);
427 #endif
428 
429  ops->close(&hc->ctx);
430  FREE(&hc->folder);
431  FREE(&hc);
432 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
char * folder
Definition: lib.h:87
Key Value Store API.
Definition: lib.h:61
void * cctx
Definition: lib.h:90
void(* close)(void **ptr)
Close a Store connection.
Definition: lib.h:121
void * ctx
Definition: lib.h:89
#define FREE(x)
Definition: memory.h:40
#define compr_get_ops()
Definition: hcache.c:66
#define hcache_get_ops()
Definition: hcache.c:63
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch()

struct HCacheEntry mutt_hcache_fetch ( header_cache_t hc,
const char *  key,
size_t  keylen,
uint32_t  uidvalidity 
)

Multiplexor for StoreOps::fetch.

fetch and validate a message's header from the cache

Definition at line 437 of file hcache.c.

439 {
440  struct RealKey *rk = realkey(key, keylen);
441  struct HCacheEntry entry = { 0 };
442 
443  size_t dlen;
444  void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
445  void *to_free = data;
446  if (!data)
447  {
448  goto end;
449  }
450 
451  /* restore uidvalidity and crc */
452  size_t hlen = header_size();
453  int off = 0;
454  serial_restore_uint32_t(&entry.uidvalidity, data, &off);
455  serial_restore_int(&entry.crc, data, &off);
456  assert((size_t) off == hlen);
457  if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
458  {
459  goto end;
460  }
461 
462 #ifdef USE_HCACHE_COMPRESSION
464  {
465  const struct ComprOps *cops = compr_get_ops();
466 
467  void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
468  if (!dblob)
469  {
470  goto end;
471  }
472  data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
473  }
474 #endif
475 
476  entry.email = restore(data);
477 
478 end:
479  mutt_hcache_free_raw(hc, &to_free);
480  return entry;
481 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:188
Wrapper for Email retrieved from the header cache.
Definition: lib.h:98
size_t len
Definition: hcache.c:179
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:73
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:100
void * mutt_hcache_fetch_raw(header_cache_t *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:495
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:96
void * cctx
Definition: lib.h:90
void serial_restore_uint32_t(uint32_t *s, const unsigned char *d, int *off)
Unpack an uint32_t from a binary blob.
Definition: serialize.c:108
char key[1024]
Definition: hcache.c:178
unsigned int crc
Definition: lib.h:88
Header Cache Compression API.
Definition: lib.h:55
void mutt_hcache_free_raw(header_cache_t *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:512
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:101
#define compr_get_ops()
Definition: hcache.c:66
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Decompress header cache data.
Definition: lib.h:94
struct Email * email
Retrieved email.
Definition: lib.h:102
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch_raw()

void* mutt_hcache_fetch_raw ( header_cache_t hc,
const char *  key,
size_t  keylen,
size_t *  dlen 
)

Fetch a message's header from the cache.

Parameters
[in]hcPointer to the header_cache_t structure got by mutt_hcache_open()
[in]keyMessage identification string
[in]keylenLength of the string pointed to by key
[out]dlenLength of the fetched data
Return values
ptrSuccess, the data if found
NULLOtherwise
Note
This function does not perform any check on the validity of the data found.
The returned data must be free with mutt_hcache_free_raw().

Definition at line 495 of file hcache.c.

496 {
497  const struct StoreOps *ops = hcache_get_ops();
498 
499  if (!hc || !ops)
500  return NULL;
501 
502  struct Buffer path = mutt_buffer_make(1024);
503  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
504  void *blob = ops->fetch(hc->ctx, mutt_b2s(&path), keylen, dlen);
505  mutt_buffer_dealloc(&path);
506  return blob;
507 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
char * folder
Definition: lib.h:87
Key Value Store API.
Definition: lib.h:61
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Fetch a Value from the Store.
Definition: lib.h:86
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_b2s(buf)
Definition: buffer.h:41
void * ctx
Definition: lib.h:89
#define hcache_get_ops()
Definition: hcache.c:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_free_raw()

void mutt_hcache_free_raw ( header_cache_t hc,
void **  data 
)

Multiplexor for StoreOps::free.

free data fetched with mutt_hcache_fetch_raw()

Definition at line 512 of file hcache.c.

513 {
514  const struct StoreOps *ops = hcache_get_ops();
515 
516  if (!hc || !ops || !data || !*data)
517  return;
518 
519  ops->free(hc->ctx, data);
520 }
Key Value Store API.
Definition: lib.h:61
void * ctx
Definition: lib.h:89
void(* free)(void *store, void **ptr)
Free a Value returned by fetch()
Definition: lib.h:93
#define hcache_get_ops()
Definition: hcache.c:63
+ Here is the caller graph for this function:

◆ mutt_hcache_store()

int mutt_hcache_store ( header_cache_t hc,
const char *  key,
size_t  keylen,
struct Email e,
uint32_t  uidvalidity 
)

Multiplexor for StoreOps::store.

store a Header along with a validity datum

Definition at line 525 of file hcache.c.

527 {
528  if (!hc)
529  return -1;
530 
531  int dlen = 0;
532  char *data = dump(hc, e, &dlen, uidvalidity);
533 
534 #ifdef USE_HCACHE_COMPRESSION
536  {
537  /* We don't compress uidvalidity and the crc, so we can check them before
538  * decompressing on fetch(). */
539  size_t hlen = header_size();
540 
541  const struct ComprOps *cops = compr_get_ops();
542 
543  /* data / dlen gets ptr to compressed data here */
544  size_t clen = dlen;
545  void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
546  if (!cdata)
547  {
548  FREE(&data);
549  return -1;
550  }
551 
552  char *whole = mutt_mem_malloc(hlen + clen);
553  memcpy(whole, data, hlen);
554  memcpy(whole + hlen, cdata, clen);
555 
556  FREE(&data);
557 
558  data = whole;
559  dlen = hlen + clen;
560  }
561 #endif
562 
563  /* store uncompressed data */
564  struct RealKey *rk = realkey(key, keylen);
565  int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
566 
567  FREE(&data);
568 
569  return rc;
570 }
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:188
static void * dump(header_cache_t *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:89
size_t len
Definition: hcache.c:179
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:73
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Compress header cache data.
Definition: lib.h:81
int mutt_hcache_store_raw(header_cache_t *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:582
void * cctx
Definition: lib.h:90
char key[1024]
Definition: hcache.c:178
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
Header Cache Compression API.
Definition: lib.h:55
#define FREE(x)
Definition: memory.h:40
#define compr_get_ops()
Definition: hcache.c:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store_raw()

int mutt_hcache_store_raw ( header_cache_t hc,
const char *  key,
size_t  keylen,
void *  data,
size_t  dlen 
)

store a key / data pair

Parameters
hcPointer to the header_cache_t structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
dataPayload to associate with key
dlenLength of the buffer pointed to by the data parameter
Return values
0Success
numGeneric or backend-specific error code otherwise

Definition at line 582 of file hcache.c.

584 {
585  const struct StoreOps *ops = hcache_get_ops();
586 
587  if (!hc || !ops)
588  return -1;
589 
590  struct Buffer path = mutt_buffer_make(1024);
591 
592  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
593  int rc = ops->store(hc->ctx, mutt_b2s(&path), keylen, data, dlen);
594  mutt_buffer_dealloc(&path);
595 
596  return rc;
597 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
char * folder
Definition: lib.h:87
Key Value Store API.
Definition: lib.h:61
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Write a Value to the Store.
Definition: lib.h:105
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_b2s(buf)
Definition: buffer.h:41
char * data
Pointer to data.
Definition: buffer.h:35
void * ctx
Definition: lib.h:89
#define hcache_get_ops()
Definition: hcache.c:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_delete_header()

int mutt_hcache_delete_header ( header_cache_t hc,
const char *  key,
size_t  keylen 
)

Multiplexor for StoreOps::delete_header.

delete a key / data pair

Definition at line 602 of file hcache.c.

603 {
604  const struct StoreOps *ops = hcache_get_ops();
605  if (!hc)
606  return -1;
607 
608  struct Buffer path = mutt_buffer_make(1024);
609 
610  keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
611 
612  int rc = ops->delete_record(hc->ctx, mutt_b2s(&path), keylen);
613  mutt_buffer_dealloc(&path);
614  return rc;
615 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
char * folder
Definition: lib.h:87
Key Value Store API.
Definition: lib.h:61
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_b2s(buf)
Definition: buffer.h:41
void * ctx
Definition: lib.h:89
int(* delete_record)(void *store, const char *key, size_t klen)
Delete a record from the Store.
Definition: lib.h:115
#define hcache_get_ops()
Definition: hcache.c:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ hcachever

unsigned int hcachever = 0x0
static

Definition at line 61 of file hcache.c.