]> granicus.if.org Git - neomutt/commitdiff
ImapStatus doesn't make sense since we have ImapMboxData.
authorMehdi Abaakouk <sileht@sileht.net>
Sat, 17 Nov 2018 17:39:32 +0000 (18:39 +0100)
committerRichard Russon <rich@flatcap.org>
Sun, 18 Nov 2018 15:26:07 +0000 (15:26 +0000)
Some attributes are duplicated a synced between strucuture.

This change moves all STATUS informations in ImapMboxData
and remove ImapStatus structure.

mboxcache is also removed because ImapMboxData stay in memory during the
whole Mailbox life, no more need to cache that.

imap/command.c
imap/imap.c
imap/imap_private.h
imap/message.c
imap/util.c

index d09dad74bb25cab17da9340ec9959907d483215b..b78d902b79e92aba640e78c85ad8188c74f96b17 100644 (file)
@@ -782,7 +782,6 @@ static void cmd_parse_search(struct ImapAccountData *adata, const char *s)
 static void cmd_parse_status(struct ImapAccountData *adata, char *s)
 {
   char *value = NULL;
-  struct ImapStatus *status = NULL;
   unsigned int olduv, oldun;
   unsigned int litlen;
   short new = 0;
@@ -818,12 +817,21 @@ static void cmd_parse_status(struct ImapAccountData *adata, char *s)
     imap_unmunge_mbox_name(adata->unicode, mailbox);
   }
 
-  struct ImapMboxData *mdata = imap_mdata_new(adata, mailbox);
-  status = imap_mboxcache_get(adata, mdata, true);
-  imap_mdata_free((void *) &mdata);
+  struct Url url;
+  mutt_account_tourl(&adata->conn_account, &url);
+  url.path = mailbox;
+  char path[PATH_MAX];
+  url_tostring(&url, path, sizeof(path), 0);
 
-  olduv = status->uidvalidity;
-  oldun = status->uidnext;
+  struct Mailbox *m = mx_mbox_find2(path);
+  if (!m || !m->mdata)
+  {
+    mutt_debug(3, "Received status for an unexpected mailbox: %s\n", mailbox);
+    return;
+  }
+  struct ImapMboxData *mdata = m->mdata;
+  olduv = mdata->uid_validity;
+  oldun = mdata->uid_next;
 
   if (*s++ != '(')
   {
@@ -845,91 +853,79 @@ static void cmd_parse_status(struct ImapAccountData *adata, char *s)
 
     if (mutt_str_startswith(s, "MESSAGES", CASE_MATCH))
     {
-      status->messages = count;
+      mdata->messages = count;
       new_msg_count = 1;
     }
     else if (mutt_str_startswith(s, "RECENT", CASE_MATCH))
-      status->recent = count;
+      mdata->recent = count;
     else if (mutt_str_startswith(s, "UIDNEXT", CASE_MATCH))
-      status->uidnext = count;
+      mdata->uid_next = count;
     else if (mutt_str_startswith(s, "UIDVALIDITY", CASE_MATCH))
-      status->uidvalidity = count;
+      mdata->uid_validity = count;
     else if (mutt_str_startswith(s, "UNSEEN", CASE_MATCH))
-      status->unseen = count;
+      mdata->unseen = count;
 
     s = value;
     if (*s && *s != ')')
       s = imap_next_word(s);
   }
   mutt_debug(3, "%s (UIDVALIDITY: %u, UIDNEXT: %u) %d messages, %d recent, %d unseen\n",
-             status->name, status->uidvalidity, status->uidnext,
-             status->messages, status->recent, status->unseen);
+             mdata->name, mdata->uid_validity, mdata->uid_next, mdata->messages,
+             mdata->recent, mdata->unseen);
 
+#if 0
+  // NOTE(sileht): I don't get this part, I haven't found where cmddata is reused
+  // after that.
   /* caller is prepared to handle the result herself */
   if (adata->cmddata && adata->cmdtype == IMAP_CT_STATUS)
   {
     memcpy(adata->cmddata, status, sizeof(struct ImapStatus));
     return;
   }
+#endif
 
   mutt_debug(3, "Running default STATUS handler\n");
 
-  /* should perhaps move this code back to imap_mailbox_check */
-  struct MailboxNode *np = NULL;
-  STAILQ_FOREACH(np, &AllMailboxes, entries)
-  {
-    if (np->m->magic != MUTT_IMAP)
-      continue;
+  mutt_debug(3, "Found %s in mailbox list (OV: %u ON: %u U: %d)\n", mailbox,
+             olduv, oldun, mdata->unseen);
 
-    struct ImapAccountData *m_adata = imap_adata_get(np->m);
-    if (imap_account_match(&adata->conn_account, &m_adata->conn_account))
+  if (MailCheckRecent)
+  {
+    if (olduv && olduv == mdata->uid_validity)
     {
-      struct ImapMboxData *mdata2 = imap_mdata_get(np->m);
-      if (mdata2 && imap_mxcmp(mailbox, mdata2->name) == 0)
-      {
-        mutt_debug(3, "Found %s in mailbox list (OV: %u ON: %u U: %d)\n",
-                   mailbox, olduv, oldun, status->unseen);
-
-        if (MailCheckRecent)
-        {
-          if (olduv && olduv == status->uidvalidity)
-          {
-            if (oldun < status->uidnext)
-              new = (status->unseen > 0);
-          }
-          else if (!olduv && !oldun)
-          {
-            /* first check per session, use recent. might need a flag for this. */
-            new = (status->recent > 0);
-          }
-          else
-            new = (status->unseen > 0);
-        }
-        else
-          new = (status->unseen > 0);
+      if (oldun < mdata->uid_next)
+        new = (mdata->unseen > 0);
+    }
+    else if (!olduv && !oldun)
+    {
+      /* first check per session, use recent. might need a flag for this. */
+      new = (mdata->recent > 0);
+    }
+    else
+      new = (mdata->unseen > 0);
+  }
+  else
+    new = (mdata->unseen > 0);
 
 #ifdef USE_SIDEBAR
-        if ((np->m->has_new != new) || (np->m->msg_count != status->messages) ||
-            (np->m->msg_unread != status->unseen))
-        {
-          mutt_menu_set_current_redraw(REDRAW_SIDEBAR);
-        }
+  if ((m->has_new != new) || (m->msg_count != mdata->messages) ||
+      (m->msg_unread != mdata->unseen))
+  {
+    mutt_menu_set_current_redraw(REDRAW_SIDEBAR);
+  }
 #endif
-        np->m->has_new = new;
-        if (new_msg_count)
-          np->m->msg_count = status->messages;
-        np->m->msg_unread = status->unseen;
+  m->has_new = new;
+  if (new_msg_count)
+    m->msg_count = mdata->messages;
+  m->msg_unread = mdata->unseen;
 
-        if (np->m->has_new)
-        {
-          /* force back to keep detecting new mail until the mailbox is
-             opened */
-          status->uidnext = oldun;
-        }
-        return;
-      }
-    }
+  if (m->has_new)
+  {
+    /* force back to keep detecting new mail until the mailbox is
+       opened */
+    mdata->uid_next = oldun;
   }
+  return;
 }
 
 /**
index e5b6e019be2f323c5e050cd69812203bf6260a29..4dacf3e87654ad92cf3f8230164b03aec39df1cf 100644 (file)
@@ -600,22 +600,16 @@ static int complete_hosts(char *buf, size_t buflen)
  */
 static int imap_access2(struct ImapAccountData *adata, struct ImapMboxData *mdata)
 {
-  struct ImapMboxData *selected_mdata = NULL;
   char buf[LONG_STRING * 2];
   int rc;
 
-  if (adata->mailbox)
-    selected_mdata = adata->mailbox->mdata;
-
   /* we may already be in the folder we're checking */
-  if (selected_mdata && mutt_str_strcmp(selected_mdata->name, mdata->name) == 0)
+  if (adata->mailbox && adata->mailbox->mdata == mdata)
     return 0;
 
-  if (imap_mboxcache_get(adata, mdata, false))
-  {
-    mutt_debug(3, "found %s in cache\n", mdata->name);
+  // We already have the information from cache.
+  if (mdata->uid_validity > 0)
     return 0;
-  }
 
   if (mutt_bit_isset(adata->capabilities, IMAP4REV1))
     snprintf(buf, sizeof(buf), "STATUS %s (UIDVALIDITY)", mdata->munge_name);
@@ -671,6 +665,11 @@ int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
  */
 int imap_access(const char *path)
 {
+  struct Mailbox *m = mx_mbox_find2(path);
+  if (m)
+    return imap_access2(m->account->adata, m->mdata);
+
+  // FIXME(sileht): Is that case possible ?
   struct ImapAccountData *adata = NULL;
   struct ImapMboxData *mdata = NULL;
   int rc;
@@ -1354,7 +1353,6 @@ int imap_mailbox_check(struct Mailbox *m, bool check_stats)
 {
   struct ImapAccountData *adata = NULL;
   struct ImapMboxData *mdata = NULL;
-  struct ImapMboxData *selected_mdata = NULL;
   char command[LONG_STRING * 2];
 
   if (imap_prepare_mailbox(m))
@@ -1366,14 +1364,11 @@ int imap_mailbox_check(struct Mailbox *m, bool check_stats)
   mdata = m->mdata;
   adata = m->account->adata;
 
-  if (adata->mailbox)
-    selected_mdata = adata->mailbox->mdata;
-
   /* Don't issue STATUS on the selected mailbox, it will be NOOPed or
    * IDLEd elsewhere.
    * adata->mailbox may be NULL for connections other than the current
    * mailbox's.. #3216. */
-  if (selected_mdata && mdata == selected_mdata)
+  if (adata->mailbox && adata->mailbox == m)
   {
     m->has_new = false;
     return -1;
@@ -1425,25 +1420,20 @@ int imap_mailbox_check(struct Mailbox *m, bool check_stats)
 int imap_status(const char *path, bool queue)
 {
   static int queued = 0;
-
-  struct ImapAccountData *adata = NULL;
-  struct ImapMboxData *mdata = NULL;
-  struct ImapMboxData *selected_mdata = NULL;
   char buf[LONG_STRING * 2];
-  struct ImapStatus *status = NULL;
 
-  if (imap_adata_find(path, &adata, &mdata) < 0)
+  struct Mailbox *m = mx_mbox_find2(path);
+  if (!m)
     return -1;
 
-  if (adata->mailbox)
-    selected_mdata = adata->mailbox->mdata;
+  if (imap_prepare_mailbox(m) < 0)
+    return -1;
 
+  struct ImapAccountData *adata = m->account->adata;
+  struct ImapMboxData *mdata = m->mdata;
   // We are in the folder we're polling - just return the mailbox count.
-  if (selected_mdata && selected_mdata == mdata)
-  {
-    imap_mdata_free((void **) &mdata);
-    return adata->mailbox->msg_count;
-  }
+  if (adata->mailbox == m)
+    return m->msg_count;
 
   else if (mutt_bit_isset(adata->capabilities, IMAP4REV1) ||
            mutt_bit_isset(adata->capabilities, STATUS))
@@ -1454,7 +1444,6 @@ int imap_status(const char *path, bool queue)
   {
     /* Server does not support STATUS, and this is not the current mailbox.
      * There is no lightweight way to check recent arrivals */
-    imap_mdata_free((void **) &mdata);
     return -1;
   }
 
@@ -1462,105 +1451,12 @@ int imap_status(const char *path, bool queue)
   {
     imap_exec(adata, buf, IMAP_CMD_QUEUE);
     queued = 1;
-    imap_mdata_free((void **) &mdata);
     return 0;
   }
   else if (!queued)
     imap_exec(adata, buf, 0);
 
-  queued = 0;
-  status = imap_mboxcache_get(adata, mdata, false);
-  imap_mdata_free((void **) &mdata);
-  if (status)
-    return status->messages;
-
-  return 0;
-}
-
-/**
- * imap_mboxcache_get - Open an hcache for a mailbox
- * @param adata  Imap Account data
- * @param mdata  Imap Mailbox data to cache
- * @param create Should it be created if it doesn't exist?
- * @retval ptr  Stats of cached mailbox
- * @retval ptr  Stats of new cache entry
- * @retval NULL Not in cache and create is false
- *
- * return cached mailbox stats or NULL if create is 0
- */
-struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata,
-                                      struct ImapMboxData *mdata, bool create)
-{
-  struct ImapStatus *status = NULL;
-  struct ListNode *np = NULL;
-  STAILQ_FOREACH(np, &adata->mboxcache, entries)
-  {
-    status = (struct ImapStatus *) np->data;
-
-    if (imap_mxcmp(mdata->name, status->name) == 0)
-      return status;
-  }
-  status = NULL;
-
-  /* lame */
-  if (create)
-  {
-    struct ImapStatus *scache = mutt_mem_calloc(1, sizeof(struct ImapStatus));
-    scache->name = mdata->name;
-    mutt_list_insert_tail(&adata->mboxcache, (char *) scache);
-    status = imap_mboxcache_get(adata, mdata, false);
-    status->name = mutt_str_strdup(mdata->name);
-  }
-
-#ifdef USE_HCACHE
-  header_cache_t *hc = imap_hcache_open(adata, mdata);
-  if (hc)
-  {
-    void *uidvalidity = mutt_hcache_fetch_raw(hc, "/UIDVALIDITY", 12);
-    void *uidnext = mutt_hcache_fetch_raw(hc, "/UIDNEXT", 8);
-    unsigned long long *modseq = mutt_hcache_fetch_raw(hc, "/MODSEQ", 7);
-    if (uidvalidity)
-    {
-      if (!status)
-      {
-        mutt_hcache_free(hc, &uidvalidity);
-        mutt_hcache_free(hc, &uidnext);
-        mutt_hcache_free(hc, (void **) &modseq);
-        mutt_hcache_close(hc);
-        return imap_mboxcache_get(adata, mdata, true);
-      }
-      status->uidvalidity = *(unsigned int *) uidvalidity;
-      status->uidnext = uidnext ? *(unsigned int *) uidnext : 0;
-      status->modseq = modseq ? *modseq : 0;
-      mutt_debug(3, "hcache uidvalidity %u, uidnext %u, modseq %llu\n",
-                 status->uidvalidity, status->uidnext, status->modseq);
-    }
-    mutt_hcache_free(hc, &uidvalidity);
-    mutt_hcache_free(hc, &uidnext);
-    mutt_hcache_free(hc, (void **) &modseq);
-    mutt_hcache_close(hc);
-  }
-#endif
-
-  return status;
-}
-
-/**
- * imap_mboxcache_free - Free the cached ImapStatus
- * @param adata Imap Account data
- */
-void imap_mboxcache_free(struct ImapAccountData *adata)
-{
-  struct ImapStatus *status = NULL;
-
-  struct ListNode *np = NULL;
-  STAILQ_FOREACH(np, &adata->mboxcache, entries)
-  {
-    status = (struct ImapStatus *) np->data;
-    FREE(&status->name);
-  }
-
-  mutt_list_free(&adata->mboxcache);
+  return mdata->messages;
 }
 
 /**
@@ -2167,7 +2063,6 @@ static int imap_mbox_open(struct Context *ctx)
   if (!m->account)
     return -1;
 
-  struct ImapStatus *status = NULL;
   char buf[PATH_MAX];
   int count = 0;
   int rc;
@@ -2196,6 +2091,7 @@ static int imap_mbox_open(struct Context *ctx)
   /* clear mailbox status */
   adata->status = 0;
   memset(adata->mailbox->rights, 0, sizeof(adata->mailbox->rights));
+  mdata->new_mail_count = 0;
 
   mutt_message(_("Selecting %s..."), mdata->name);
 
@@ -2245,8 +2141,6 @@ static int imap_mbox_open(struct Context *ctx)
 
   imap_cmd_start(adata, buf);
 
-  status = imap_mboxcache_get(adata, mdata, true);
-
   do
   {
     char *pc = NULL;
@@ -2290,16 +2184,14 @@ static int imap_mbox_open(struct Context *ctx)
       pc = imap_next_word(pc);
       if (mutt_str_atoui(pc, &mdata->uid_validity) < 0)
         goto fail;
-      status->uidvalidity = mdata->uid_validity;
     }
     else if (mutt_str_startswith(pc, "OK [UIDNEXT", CASE_IGNORE))
     {
       mutt_debug(3, "Getting mailbox UIDNEXT\n");
       pc += 3;
       pc = imap_next_word(pc);
-      if (mutt_str_atoui(pc, &mdata->uidnext) < 0)
+      if (mutt_str_atoui(pc, &mdata->uid_next) < 0)
         goto fail;
-      status->uidnext = mdata->uidnext;
     }
     else if (mutt_str_startswith(pc, "OK [HIGHESTMODSEQ", CASE_IGNORE))
     {
@@ -2308,12 +2200,11 @@ static int imap_mbox_open(struct Context *ctx)
       pc = imap_next_word(pc);
       if (mutt_str_atoull(pc, &mdata->modseq) < 0)
         goto fail;
-      status->modseq = mdata->modseq;
     }
     else if (mutt_str_startswith(pc, "OK [NOMODSEQ", CASE_IGNORE))
     {
       mutt_debug(3, "Mailbox has NOMODSEQ set\n");
-      status->modseq = mdata->modseq = 0;
+      mdata->modseq = 0;
     }
     else
     {
@@ -2501,12 +2392,7 @@ static int imap_mbox_close(struct Context *ctx)
     adata->mailbox = NULL;
     adata->ctx = NULL;
 
-    // TODO(sileht): As this is associated to a Mailbox we could keep it
-    // to not requery everything each time a mailbox is reopen. This need to be
-    // tested and we need to free this somewhere.
-    // For now free it each time we close the mailbox to keep the previous mutt
-    // behavior.
-    imap_mdata_free(&m->mdata);
+    imap_mdata_cache_reset(m->mdata);
   }
 
   return 0;
index 44035207debe3b0ed81dcaa2c36572e4b767bbf7..57828a885d43c8789dad1c7c7269b6951d13cbe0 100644 (file)
@@ -157,21 +157,6 @@ struct ImapCache
   char *path;
 };
 
-/**
- * struct ImapStatus - Status of an IMAP mailbox
- */
-struct ImapStatus
-{
-  char *name;
-
-  unsigned int messages;
-  unsigned int recent;
-  unsigned int uidnext;
-  unsigned int uidvalidity;
-  unsigned int unseen;
-  unsigned long long modseq;  /* Used by CONDSTORE. 1 <= modseq < 2^63 */
-};
-
 /**
  * struct ImapList - Items in an IMAP browser
  */
@@ -245,9 +230,6 @@ struct ImapAccountData
   int lastcmd;
   struct Buffer *cmdbuf;
 
-  /* cache ImapStatus of visited mailboxes */
-  struct ListHead mboxcache;
-
   char delim;
   struct Context *ctx;
   struct Mailbox *mailbox;     /* Current selected mailbox */
@@ -270,11 +252,18 @@ struct ImapMboxData
   unsigned char reopen;        /**< Flags, e.g. #IMAP_REOPEN_ALLOW */
   unsigned short check_status; /**< Flags, e.g. #IMAP_NEWMAIL_PENDING */
   unsigned int new_mail_count; /**< Set when EXISTS notifies of new mail */
-  struct ImapCache cache[IMAP_CACHE_LEN];
-  struct Hash *uid_hash;
+
+  // IMAP STATUS information
   unsigned int uid_validity;
-  unsigned int uidnext;
+  unsigned int uid_next;
   unsigned long long modseq;
+  unsigned int messages;
+  unsigned int recent;
+  unsigned int unseen;
+
+  // Cached data used only when the mailbox is opened
+  struct ImapCache cache[IMAP_CACHE_LEN];
+  struct Hash *uid_hash;
   struct Email **msn_index;   /**< look up headers by (MSN-1) */
   size_t msn_index_size;       /**< allocation size */
   unsigned int max_msn;        /**< the largest MSN fetched so far */
@@ -305,8 +294,6 @@ struct SeqsetIterator
 int imap_check(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool force);
 int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox);
 int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char *newname);
-struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool create);
-void imap_mboxcache_free(struct ImapAccountData *adata);
 int imap_exec_msgset(struct ImapAccountData *adata, const char *pre, const char *post,
                      int flag, bool changed, bool invert);
 int imap_open_connection(struct ImapAccountData *adata);
@@ -364,6 +351,7 @@ struct ImapAccountData *imap_adata_new(void);
 void imap_adata_free(void **ptr);
 struct ImapMboxData *imap_mdata_new(struct ImapAccountData *adata, const char* name);
 void imap_mdata_free(void **ptr);
+void imap_mdata_cache_reset(struct ImapMboxData *mdata);
 char *imap_fix_path(struct ImapAccountData *adata, const char *mailbox, char *path, size_t plen);
 void imap_cachepath(struct ImapAccountData *adata, const char *mailbox, char *dest, size_t dlen);
 int imap_get_literal_count(const char *buf, unsigned int *bytes);
index 640086965818c82d039fe6ac74cc6d5ec3cc7994..92b17a13ceb27803bf0d19d83dc612dbdb8dfb23 100644 (file)
@@ -683,7 +683,7 @@ static void set_changed_flag(struct Context *ctx, struct Email *e,
  * read_headers_normal_eval_cache - Retrieve data from the header cache
  * @param adata              Imap Account data
  * @param msn_end            Last Message Sequence number
- * @param uidnext            UID of next email
+ * @param uid_next           UID of next email
  * @param store_flag_updates if true, save flags to the header cache
  * @param eval_condstore     if true, use CONDSTORE to fetch flags
  * @retval  0 Success
@@ -697,7 +697,7 @@ static void set_changed_flag(struct Context *ctx, struct Email *e,
  * read_headers_condstore_qresync_updates().
  */
 static int read_headers_normal_eval_cache(struct ImapAccountData *adata,
-                                          unsigned int msn_end, unsigned int uidnext,
+                                          unsigned int msn_end, unsigned int uid_next,
                                           bool store_flag_updates, bool eval_condstore)
 {
   struct Progress progress;
@@ -714,7 +714,7 @@ static int read_headers_normal_eval_cache(struct ImapAccountData *adata,
   /* If we are using CONDSTORE's "FETCH CHANGEDSINCE", then we keep
    * the flags in the header cache, and update them further below.
    * Otherwise, we fetch the current state of the flags here. */
-  snprintf(buf, sizeof(buf), "UID FETCH 1:%u (UID%s)", uidnext - 1,
+  snprintf(buf, sizeof(buf), "UID FETCH 1:%u (UID%s)", uid_next - 1,
            eval_condstore ? "" : " FLAGS");
 
   imap_cmd_start(adata, buf);
@@ -897,7 +897,7 @@ static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *
  * read_headers_condstore_qresync_updates - Retrieve updates from the server
  * @param adata        Imap Account data
  * @param msn_end      Last Message Sequence number
- * @param uidnext      UID of next email
+ * @param uid_next     UID of next email
  * @param hc_modseq    Timestamp of last Header Cache update
  * @param eval_qresync If true, use QRESYNC
  * @retval  0 Success
@@ -906,7 +906,7 @@ static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *
  * CONDSTORE and QRESYNC use FETCH extensions to grab updates.
  */
 static int read_headers_condstore_qresync_updates(struct ImapAccountData *adata,
-                                                  unsigned int msn_end, unsigned int uidnext,
+                                                  unsigned int msn_end, unsigned int uid_next,
                                                   unsigned long long hc_modseq, bool eval_qresync)
 {
   struct Progress progress;
@@ -921,7 +921,7 @@ static int read_headers_condstore_qresync_updates(struct ImapAccountData *adata,
                      MUTT_PROGRESS_MSG, ReadInc, msn_end);
 
   snprintf(buf, sizeof(buf), "UID FETCH 1:%u (FLAGS) (CHANGEDSINCE %llu%s)",
-           uidnext - 1, hc_modseq, eval_qresync ? " VANISHED" : "");
+           uid_next - 1, hc_modseq, eval_qresync ? " VANISHED" : "");
 
   imap_cmd_start(adata, buf);
 
@@ -1203,7 +1203,6 @@ bail:
 int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
                       unsigned int msn_end, bool initial_download)
 {
-  struct ImapStatus *status = NULL;
   int oldmsgcount;
   unsigned int maxuid = 0;
   int retval = -1;
@@ -1211,8 +1210,8 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
 
 #ifdef USE_HCACHE
   void *uid_validity = NULL;
-  void *puidnext = NULL;
-  unsigned int uidnext = 0;
+  void *puid_next = NULL;
+  unsigned int uid_next = 0;
   bool has_condstore = false;
   bool has_qresync = false;
   bool eval_condstore = false;
@@ -1241,11 +1240,11 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
   if (mdata->hcache && initial_download)
   {
     uid_validity = mutt_hcache_fetch_raw(mdata->hcache, "/UIDVALIDITY", 12);
-    puidnext = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8);
-    if (puidnext)
+    puid_next = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8);
+    if (puid_next)
     {
-      uidnext = *(unsigned int *) puidnext;
-      mutt_hcache_free(mdata->hcache, &puidnext);
+      uid_next = *(unsigned int *) puid_next;
+      mutt_hcache_free(mdata->hcache, &puid_next);
     }
 
     if (mdata->modseq)
@@ -1261,7 +1260,7 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
         has_qresync = true;
     }
 
-    if (uid_validity && uidnext && (*(unsigned int *) uid_validity == mdata->uid_validity))
+    if (uid_validity && uid_next && (*(unsigned int *) uid_validity == mdata->uid_validity))
     {
       evalhc = true;
       pmodseq = mutt_hcache_fetch_raw(mdata->hcache, "/MODSEQ", 7);
@@ -1294,14 +1293,14 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
     }
     else
     {
-      if (read_headers_normal_eval_cache(adata, msn_end, uidnext, has_condstore || has_qresync,
+      if (read_headers_normal_eval_cache(adata, msn_end, uid_next, has_condstore || has_qresync,
                                          eval_condstore) < 0)
         goto bail;
     }
 
     if ((eval_condstore || eval_qresync) && (hc_modseq != mdata->modseq))
     {
-      if (read_headers_condstore_qresync_updates(adata, msn_end, uidnext,
+      if (read_headers_condstore_qresync_updates(adata, msn_end, uid_next,
                                                  hc_modseq, eval_qresync) < 0)
       {
         goto bail;
@@ -1321,24 +1320,21 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
   if (read_headers_fetch_new(adata, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
     goto bail;
 
-  if (maxuid && (status = imap_mboxcache_get(adata, mdata, 0)) &&
-      (status->uidnext < maxuid + 1))
-  {
-    status->uidnext = maxuid + 1;
-  }
+  if (maxuid && mdata->uid_next < maxuid + 1)
+    mdata->uid_next = maxuid + 1;
 
 #ifdef USE_HCACHE
   mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uid_validity,
                         sizeof(mdata->uid_validity));
-  if (maxuid && mdata->uidnext < maxuid + 1)
+  if (maxuid && mdata->uid_next < maxuid + 1)
   {
-    mutt_debug(2, "Overriding UIDNEXT: %u -> %u\n", mdata->uidnext, maxuid + 1);
-    mdata->uidnext = maxuid + 1;
+    mutt_debug(2, "Overriding UIDNEXT: %u -> %u\n", mdata->uid_next, maxuid + 1);
+    mdata->uid_next = maxuid + 1;
   }
-  if (mdata->uidnext > 1)
+  if (mdata->uid_next > 1)
   {
-    mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uidnext,
-                          sizeof(mdata->uidnext));
+    mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uid_next,
+                          sizeof(mdata->uid_next));
   }
 
   /* We currently only sync CONDSTORE and QRESYNC on the initial download.
index 9002a715f90fcd952f4cb0008febd95d98e1f95b..e51533ecf7d11499def7a2c48ceea5400f247644 100644 (file)
@@ -79,7 +79,6 @@ void imap_adata_free(void **ptr)
 
   FREE(&adata->capstr);
   mutt_list_free(&adata->flags);
-  imap_mboxcache_free(adata);
   mutt_buffer_free(&adata->cmdbuf);
   FREE(&adata->buf);
   FREE(&adata->cmds);
@@ -107,7 +106,6 @@ struct ImapAccountData *imap_adata_new(void)
   adata->cmds = mutt_mem_calloc(adata->cmdslots, sizeof(*adata->cmds));
 
   STAILQ_INIT(&adata->flags);
-  STAILQ_INIT(&adata->mboxcache);
 
   return adata;
 }
@@ -174,19 +172,41 @@ struct ImapMboxData *imap_mdata_new(struct ImapAccountData *adata, const char *n
 
   mdata->reopen &= IMAP_REOPEN_ALLOW;
 
+#ifdef USE_HCACHE
+  header_cache_t *hc = imap_hcache_open(adata, mdata);
+  if (hc)
+  {
+    void *uidvalidity = mutt_hcache_fetch_raw(hc, "/UIDVALIDITY", 12);
+    void *uidnext = mutt_hcache_fetch_raw(hc, "/UIDNEXT", 8);
+    unsigned long long *modseq = mutt_hcache_fetch_raw(hc, "/MODSEQ", 7);
+    if (uidvalidity)
+    {
+      mdata->uid_validity = *(unsigned int *) uidvalidity;
+      mdata->uid_next = uidnext ? *(unsigned int *) uidnext : 0;
+      mdata->modseq = modseq ? *modseq : 0;
+      mutt_debug(3, "hcache uidvalidity %u, uidnext %u, modseq %llu\n",
+                 mdata->uid_validity, mdata->uid_next, mdata->modseq);
+    }
+    mutt_hcache_free(hc, &uidvalidity);
+    mutt_hcache_free(hc, &uidnext);
+    mutt_hcache_free(hc, (void **) &modseq);
+    mutt_hcache_close(hc);
+  }
+#endif
+
   return mdata;
 }
 
 /**
- * imap_mdata_free - Release and clear storage in an ImapMboxData structure
- * @param ptr Imap Mailbox data
+ * imap_mdata_cache_reset - Release and clear cache data of ImapMboxData structure
+ * @param mdata Imap Mailbox data
  */
-void imap_mdata_free(void **ptr)
+void imap_mdata_cache_reset(struct ImapMboxData *mdata)
 {
-  if (!ptr || !*ptr)
-    return;
-
-  struct ImapMboxData *mdata = *ptr;
+  mutt_hash_destroy(&mdata->uid_hash);
+  FREE(&mdata->msn_index);
+  mdata->msn_index_size = 0;
+  mdata->max_msn = 0;
 
   for (int i = 0; i < IMAP_CACHE_LEN; i++)
   {
@@ -198,11 +218,23 @@ void imap_mdata_free(void **ptr)
   }
 
   mutt_bcache_close(&mdata->bcache);
-  mutt_hash_destroy(&mdata->uid_hash);
+}
+
+/**
+ * imap_mdata_free - Release and clear storage in an ImapMboxData structure
+ * @param ptr Imap Mailbox data
+ */
+void imap_mdata_free(void **ptr)
+{
+  if (!ptr || !*ptr)
+    return;
+
+  struct ImapMboxData *mdata = *ptr;
+
+  imap_mdata_cache_reset(mdata);
   FREE(&mdata->name);
   FREE(&mdata->real_name);
   FREE(&mdata->munge_name);
-  FREE(&mdata->msn_index);
   FREE(ptr);
 }