typedef void * (*hcache_open_t)(const char *path);
/**
- * hcache_fetch_t - backend-specific routine to fetch a message's headers.
+ * hcache_fetch_t - backend-specific routine to fetch a message's headers.
*
* @param ctx The backend-specific context retrieved via hcache_open.
* @param key A message identification string.
*/
typedef void * (*hcache_fetch_t)(void *ctx, const char *key, size_t keylen);
+/**
+ * hcache_free_t - backend-specific routine to free fetched data.
+ *
+ * @param ctx The backend-specific context retrieved via hcache_open.
+ * @param data A pointer to the data got with hcache_fetch or hcache_fetch_raw
+ */
+typedef void (*hcache_free_t)(void *ctx, void **data);
+
/**
* hcache_store_t - backend-specific routine to store a message's headers.
*
const char * name;
hcache_open_t open;
hcache_fetch_t fetch;
+ hcache_free_t free;
hcache_store_t store;
hcache_delete_t delete;
hcache_close_t close;
#define HCACHE_BACKEND_OPS(_name) \
const hcache_ops_t hcache_##_name##_ops = { \
- .name = #_name, \
+ .name = #_name, \
.open = hcache_##_name##_open, \
.fetch = hcache_##_name##_fetch, \
+ .free = hcache_##_name##_free, \
.store = hcache_##_name##_store, \
.delete = hcache_##_name##_delete, \
.close = hcache_##_name##_close, \
return data.data;
}
+static void
+hcache_bdb_free(void *vctx, void **data)
+{
+ FREE(data);
+}
+
static int
hcache_bdb_store(void *vctx, const char *key, size_t keylen, void *data, size_t dlen)
{
return data.dptr;
}
+static void
+hcache_gdbm_free(void *vctx, void **data)
+{
+ FREE(data);
+}
+
static int
hcache_gdbm_store(void *ctx, const char *key, size_t keylen, void *data, size_t dlen)
{
return kcdbget(db, key, keylen, &sp);
}
+static void
+hcache_kyotocabinet_free(void *vctx, void **data)
+{
+ FREE(data);
+}
+
static int
hcache_kyotocabinet_store(void *ctx, const char* key, size_t keylen, void *data, size_t dlen)
{
fprintf(stderr, "mdb_get: %s\n", mdb_strerror(rc));
return NULL;
}
- /* Caller frees the data we return, so I MUST make a copy of it */
- char *d = safe_malloc(data.mv_size);
- memcpy(d, data.mv_data, data.mv_size);
+ return data.mv_data;
+}
- return d;
+static void
+hcache_lmdb_free(void *vctx, void **data)
+{
+ /* LMDB data is owned by the database */
}
static int
return vlget(db, key, keylen, NULL);
}
+static void
+hcache_qdbm_free(void *ctx, void **data)
+{
+ FREE(data);
+}
+
static int
hcache_qdbm_store(void *ctx, const char *key, size_t keylen, void *data, size_t dlen)
{
return tcbdbget(db, key, keylen, &sp);
}
+static void
+hcache_tokyocabinet_free(void *ctx, void **data)
+{
+ FREE(data);
+}
+
static int
hcache_tokyocabinet_store(void *ctx, const char *key, size_t keylen, void *data, size_t dlen)
{
void* data;
data = mutt_hcache_fetch_raw (h, key, keylen);
+ if (!data)
+ {
+ return NULL;
+ }
- if (!data || !crc_matches(data, h->crc))
+ if (!crc_matches(data, h->crc))
{
- FREE(&data);
+ mutt_hcache_free(h, &data);
return NULL;
}
return ops->fetch(h->ctx, path, keylen);
}
+void
+mutt_hcache_free(header_cache_t *h, void **data)
+{
+ const hcache_ops_t *ops = hcache_get_ops();
+
+ if (!h || !ops)
+ return;
+
+ ops->free(h->ctx, data);
+}
+
int
mutt_hcache_store(header_cache_t *h, const char *key, size_t keylen,
HEADER * header, unsigned int uidvalidity)
* @return Pointer to the data if found and valid, NULL otherwise.
* @note This function performs a check on the validity of the data found by
* comparing it with the crc value of the header_cache_t structure.
+ * @note The returned pointer must be freed by calling mutt_hcache_free. This
+ * must be done before closing the header cache with mutt_hcache_close.
*/
void *
mutt_hcache_fetch(header_cache_t *h, const char *key, size_t keylen);
* @return Pointer to the data if found, NULL otherwise.
* @note This function does not perform any check on the validity of the data
* found.
+ * @note The returned pointer must be freed by calling mutt_hcache_free. This
+ * must be done before closing the header cache with mutt_hcache_close.
*/
void *
mutt_hcache_fetch_raw(header_cache_t *h, const char *key, size_t keylen);
+/**
+ * mutt_hcache_free - free previously fetched data.
+ *
+ * @param h Pointer to the header_cache_t structure got by mutt_hcache_open.
+ * @param data Pointer to the data got using hcache_fetch or hcache_fetch_raw.
+ */
+void
+mutt_hcache_free(header_cache_t *h, void **data);
+
/**
* mutt_hcache_restore - restore a HEADER from data retrieved from the cache.
*
IMAP_STATUS scache;
#ifdef USE_HCACHE
header_cache_t *hc = NULL;
- unsigned int *uidvalidity = NULL;
- unsigned int *uidnext = NULL;
+ void *uidvalidity = NULL;
+ void *uidnext = NULL;
#endif
for (cur = idata->mboxcache; cur; cur = cur->next)
{
uidvalidity = mutt_hcache_fetch_raw (hc, "/UIDVALIDITY", 12);
uidnext = mutt_hcache_fetch_raw (hc, "/UIDNEXT", 8);
- mutt_hcache_close (hc);
if (uidvalidity)
{
if (!status)
{
- FREE (&uidvalidity);
- FREE (&uidnext);
+ mutt_hcache_free (hc, &uidvalidity);
+ mutt_hcache_free (hc, &uidnext);
+ mutt_hcache_close (hc);
return imap_mboxcache_get (idata, mbox, 1);
}
- status->uidvalidity = *uidvalidity;
- status->uidnext = uidnext ? *uidnext: 0;
+ status->uidvalidity = *(unsigned int *)uidvalidity;
+ status->uidnext = uidnext ? *(unsigned int *)uidnext: 0;
dprint (3, (debugfile, "mboxcache: hcache uidvalidity %d, uidnext %d\n",
status->uidvalidity, status->uidnext));
}
- FREE (&uidvalidity);
- FREE (&uidnext);
+ mutt_hcache_free (hc, &uidvalidity);
+ mutt_hcache_free (hc, &uidnext);
+ mutt_hcache_close (hc);
}
#endif
#if USE_HCACHE
char buf[LONG_STRING];
- unsigned int *uid_validity = NULL;
- unsigned int *puidnext = NULL;
+ void *uid_validity = NULL;
+ void *puidnext = NULL;
unsigned int uidnext = 0;
int evalhc = 0;
#endif /* USE_HCACHE */
puidnext = mutt_hcache_fetch_raw (idata->hcache, "/UIDNEXT", 8);
if (puidnext)
{
- uidnext = *puidnext;
- FREE (&puidnext);
+ uidnext = *(unsigned int *)puidnext;
+ mutt_hcache_free (idata->hcache, &puidnext);
}
- if (uid_validity && uidnext && *uid_validity == idata->uid_validity)
+ if (uid_validity && uidnext &&
+ *(unsigned int *)uid_validity == idata->uid_validity)
evalhc = 1;
- FREE (&uid_validity);
+ mutt_hcache_free (idata->hcache, &uid_validity);
}
if (evalhc)
{
HEADER* imap_hcache_get (IMAP_DATA* idata, unsigned int uid)
{
char key[16];
- unsigned int* uv;
+ void* uv;
HEADER* h = NULL;
if (!idata->hcache)
imap_hcache_keylen(key));
if (uv)
{
- if (*uv == idata->uid_validity)
- h = mutt_hcache_restore ((const unsigned char*)uv);
+ if (*(unsigned int *)uv == idata->uid_validity)
+ h = mutt_hcache_restore (uv);
else
- dprint (3, (debugfile, "hcache uidvalidity mismatch: %u", *uv));
- FREE (&uv);
+ dprint (3, (debugfile, "hcache uidvalidity mismatch: %u",
+ *(unsigned int *)uv));
+ mutt_hcache_free (idata->hcache, &uv);
}
return h;
mutt_free_header (&p->h);
#if USE_HCACHE
}
- FREE (&data);
+ mutt_hcache_free(hc, &data);
#endif
last = p;
}
mutt_hcache_delete (hc, buf, strlen(buf));
}
}
- FREE (&hdata);
+ mutt_hcache_free (hc, &hdata);
}
/* store current values of first and last */
nntp_data->group, last));
}
}
- FREE (&hdata);
+ mutt_hcache_free (hc, &hdata);
}
mutt_hcache_close (hc);
}
mutt_free_header (&hdr);
ctx->hdrs[ctx->msgcount] =
hdr = mutt_hcache_restore (hdata);
- FREE (&hdata);
+ mutt_hcache_free (fc->hc, &hdata);
hdr->data = 0;
hdr->read = 0;
hdr->old = 0;
"nntp_fetch_headers: mutt_hcache_fetch %s\n", buf));
ctx->hdrs[ctx->msgcount] =
hdr = mutt_hcache_restore (hdata);
- FREE (&hdata);
+ mutt_hcache_free (fc.hc, &hdata);
hdr->data = 0;
/* skip header marked as deleted in cache */
dprint (2, (debugfile,
"nntp_check_mailbox: mutt_hcache_fetch %s\n", buf));
hdr = mutt_hcache_restore (hdata);
- FREE (&hdata);
+ mutt_hcache_free (hc, &hdata);
hdr->data = 0;
deleted = hdr->deleted;
flagged = hdr->flagged;
ctx->hdrs[ctx->msgcount] =
hdr = mutt_hcache_restore (hdata);
- FREE (&hdata);
+ mutt_hcache_free (hc, &hdata);
hdr->data = 0;
if (hdr->deleted)
{
* hcache so there shouldn't be a memleak here)
*/
HEADER *h = mutt_hcache_restore ((unsigned char *) data);
+ mutt_hcache_free (hc, &data);
mutt_free_header (&ctx->hdrs[i]);
ctx->hdrs[i] = h;
ctx->hdrs[i]->refno = refno;
mutt_hcache_store (hc, ctx->hdrs[i]->data, strlen(ctx->hdrs[i]->data),
ctx->hdrs[i], 0);
}
-
- FREE(&data);
#endif
/*