NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
lib.h File Reference

Header cache multiplexor. More...

#include <stdbool.h>
#include <stddef.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_raw_obj(hc, key, keylen, dst)

Typedefs

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

Functions

struct HeaderCachehcache_open (const char *path, const char *folder, hcache_namer_t namer, bool create)
 Open the connection to the header cache.
void hcache_close (struct HeaderCache **ptr)
 Close the connection to the header cache.
int hcache_store_email (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_email (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_raw_str (struct HeaderCache *hc, const char *key, size_t keylen)
 Fetch a string from the cache.
bool hcache_fetch_raw_obj_full (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_email (struct HeaderCache *hc, const char *key, size_t keylen)
 Delete a key / data pair.
int hcache_delete_raw (struct HeaderCache *hc, const char *key, size_t keylen)
 Delete a key / data pair.

Detailed Description

Header cache multiplexor.

Authors
  • Richard Russon
  • 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_raw_obj

#define hcache_fetch_raw_obj ( hc,
key,
keylen,
dst )
Value:
hcache_fetch_raw_obj_full(hc, key, keylen, dst, sizeof(*(dst)))
bool hcache_fetch_raw_obj_full(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.
Definition hcache.c:650

Definition at line 168 of file lib.h.

Typedef Documentation

◆ hcache_namer_t

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

Definition at line 119 of file lib.h.

Function Documentation

◆ hcache_open()

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

Open the connection to the header cache.

Multiplexor for StoreOps::open.

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.
createCreate the file if it's not there?
Return values
ptrSuccess, struct HeaderCache struct
NULLOtherwise

Open the connection to the header cache.

Definition at line 492 of file hcache.c.

494{
495 if (!path || (path[0] == '\0'))
496 return NULL;
497
499 if (mod_data->hcache_ver == 0x0)
500 mod_data->hcache_ver = generate_hcachever();
501
502 struct HeaderCache *hc = hcache_new();
503
505 hc->crc = mod_data->hcache_ver;
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), create);
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), create);
545 }
546 }
547
548 if (!hc->store_handle)
549 {
550 if (hc->compr_ops)
551 {
552 hc->compr_ops->close(&hc->compr_handle);
553 }
554 hcache_free(&hc);
555 }
556
557 buf_pool_release(&hcpath);
558 return hc;
559}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition compress.c:78
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition hcache.c:106
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition hcache.c:121
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition hcache.c:450
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:374
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition hcache.c:427
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ MODULE_ID_HCACHE
ModuleHcache, Email Header Cache
Definition module_api.h:68
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:88
String manipulation buffer.
Definition buffer.h:36
ComprHandle *(* open)(short level)
Definition lib.h:79
const char * name
Compression name.
Definition lib.h:66
void(* close)(ComprHandle **ptr)
Definition lib.h:125
Hcache private Module data.
Definition module_data.h:30
unsigned int hcache_ver
Header Cache version.
Definition module_data.h:32
Header Cache.
Definition lib.h:87
ComprHandle * compr_handle
Compression handle.
Definition lib.h:93
unsigned int crc
CRC of the cache entry.
Definition lib.h:89
char * folder
Folder name.
Definition lib.h:88
const struct StoreOps * store_ops
Store backend.
Definition lib.h:90
StoreHandle * store_handle
Store handle.
Definition lib.h:91
const struct ComprOps * compr_ops
Compression backend.
Definition lib.h:92
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
StoreHandle *(* open)(const char *path, bool create)
Definition lib.h:83
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.

Multiplexor for StoreOps::close.

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 564 of file hcache.c.

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

◆ hcache_store_email()

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

Store a Header along with a validity datum.

Multiplexor for StoreOps::store.

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 703 of file hcache.c.

705{
706 if (!hc)
707 return -1;
708
709 int dlen = 0;
710 char *data = dump_email(hc, e, &dlen, uidvalidity);
711
712#ifdef USE_HCACHE_COMPRESSION
713 if (hc->compr_ops)
714 {
715 /* We don't compress uidvalidity and the crc, so we can check them before
716 * decompressing on fetch(). */
717 size_t hlen = header_size();
718
719 /* data / dlen gets ptr to compressed data here */
720 size_t clen = dlen;
721 void *cdata = hc->compr_ops->compress(hc->compr_handle, data + hlen, dlen - hlen, &clen);
722 if (!cdata)
723 {
724 FREE(&data);
725 return -1;
726 }
727
728 char *whole = MUTT_MEM_MALLOC(hlen + clen, char);
729 memcpy(whole, data, hlen);
730 memcpy(whole + hlen, cdata, clen);
731
732 FREE(&data);
733
734 data = whole;
735 dlen = hlen + clen;
736 }
737#endif
738
739 struct RealKey *rk = realkey(hc, key, keylen, true);
740 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
741
742 FREE(&data);
743
744 return rc;
745}
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition hcache.c:230
static struct RealKey * realkey(struct HeaderCache *hc, const char *key, size_t keylen, bool compress)
Compute the real key used in the backend, taking into account the compression method.
Definition hcache.c:78
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition hcache.c:130
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition lib.h:96
Hcache key name (including compression method).
Definition hcache.c:65
char key[1024]
Key name.
Definition hcache.c:66
size_t keylen
Length of key.
Definition hcache.c:67
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition lib.h:122
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hcache_fetch_email()

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

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

Multiplexor for StoreOps::fetch.

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 584 of file hcache.c.

586{
587 struct HCacheEntry hce = { 0 };
588 if (!hc)
589 return hce;
590
591 size_t dlen = 0;
592 struct RealKey *rk = realkey(hc, key, keylen, true);
593 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
594 void *to_free = data;
595 if (!data)
596 {
597 goto end;
598 }
599
600 /* restore uidvalidity and crc */
601 size_t hlen = header_size();
602 if (hlen > dlen)
603 {
604 goto end;
605 }
606 int off = 0;
607 if (!serial_restore_uint32_t(&hce.uidvalidity, data, &off, dlen) ||
608 !serial_restore_int(&hce.crc, data, &off, dlen))
609 {
610 goto end;
611 }
612 ASSERT((size_t) off == hlen);
613 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
614 {
615 goto end;
616 }
617
618#ifdef USE_HCACHE_COMPRESSION
619 if (hc->compr_ops)
620 {
621 size_t ulen = 0;
622 void *dblob = hc->compr_ops->decompress(hc->compr_handle, (char *) data + hlen,
623 dlen - hlen, &ulen);
624 if (!dblob)
625 {
626 goto end;
627 }
628 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
629 dlen = hlen + ulen;
630 }
631#endif
632
633 hce.email = restore_email(data, dlen);
634
635end:
636 free_raw(hc, &to_free);
637 return hce;
638}
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition hcache.c:441
static struct Email * restore_email(const unsigned char *d, size_t dlen)
Restore an Email from data retrieved from the cache.
Definition hcache.c:272
bool serial_restore_uint32_t(uint32_t *s, const unsigned char *d, int *off, size_t dlen)
Unpack an uint32_t from a binary blob.
Definition serialize.c:159
bool serial_restore_int(unsigned int *i, const unsigned char *d, int *off, size_t dlen)
Unpack an integer from a binary blob.
Definition serialize.c:140
#define ASSERT(COND)
Definition signal2.h:59
void *(* decompress)(ComprHandle *handle, const char *cbuf, size_t clen, size_t *dlen)
Definition lib.h:113
Wrapper for Email retrieved from the header cache.
Definition lib.h:100
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition lib.h:101
struct Email * email
Retrieved email.
Definition lib.h:103
unsigned int crc
CRC of Email/Body/etc structs.
Definition lib.h:102
void *(* fetch)(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Definition lib.h:97
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hcache_fetch_raw_str()

char * hcache_fetch_raw_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 682 of file hcache.c.

683{
684 if (!hc)
685 return NULL;
686
687 char *res = NULL;
688 size_t dlen = 0;
689
690 struct RealKey *rk = realkey(hc, key, keylen, false);
691 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
692 if (data)
693 {
694 res = mutt_strn_dup(data, dlen);
695 free_raw(hc, &data);
696 }
697 return res;
698}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:384
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hcache_fetch_raw_obj_full()

bool hcache_fetch_raw_obj_full ( 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 650 of file hcache.c.

652{
653 if (!hc)
654 return false;
655
656 bool rc = true;
657 size_t srclen = 0;
658
659 struct RealKey *rk = realkey(hc, key, keylen, false);
660 void *src = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &srclen);
661
662 if (src && (srclen == dstlen))
663 {
664 memcpy(dst, src, dstlen);
665 }
666 else
667 {
668 rc = false;
669 }
670 free_raw(hc, &src);
671 return rc;
672}
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 757 of file hcache.c.

759{
760 if (!hc)
761 return -1;
762
763 struct RealKey *rk = realkey(hc, key, keylen, false);
764 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
765
766 return rc;
767}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hcache_delete_email()

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

Delete a key / data pair.

Multiplexor for StoreOps::delete_record.

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 772 of file hcache.c.

773{
774 if (!hc)
775 return -1;
776
777 struct RealKey *rk = realkey(hc, key, keylen, true);
778
779 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
780}
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition lib.h:135
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hcache_delete_raw()

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

Delete a key / data pair.

Multiplexor for StoreOps::delete_record.

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 785 of file hcache.c.

786{
787 if (!hc)
788 return -1;
789
790 struct RealKey *rk = realkey(hc, key, keylen, false);
791
792 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
793}
Here is the call graph for this function:
Here is the caller graph for this function: