NeoMutt  2025-09-05-55-g97fc89
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 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:625

Definition at line 162 of file lib.h.

Typedef Documentation

◆ hcache_namer_t

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

Definition at line 113 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.

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

475{
476 if (!path || (path[0] == '\0'))
477 return NULL;
478
479 if (HcacheVer == 0x0)
481
482 struct HeaderCache *hc = hcache_new();
483
485 hc->crc = HcacheVer;
486
487 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
488 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
489 if (!hc->store_ops)
490 {
491 hcache_free(&hc);
492 return NULL;
493 }
494
495#ifdef USE_HCACHE_COMPRESSION
496 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
497 if (c_header_cache_compress_method)
498 {
499 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
500
501 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
502 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
503 if (!hc->compr_handle)
504 {
505 hcache_free(&hc);
506 return NULL;
507 }
508
509 /* remember the buffer of database backend */
510 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
511 hc->compr_ops->name);
512 }
513#endif
514
515 struct Buffer *hcpath = buf_pool_get();
516 hcache_per_folder(hc, hcpath, path, namer);
517
518 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
519 if (!hc->store_handle)
520 {
521 /* remove a possibly incompatible version */
522 if (unlink(buf_string(hcpath)) == 0)
523 {
524 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
525 }
526 }
527
528 if (!hc->store_handle)
529 {
530 if (hc->compr_ops)
531 {
532 hc->compr_ops->close(&hc->compr_handle);
533 }
534 hcache_free(&hc);
535 }
536
537 buf_pool_release(&hcpath);
538 return hc;
539}
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:90
static unsigned int HcacheVer
Header Cache version.
Definition hcache.c:63
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition hcache.c:105
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition hcache.c:120
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition hcache.c:434
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:358
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition hcache.c:411
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:104
String manipulation buffer.
Definition buffer.h:36
ComprHandle *(* open)(short level)
Definition lib.h:78
const char * name
Compression name.
Definition lib.h:65
void(* close)(ComprHandle **ptr)
Definition lib.h:123
Header Cache.
Definition lib.h:86
ComprHandle * compr_handle
Compression handle.
Definition lib.h:92
unsigned int crc
CRC of the cache entry.
Definition lib.h:88
char * folder
Folder name.
Definition lib.h:87
const struct StoreOps * store_ops
Store backend.
Definition lib.h:89
StoreHandle * store_handle
Store handle.
Definition lib.h:90
const struct ComprOps * compr_ops
Compression backend.
Definition lib.h:91
Container for Accounts, Notifications.
Definition neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
StoreHandle *(* open)(const char *path, bool create)
Definition lib.h:86
+ 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 544 of file hcache.c.

545{
546 if (!ptr || !*ptr)
547 return;
548
549 struct HeaderCache *hc = *ptr;
550
551#ifdef USE_HCACHE_COMPRESSION
552 if (hc->compr_ops)
553 hc->compr_ops->close(&hc->compr_handle);
554#endif
555
556 hc->store_ops->close(&hc->store_handle);
557
558 hcache_free(ptr);
559}
void(* close)(StoreHandle **ptr)
Definition lib.h:147
+ 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.

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

674{
675 if (!hc)
676 return -1;
677
678 int dlen = 0;
679 char *data = dump_email(hc, e, &dlen, uidvalidity);
680
681#ifdef USE_HCACHE_COMPRESSION
682 if (hc->compr_ops)
683 {
684 /* We don't compress uidvalidity and the crc, so we can check them before
685 * decompressing on fetch(). */
686 size_t hlen = header_size();
687
688 /* data / dlen gets ptr to compressed data here */
689 size_t clen = dlen;
690 void *cdata = hc->compr_ops->compress(hc->compr_handle, data + hlen, dlen - hlen, &clen);
691 if (!cdata)
692 {
693 FREE(&data);
694 return -1;
695 }
696
697 char *whole = MUTT_MEM_MALLOC(hlen + clen, char);
698 memcpy(whole, data, hlen);
699 memcpy(whole + hlen, cdata, clen);
700
701 FREE(&data);
702
703 data = whole;
704 dlen = hlen + clen;
705 }
706#endif
707
708 struct RealKey *rk = realkey(hc, key, keylen, true);
709 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
710
711 FREE(&data);
712
713 return rc;
714}
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition hcache.c:229
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:82
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition hcache.c:129
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:48
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition lib.h:95
Hcache key name (including compression method)
Definition hcache.c:69
char key[1024]
Key name.
Definition hcache.c:70
size_t keylen
Length of key.
Definition hcache.c:71
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition lib.h:125
+ 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.

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

566{
567 struct HCacheEntry hce = { 0 };
568 if (!hc)
569 return hce;
570
571 size_t dlen = 0;
572 struct RealKey *rk = realkey(hc, key, keylen, true);
573 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
574 void *to_free = data;
575 if (!data)
576 {
577 goto end;
578 }
579
580 /* restore uidvalidity and crc */
581 size_t hlen = header_size();
582 if (hlen > dlen)
583 {
584 goto end;
585 }
586 int off = 0;
587 serial_restore_uint32_t(&hce.uidvalidity, data, &off);
588 serial_restore_int(&hce.crc, data, &off);
589 ASSERT((size_t) off == hlen);
590 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
591 {
592 goto end;
593 }
594
595#ifdef USE_HCACHE_COMPRESSION
596 if (hc->compr_ops)
597 {
598 void *dblob = hc->compr_ops->decompress(hc->compr_handle,
599 (char *) data + hlen, dlen - hlen);
600 if (!dblob)
601 {
602 goto end;
603 }
604 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
605 }
606#endif
607
608 hce.email = restore_email(data);
609
610end:
611 free_raw(hc, &to_free);
612 return hce;
613}
static struct Email * restore_email(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition hcache.c:269
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition hcache.c:425
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition serialize.c:114
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:126
#define ASSERT(COND)
Definition signal2.h:60
void *(* decompress)(ComprHandle *handle, const char *cbuf, size_t clen)
Definition lib.h:111
Wrapper for Email retrieved from the header cache.
Definition lib.h:99
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition lib.h:100
struct Email * email
Retrieved email.
Definition lib.h:102
unsigned int crc
CRC of Email/Body/etc structs.
Definition lib.h:101
void *(* fetch)(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Definition lib.h:100
+ 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 654 of file hcache.c.

655{
656 char *res = NULL;
657 size_t dlen = 0;
658
659 struct RealKey *rk = realkey(hc, key, keylen, false);
660 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
661 if (data)
662 {
663 res = mutt_strn_dup(data, dlen);
664 free_raw(hc, &data);
665 }
666 return res;
667}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:382
+ 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 625 of file hcache.c.

627{
628 bool rc = true;
629 size_t srclen = 0;
630
631 struct RealKey *rk = realkey(hc, key, keylen, false);
632 void *src = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &srclen);
633
634 if (src && (srclen == dstlen))
635 {
636 memcpy(dst, src, dstlen);
637 }
638 else
639 {
640 rc = false;
641 }
642 free_raw(hc, &src);
643 return rc;
644}
+ 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 726 of file hcache.c.

728{
729 if (!hc)
730 return -1;
731
732 struct RealKey *rk = realkey(hc, key, keylen, false);
733 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
734
735 return rc;
736}
+ 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.

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

742{
743 if (!hc)
744 return -1;
745
746 struct RealKey *rk = realkey(hc, key, keylen, true);
747
748 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
749}
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition lib.h:138
+ 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.

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

755{
756 if (!hc)
757 return -1;
758
759 struct RealKey *rk = realkey(hc, key, keylen, false);
760
761 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
762}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: