NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Header cache multiplexor. More...

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "compress/lib.h"
#include "store/lib.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HeaderCache
 Header Cache. More...
 
struct  HCacheEntry
 Wrapper for Email retrieved from the header cache. More...
 

Macros

#define hcache_fetch_obj(hc, key, keylen, dst)   hcache_fetch_obj_(hc, key, keylen, dst, sizeof(*dst))
 

Typedefs

typedef void(* hcache_namer_t) (const char *path, struct Buffer *dest)
 

Functions

struct HeaderCachehcache_open (const char *path, const char *folder, hcache_namer_t namer)
 Open the connection to the header cache.
 
void hcache_close (struct HeaderCache **ptr)
 Close the connection to the header cache.
 
int hcache_store (struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Store a Header along with a validity datum.
 
struct HCacheEntry hcache_fetch (struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Fetch and validate a message's header from the cache.
 
char * hcache_fetch_str (struct HeaderCache *hc, const char *key, size_t keylen)
 Fetch a string from the cache.
 
bool hcache_fetch_obj_ (struct HeaderCache *hc, const char *key, size_t keylen, void *dst, size_t dstlen)
 Fetch a message's header from the cache into a destination object.
 
int hcache_store_raw (struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
 Store a key / data pair.
 
int hcache_delete_record (struct HeaderCache *hc, const char *key, size_t keylen)
 Delete a key / data pair.
 

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 lib.h.

Macro Definition Documentation

◆ hcache_fetch_obj

#define hcache_fetch_obj (   hc,
  key,
  keylen,
  dst 
)    hcache_fetch_obj_(hc, key, keylen, dst, sizeof(*dst))

Definition at line 164 of file lib.h.

Typedef Documentation

◆ hcache_namer_t

typedef void(* hcache_namer_t) (const char *path, struct Buffer *dest)

Definition at line 115 of file lib.h.

Function Documentation

◆ hcache_open()

struct HeaderCache * hcache_open ( const char *  path,
const char *  folder,
hcache_namer_t  namer 
)

Open the connection to the header cache.

Parameters
pathLocation of the header cache (often as specified by the user)
folderName of the folder containing the messages
namerOptional (might be NULL) client-specific function to form the final name of the hcache database file.
Return values
ptrSuccess, struct HeaderCache struct
NULLOtherwise

Open the connection to the header cache.

Definition at line 494 of file hcache.c.

495{
496 if (!path || (path[0] == '\0'))
497 return NULL;
498
499 if (HcacheVer == 0x0)
501
502 struct HeaderCache *hc = hcache_new();
503
505 hc->crc = HcacheVer;
506
507 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
508 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
509 if (!hc->store_ops)
510 {
511 hcache_free(&hc);
512 return NULL;
513 }
514
515#ifdef USE_HCACHE_COMPRESSION
516 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
517 if (c_header_cache_compress_method)
518 {
519 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
520
521 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
522 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
523 if (!hc->compr_handle)
524 {
525 hcache_free(&hc);
526 return NULL;
527 }
528
529 /* remember the buffer of database backend */
530 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
531 hc->compr_ops->name);
532 }
533#endif
534
535 struct Buffer *hcpath = buf_pool_get();
536 hcache_per_folder(hc, hcpath, path, namer);
537
538 hc->store_handle = hc->store_ops->open(buf_string(hcpath));
539 if (!hc->store_handle)
540 {
541 /* remove a possibly incompatible version */
542 if (unlink(buf_string(hcpath)) == 0)
543 {
544 hc->store_handle = hc->store_ops->open(buf_string(hcpath));
545 if (!hc->store_handle)
546 {
547 if (hc->compr_ops)
548 {
549 hc->compr_ops->close(&hc->compr_handle);
550 }
551 hcache_free(&hc);
552 }
553 }
554 }
555
556 buf_pool_release(&hcpath);
557 return hc;
558}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:79
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static unsigned int HcacheVer
Header Cache version.
Definition: hcache.c:64
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition: hcache.c:70
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition: hcache.c:85
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition: hcache.c:455
static void hcache_per_folder(struct HeaderCache *hc, struct Buffer *hcpath, const char *path, hcache_namer_t namer)
Generate the hcache pathname.
Definition: hcache.c:356
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:408
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:106
String manipulation buffer.
Definition: buffer.h:34
ComprHandle *(* open)(short level)
Definition: lib.h:77
const char * name
Compression name.
Definition: lib.h:64
void(* close)(ComprHandle **ptr)
Definition: lib.h:122
Header Cache.
Definition: lib.h:88
ComprHandle * compr_handle
Compression handle.
Definition: lib.h:94
unsigned int crc
CRC of the cache entry.
Definition: lib.h:90
char * folder
Folder name.
Definition: lib.h:89
const struct StoreOps * store_ops
Store backend.
Definition: lib.h:91
StoreHandle * store_handle
Store handle.
Definition: lib.h:92
const struct ComprOps * compr_ops
Compression backend.
Definition: lib.h:93
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
StoreHandle *(* open)(const char *path)
Definition: lib.h:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_close()

void hcache_close ( struct HeaderCache **  ptr)

Close the connection to the header cache.

Parameters
ptrPointer to the struct HeaderCache structure got by hcache_open()
Note
The pointer will be set to NULL

Close the connection to the header cache.

Definition at line 563 of file hcache.c.

564{
565 if (!ptr || !*ptr)
566 return;
567
568 struct HeaderCache *hc = *ptr;
569
570#ifdef USE_HCACHE_COMPRESSION
571 if (hc->compr_ops)
572 hc->compr_ops->close(&hc->compr_handle);
573#endif
574
575 hc->store_ops->close(&hc->store_handle);
576
577 hcache_free(ptr);
578}
void(* close)(StoreHandle **ptr)
Definition: lib.h:146
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_store()

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

Store a Header along with a validity datum.

Parameters
hcPointer to the struct HeaderCache structure got by hcache_open()
keyMessage identification string
keylenLength of the key string
eEmail to store
uidvalidityIMAP-specific UIDVALIDITY value, or 0 to use the current time
Return values
0Success
numGeneric or backend-specific error code otherwise

Store a Header along with a validity datum.

Definition at line 686 of file hcache.c.

688{
689 if (!hc)
690 return -1;
691
692 int dlen = 0;
693 char *data = dump_email(hc, e, &dlen, uidvalidity);
694
695#ifdef USE_HCACHE_COMPRESSION
696 if (hc->compr_ops)
697 {
698 /* We don't compress uidvalidity and the crc, so we can check them before
699 * decompressing on fetch(). */
700 size_t hlen = header_size();
701
702 /* data / dlen gets ptr to compressed data here */
703 size_t clen = dlen;
704 void *cdata = hc->compr_ops->compress(hc->compr_handle, data + hlen, dlen - hlen, &clen);
705 if (!cdata)
706 {
707 FREE(&data);
708 return -1;
709 }
710
711 char *whole = mutt_mem_malloc(hlen + clen);
712 memcpy(whole, data, hlen);
713 memcpy(whole + hlen, cdata, clen);
714
715 FREE(&data);
716
717 data = whole;
718 dlen = hlen + clen;
719 }
720#endif
721
722 /* store uncompressed data */
723 struct RealKey *rk = realkey(hc, key, keylen);
724 int rc = hcache_store_raw(hc, rk->key, rk->len, data, dlen);
725
726 FREE(&data);
727
728 return rc;
729}
static struct RealKey * realkey(struct HeaderCache *hc, const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:289
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:194
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:94
int hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
Store a key / data pair.
Definition: hcache.c:741
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:45
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:94
Hcache key name (including compression method)
Definition: hcache.c:277
char key[1024]
Key name.
Definition: hcache.c:278
size_t len
Length of key.
Definition: hcache.c:279
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_fetch()

struct HCacheEntry hcache_fetch ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
uint32_t  uidvalidity 
)

Fetch and validate a message's header from the cache.

Parameters
hcPointer to the struct HeaderCache structure got by hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
uidvalidityOnly restore if it matches the stored uidvalidity
Return values
objHCacheEntry containing an Email, empty on failure
Note
This function performs a check on the validity of the data found by comparing it with the crc value of the struct HeaderCache structure.

Fetch and validate a message's header from the cache.

Definition at line 583 of file hcache.c.

585{
586 struct HCacheEntry hce = { 0 };
587 if (!hc)
588 return hce;
589
590 size_t dlen = 0;
591 struct RealKey *rk = realkey(hc, key, keylen);
592 void *data = fetch_raw(hc, rk->key, rk->len, &dlen);
593 void *to_free = data;
594 if (!data)
595 {
596 goto end;
597 }
598
599 /* restore uidvalidity and crc */
600 size_t hlen = header_size();
601 if (hlen > dlen)
602 {
603 goto end;
604 }
605 int off = 0;
606 serial_restore_uint32_t(&hce.uidvalidity, data, &off);
607 serial_restore_int(&hce.crc, data, &off);
608 assert((size_t) off == hlen);
609 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
610 {
611 goto end;
612 }
613
614#ifdef USE_HCACHE_COMPRESSION
615 if (hc->compr_ops)
616 {
617 void *dblob = hc->compr_ops->decompress(hc->compr_handle,
618 (char *) data + hlen, dlen - hlen);
619 if (!dblob)
620 {
621 goto end;
622 }
623 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
624 }
625#endif
626
627 hce.email = restore_email(data);
628
629end:
630 free_raw(hc, &to_free);
631 return hce;
632}
static struct Email * restore_email(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:234
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:446
static void * fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:431
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:115
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:127
void *(* decompress)(ComprHandle *handle, const char *cbuf, size_t clen)
Definition: lib.h:110
Wrapper for Email retrieved from the header cache.
Definition: lib.h:101
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:102
struct Email * email
Retrieved email.
Definition: lib.h:104
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_fetch_str()

char * hcache_fetch_str ( struct HeaderCache hc,
const char *  key,
size_t  keylen 
)

Fetch a string from the cache.

Parameters
[in]hcPointer to the struct HeaderCache structure got by hcache_open()
[in]keyMessage identification string
[in]keylenLength of the string pointed to by key
Return values
ptrSuccess, the data if found
NULLOtherwise

Definition at line 670 of file hcache.c.

671{
672 char *res = NULL;
673 size_t dlen = 0;
674 void *data = fetch_raw(hc, key, keylen, &dlen);
675 if (data)
676 {
677 res = mutt_strn_dup(data, dlen);
678 free_raw(hc, &data);
679 }
680 return res;
681}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:452
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_fetch_obj_()

bool hcache_fetch_obj_ ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
void *  dst,
size_t  dstlen 
)

Fetch a message's header from the cache into a destination object.

Parameters
[in]hcPointer to the struct HeaderCache structure got by hcache_open()
[in]keyMessage identification string
[in]keylenLength of the string pointed to by key
[out]dstPointer to the destination object
[in]dstlenSize of the destination object
Return values
trueSuccess, the data was found and the length matches
falseOtherwise

Definition at line 644 of file hcache.c.

646{
647 bool rc = true;
648 size_t srclen = 0;
649 void *src = fetch_raw(hc, key, keylen, &srclen);
650 if (src && (srclen == dstlen))
651 {
652 memcpy(dst, src, dstlen);
653 }
654 else
655 {
656 rc = false;
657 }
658 free_raw(hc, &src);
659 return rc;
660}
+ Here is the call graph for this function:

◆ hcache_store_raw()

int hcache_store_raw ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
void *  data,
size_t  dlen 
)

Store a key / data pair.

Parameters
hcPointer to the struct HeaderCache structure got by 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 741 of file hcache.c.

743{
744 if (!hc)
745 return -1;
746
747 struct Buffer path = buf_make(1024);
748
749 keylen = buf_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
750 int rc = hc->store_ops->store(hc->store_handle, buf_string(&path), keylen, data, dlen);
751 buf_dealloc(&path);
752
753 return rc;
754}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:389
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
char * data
Pointer to data.
Definition: buffer.h:35
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition: lib.h:124
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_delete_record()

int hcache_delete_record ( struct HeaderCache hc,
const char *  key,
size_t  keylen 
)

Delete a key / data pair.

Parameters
hcPointer to the struct HeaderCache structure got by hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
Return values
0Success
numGeneric or backend-specific error code otherwise

Delete a key / data pair.

Definition at line 759 of file hcache.c.

760{
761 if (!hc)
762 return -1;
763
764 struct Buffer path = buf_make(1024);
765
766 keylen = buf_printf(&path, "%s%s", hc->folder, key);
767
768 int rc = hc->store_ops->delete_record(hc->store_handle, buf_string(&path), keylen);
769 buf_dealloc(&path);
770 return rc;
771}
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition: lib.h:137
+ Here is the call graph for this function:
+ Here is the caller graph for this function: