]> granicus.if.org Git - neomutt/commitdiff
Implement mutt_hcache_free to dispose of header cache data
authorPietro Cerutti <gahr@gahr.ch>
Tue, 22 Nov 2016 09:57:37 +0000 (09:57 +0000)
committerRichard Russon <rich@flatcap.org>
Thu, 24 Nov 2016 12:41:00 +0000 (12:41 +0000)
16 files changed:
hcache-backend.h
hcache-bdb.c
hcache-gdbm.c
hcache-kc.c
hcache-lmdb.c
hcache-qdbm.c
hcache-tc.c
hcache.c
hcache.h
imap/imap.c
imap/message.c
imap/util.c
mh.c
newsrc.c
nntp.c
pop.c

index ce858b1e9e5df4e9df23c34cbc925a687787dd5b..983dcc379f3070dc350bd6cc1697cc7e96eb3cf0 100644 (file)
@@ -39,7 +39,7 @@
 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.
@@ -48,6 +48,14 @@ typedef void * (*hcache_open_t)(const char *path);
  */
 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.
  *
@@ -94,6 +102,7 @@ typedef struct
     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;
@@ -110,9 +119,10 @@ typedef struct
 
 #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,        \
index e8931fd99abe892000c04b5f783242550c1d213d..3c291386c6e27b80715a22e2d551eb6e21a3e128 100644 (file)
@@ -140,6 +140,12 @@ hcache_bdb_fetch(void *vctx, const char *key, size_t keylen)
   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)
 {
index 231ac0c94cd0ef4a91648e8c7dd4b22ff55541c7..6aa055c2b66fa0e8d7d366d8f642b744434b6f81 100644 (file)
@@ -60,6 +60,12 @@ hcache_gdbm_fetch(void *ctx, const char *key, size_t keylen)
   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)
 {
index e437f03bf39ef23a3cb6764e36edbd2f28bf3b0e..ff07631867aa1775f1c58d16325e2300a45833ed 100644 (file)
@@ -70,6 +70,12 @@ hcache_kyotocabinet_fetch(void *ctx, const char *key, size_t keylen)
   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)
 {
index cf2f168c0a56c869709bbf9d9d4e75274b5c95e5..9ebaef319361f2782bfd5eb2f6cb4df47072c021 100644 (file)
@@ -172,12 +172,14 @@ hcache_lmdb_fetch(void *vctx, const char *key, size_t keylen)
     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
index 83666598ee5e932d536d892ba3e6db5076c9dc78..3de9cf4ab130b4ab6b05d0155588e38a393686e1 100644 (file)
@@ -50,6 +50,12 @@ hcache_qdbm_fetch(void *ctx, const char *key, size_t keylen)
   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)
 {
index 27443612fbcb9af7476b01202aaf5b7c11e432ab..85b5ba8fc22347158b9d950236b49e9912d4c6ca 100644 (file)
@@ -60,6 +60,12 @@ hcache_tokyocabinet_fetch(void *ctx, const char *key, size_t keylen)
   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)
 {
index 5a7b240b9e8fdc99249d0bcabd8c49a1c87648fd..7627420ce7289ca086a0b8c92a5dc7b180c29088 100644 (file)
--- a/hcache.c
+++ b/hcache.c
@@ -829,10 +829,14 @@ mutt_hcache_fetch(header_cache_t *h, const char *key, size_t keylen)
   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;
   }
 
@@ -853,6 +857,17 @@ mutt_hcache_fetch_raw(header_cache_t *h, const char *key, size_t keylen)
   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)
index 07d59b6f1a0be23ef1f92f1f63bb42b6eb865359..d669a0d54bbd74637ff483b198c1c07b21aee19e 100644 (file)
--- a/hcache.h
+++ b/hcache.h
@@ -58,6 +58,8 @@ mutt_hcache_close(header_cache_t *h);
  * @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);
@@ -71,10 +73,21 @@ 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.
  *
index fb6689809be68e495ab477b708375b1649a18761..73809ff358a747386371f945ff335aad8413f517 100644 (file)
@@ -1652,8 +1652,8 @@ IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox, int create)
   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)
@@ -1682,22 +1682,23 @@ IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox, int create)
   {
     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
 
index 857914c889e996e247600bea2577d9b5c266aa6a..80144cec069f85adf66a52107a6e70e19d2ff794 100644 (file)
@@ -75,8 +75,8 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
 
 #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 */
@@ -128,12 +128,13 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
     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)
   {
index 6b44e2fd023f91ff5dac0647eccbc3cda749d23f..c2ae103bbced53928ade3608f99011e49c3566d3 100644 (file)
@@ -216,7 +216,7 @@ void imap_hcache_close (IMAP_DATA* idata)
 HEADER* imap_hcache_get (IMAP_DATA* idata, unsigned int uid)
 {
   char key[16];
-  unsigned int* uv;
+  void* uv;
   HEADER* h = NULL;
 
   if (!idata->hcache)
@@ -227,11 +227,12 @@ HEADER* imap_hcache_get (IMAP_DATA* idata, unsigned int uid)
                                          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;
diff --git a/mh.c b/mh.c
index fae0cfbb25683c8a754c4141bb9f753d13e176aa..4ce73ebf726086f9aa8888d4291805d4b6e73d71 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -1231,7 +1231,7 @@ static void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md,
       mutt_free_header (&p->h);
 #if USE_HCACHE
     }
-    FREE (&data);
+    mutt_hcache_free(hc, &data);
 #endif
     last = p;
    }
index d30d5545a7d2f30a9a9305534463d1d08fdf83b1..bc2167f478f8a55af8194b6009c8c773736393a0 100644 (file)
--- a/newsrc.c
+++ b/newsrc.c
@@ -667,7 +667,7 @@ void nntp_hcache_update (NNTP_DATA *nntp_data, header_cache_t *hc)
        mutt_hcache_delete (hc, buf, strlen(buf));
       }
     }
-    FREE (&hdata);
+    mutt_hcache_free (hc, &hdata);
   }
 
   /* store current values of first and last */
@@ -1049,7 +1049,7 @@ NNTP_SERVER *nntp_select_server (char *server, int leave_lock)
                          nntp_data->group, last));
            }
          }
-         FREE (&hdata);
+         mutt_hcache_free (hc, &hdata);
        }
        mutt_hcache_close (hc);
       }
diff --git a/nntp.c b/nntp.c
index d5d41170a62d1a813d1ebec687b500267bb66558..a07e230193e42fc39eef80ef17d88a798f396c44 100644 (file)
--- a/nntp.c
+++ b/nntp.c
@@ -1125,7 +1125,7 @@ static int parse_overview_line (char *line, void *data)
       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;
@@ -1289,7 +1289,7 @@ static int nntp_fetch_headers (CONTEXT *ctx, void *hc,
                  "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 */
@@ -2050,7 +2050,7 @@ int nntp_check_mailbox (CONTEXT *ctx, int *index_hint)
          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;
@@ -2099,7 +2099,7 @@ int nntp_check_mailbox (CONTEXT *ctx, int *index_hint)
 
        ctx->hdrs[ctx->msgcount] =
        hdr = mutt_hcache_restore (hdata);
-       FREE (&hdata);
+       mutt_hcache_free (hc, &hdata);
        hdr->data = 0;
        if (hdr->deleted)
        {
diff --git a/pop.c b/pop.c
index 2a708d0ff54031406928767a5f141111152f2ed6..27bed8def21b6017f0fdb7093e94b6baf8d07b86 100644 (file)
--- a/pop.c
+++ b/pop.c
@@ -318,6 +318,7 @@ static int pop_fetch_headers (CONTEXT *ctx)
         *   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;
@@ -336,8 +337,6 @@ static int pop_fetch_headers (CONTEXT *ctx)
        mutt_hcache_store (hc, ctx->hdrs[i]->data, strlen(ctx->hdrs[i]->data), 
                        ctx->hdrs[i], 0);
       }
-
-      FREE(&data);
 #endif
 
       /*