NeoMutt  2024-04-25-102-g19653a
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)   hcache_fetch_raw_obj_full(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, 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 
)    hcache_fetch_raw_obj_full(hc, key, keylen, dst, sizeof(*dst))

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

473{
474 if (!path || (path[0] == '\0'))
475 return NULL;
476
477 if (HcacheVer == 0x0)
479
480 struct HeaderCache *hc = hcache_new();
481
483 hc->crc = HcacheVer;
484
485 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
486 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
487 if (!hc->store_ops)
488 {
489 hcache_free(&hc);
490 return NULL;
491 }
492
493#ifdef USE_HCACHE_COMPRESSION
494 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
495 if (c_header_cache_compress_method)
496 {
497 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
498
499 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
500 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
501 if (!hc->compr_handle)
502 {
503 hcache_free(&hc);
504 return NULL;
505 }
506
507 /* remember the buffer of database backend */
508 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
509 hc->compr_ops->name);
510 }
511#endif
512
513 struct Buffer *hcpath = buf_pool_get();
514 hcache_per_folder(hc, hcpath, path, namer);
515
516 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
517 if (!hc->store_handle)
518 {
519 /* remove a possibly incompatible version */
520 if (unlink(buf_string(hcpath)) == 0)
521 {
522 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
523 if (!hc->store_handle)
524 {
525 if (hc->compr_ops)
526 {
527 hc->compr_ops->close(&hc->compr_handle);
528 }
529 hcache_free(&hc);
530 }
531 }
532 else
533 {
534 hcache_free(&hc);
535 }
536 }
537
538 buf_pool_release(&hcpath);
539 return hc;
540}
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:81
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:89
static unsigned int HcacheVer
Header Cache version.
Definition: hcache.c:61
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition: hcache.c:103
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition: hcache.c:118
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition: hcache.c:432
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:409
@ 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:107
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:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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 545 of file hcache.c.

546{
547 if (!ptr || !*ptr)
548 return;
549
550 struct HeaderCache *hc = *ptr;
551
552#ifdef USE_HCACHE_COMPRESSION
553 if (hc->compr_ops)
554 hc->compr_ops->close(&hc->compr_handle);
555#endif
556
557 hc->store_ops->close(&hc->store_handle);
558
559 hcache_free(ptr);
560}
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 673 of file hcache.c.

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

567{
568 struct HCacheEntry hce = { 0 };
569 if (!hc)
570 return hce;
571
572 size_t dlen = 0;
573 struct RealKey *rk = realkey(hc, key, keylen, true);
574 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
575 void *to_free = data;
576 if (!data)
577 {
578 goto end;
579 }
580
581 /* restore uidvalidity and crc */
582 size_t hlen = header_size();
583 if (hlen > dlen)
584 {
585 goto end;
586 }
587 int off = 0;
588 serial_restore_uint32_t(&hce.uidvalidity, data, &off);
589 serial_restore_int(&hce.crc, data, &off);
590 ASSERT((size_t) off == hlen);
591 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
592 {
593 goto end;
594 }
595
596#ifdef USE_HCACHE_COMPRESSION
597 if (hc->compr_ops)
598 {
599 void *dblob = hc->compr_ops->decompress(hc->compr_handle,
600 (char *) data + hlen, dlen - hlen);
601 if (!dblob)
602 {
603 goto end;
604 }
605 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
606 }
607#endif
608
609 hce.email = restore_email(data);
610
611end:
612 free_raw(hc, &to_free);
613 return hce;
614}
static struct Email * restore_email(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:267
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:423
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:58
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 655 of file hcache.c.

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

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

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

743{
744 if (!hc)
745 return -1;
746
747 struct RealKey *rk = realkey(hc, key, keylen, true);
748
749 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
750}
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 755 of file hcache.c.

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