Make moving IMAP articles faster in large groups
authorLars Ingebrigtsen <larsi@gnus.org>
Mon, 26 Jan 2015 02:50:20 +0000 (13:50 +1100)
committerLars Ingebrigtsen <larsi@gnus.org>
Mon, 26 Jan 2015 02:50:20 +0000 (13:50 +1100)
* lisp/gnus-group.el (gnus-group-get-new-news-this-group): Explicitly
request rescans when being run interactively.

* lisp/gnus-int.el (gnus-request-group-scan): New backend function.

* lisp/nnimap.el (nnimap-request-scan-group): Implement in on IMAP.

* lisp/nnimap.el (nnimap-request-group): Don't rescan the group here,
because that can be very slow in large groups.

lisp/ChangeLog
lisp/gnus-group.el
lisp/gnus-int.el
lisp/nnimap.el

index d62bfdf..0001120 100644 (file)
@@ -1,3 +1,15 @@
+2015-01-26  Lars Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-get-new-news-this-group): Explicitly
+       request rescans when being run interactively.
+
+       * nnimap.el (nnimap-request-group): Don't rescan the group here,
+       because that can be very slow in large groups.
+
+       * gnus-int.el (gnus-request-group-scan): New backend function.
+
+       * nnimap.el (nnimap-request-scan-group): Implement in on IMAP.
+
 2015-01-25  Lars Ingebrigtsen  <larsi@gnus.org>
 
        * gnus-group.el (gnus-group-suspend): Close all backends.
index dc11442..e22138b 100644 (file)
@@ -4075,7 +4075,9 @@ If DONT-SCAN is non-nil, scan non-activated groups as well."
       (gnus-group-remove-mark group)
       ;; Bypass any previous denials from the server.
       (gnus-remove-denial (setq method (gnus-find-method-for-group group)))
-      (if (gnus-activate-group group (if dont-scan nil 'scan) nil method)
+      (if (or (and (not dont-scan)
+                  (gnus-request-group-scan group (gnus-get-info group)))
+             (gnus-activate-group group (if dont-scan nil 'scan) nil method))
          (let ((info (gnus-get-info group))
                (active (gnus-active group)))
            (when info
index 487b85f..dd938ce 100644 (file)
@@ -439,6 +439,14 @@ If it is down, start it up (again)."
       (funcall (gnus-get-function gnus-command-method func)
               (gnus-group-real-name group) (nth 1 gnus-command-method)))))
 
+(defun gnus-request-group-scan (group info)
+  "Request that GROUP get a complete rescan."
+  (let ((gnus-command-method (gnus-find-method-for-group group))
+       (func 'request-group-description))
+    (when (gnus-check-backend-function func group)
+      (funcall (gnus-get-function gnus-command-method func)
+              (gnus-group-real-name group) (nth 1 gnus-command-method) info))))
+
 (defun gnus-close-group (group)
   "Request the GROUP be closed."
   (let ((gnus-command-method (inline (gnus-find-method-for-group group))))
index f3a8957..382e490 100644 (file)
@@ -792,43 +792,55 @@ textual parts.")
        articles active marks high low)
     (with-current-buffer nntp-server-buffer
       (when result
-       (if (and dont-check
-                (setq active (nth 2 (assoc group nnimap-current-infos))))
-           (insert (format "211 %d %d %d %S\n"
-                           (- (cdr active) (car active))
-                           (car active)
-                           (cdr active)
-                           group))
-         (with-current-buffer (nnimap-buffer)
-           (erase-buffer)
-           (let ((group-sequence
-                  (nnimap-send-command "SELECT %S" (utf7-encode group t)))
-                 (flag-sequence
-                  (nnimap-send-command "UID FETCH 1:* FLAGS")))
-             (setf (nnimap-group nnimap-object) group)
-             (nnimap-wait-for-response flag-sequence)
-             (setq marks
-                   (nnimap-flags-to-marks
-                    (nnimap-parse-flags
-                     (list (list group-sequence flag-sequence
-                                 1 group "SELECT")))))
-             (when (and info
-                        marks)
-               (nnimap-update-infos marks (list info))
-               (nnimap-store-info info (gnus-active (gnus-info-group info))))
-             (goto-char (point-max))
-             (let ((uidnext (nth 5 (car marks))))
-               (setq high (or (if uidnext
-                                   (1- uidnext)
-                                 (nth 3 (car marks)))
-                               0)
-                     low (or (nth 4 (car marks)) uidnext 1)))))
-         (erase-buffer)
-         (insert
-          (format
-           "211 %d %d %d %S\n" (1+ (- high low)) low high group)))
+       (when (or (not dont-check)
+                 (not (setq active
+                            (nth 2 (assoc group nnimap-current-infos)))))
+         (let ((sequences (nnimap-retrieve-group-data-early
+                           server (list info))))
+           (nnimap-finish-retrieve-group-infos server (list info) sequences
+                                               t)
+           (setq active (nth 2 (assoc group nnimap-current-infos)))))
+       (insert (format "211 %d %d %d %S\n"
+                       (- (cdr active) (car active))
+                       (car active)
+                       (cdr active)
+                       group))
        t))))
 
+(deffoo nnimap-request-scan-group (group &optional server info)
+  (setq group (nnimap-decode-gnus-group group))
+  (let (marks high low)
+    (with-current-buffer (nnimap-buffer)
+      (erase-buffer)
+      (let ((group-sequence
+            (nnimap-send-command "SELECT %S" (utf7-encode group t)))
+           (flag-sequence
+            (nnimap-send-command "UID FETCH 1:* FLAGS")))
+       (setf (nnimap-group nnimap-object) group)
+       (nnimap-wait-for-response flag-sequence)
+       (setq marks
+             (nnimap-flags-to-marks
+              (nnimap-parse-flags
+               (list (list group-sequence flag-sequence
+                           1 group "SELECT")))))
+       (when (and info
+                  marks)
+         (nnimap-update-infos marks (list info))
+         (nnimap-store-info info (gnus-active (gnus-info-group info))))
+       (goto-char (point-max))
+       (let ((uidnext (nth 5 (car marks))))
+         (setq high (or (if uidnext
+                            (1- uidnext)
+                          (nth 3 (car marks)))
+                        0)
+               low (or (nth 4 (car marks)) uidnext 1)))))
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (insert
+       (format
+       "211 %d %d %d %S\n" (1+ (- high low)) low high group))
+      t)))
+
 (deffoo nnimap-request-create-group (group &optional server args)
   (setq group (nnimap-decode-gnus-group group))
   (when (nnimap-change-group nil server)
@@ -1371,7 +1383,8 @@ If LIMIT, first try to limit the search to the N last articles."
        command
       (nth 2 quirk))))
 
-(deffoo nnimap-finish-retrieve-group-infos (server infos sequences)
+(deffoo nnimap-finish-retrieve-group-infos (server infos sequences
+                                                  &optional dont-insert)
   (when (and sequences
             (nnimap-change-group nil server t)
             ;; Check that the process is still alive.
@@ -1391,19 +1404,20 @@ If LIMIT, first try to limit the search to the N last articles."
                              (nnimap-parse-flags
                               (nreverse sequences)))
                             infos)
-       ;; Finally, just return something resembling an active file in
-       ;; the nntp buffer, so that the agent can save the info, too.
-       (with-current-buffer nntp-server-buffer
-         (erase-buffer)
-         (dolist (info infos)
-           (let* ((group (gnus-info-group info))
-                  (active (gnus-active group)))
-             (when active
-               (insert (format "%S %d %d y\n"
-                               (decode-coding-string
-                                (gnus-group-real-name group) 'utf-8)
-                               (cdr active)
-                               (car active)))))))))))
+       (unless dont-insert
+         ;; Finally, just return something resembling an active file in
+         ;; the nntp buffer, so that the agent can save the info, too.
+         (with-current-buffer nntp-server-buffer
+           (erase-buffer)
+           (dolist (info infos)
+             (let* ((group (gnus-info-group info))
+                    (active (gnus-active group)))
+               (when active
+                 (insert (format "%S %d %d y\n"
+                                 (decode-coding-string
+                                  (gnus-group-real-name group) 'utf-8)
+                                 (cdr active)
+                                 (car active))))))))))))
 
 (defun nnimap-update-infos (flags infos)
   (dolist (info infos)