X-Git-Url: http://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fgnus-cache.el;h=aa377cdea53758b5f12e88eeae5d1191b56b9a4a;hp=ed2f79ff7a3608ee42e0f9f399462ce273b68e51;hb=125d88b46ad2efa065f06d5dac37a245b488985a;hpb=ee4a7be24fb6982b5baa5eafb65178ccaca6df50 diff --git a/lisp/gnus-cache.el b/lisp/gnus-cache.el index ed2f79ff7..aa377cdea 100644 --- a/lisp/gnus-cache.el +++ b/lisp/gnus-cache.el @@ -1,5 +1,5 @@ ;;; gnus-cache.el --- cache interface for Gnus -;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 ;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen @@ -29,10 +29,9 @@ (eval-when-compile (require 'cl)) (require 'gnus) -(require 'gnus-int) -(require 'gnus-range) -(require 'gnus-start) (eval-when-compile + (unless (fboundp 'gnus-agent-load-alist) + (defun gnus-agent-load-alist (group))) (require 'gnus-sum)) (defcustom gnus-cache-active-file @@ -89,6 +88,7 @@ it's not cached." (defvar gnus-cache-buffer nil) (defvar gnus-cache-active-hashtb nil) (defvar gnus-cache-active-altered nil) +(defvar gnus-cache-total-fetched-hashtb nil) (eval-and-compile (autoload 'nnml-generate-nov-databases-1 "nnml") @@ -123,9 +123,9 @@ it's not cached." (overview-file (gnus-cache-file-name (car gnus-cache-buffer) ".overview"))) ;; write the overview only if it was modified - (when (buffer-modified-p buffer) - (save-excursion - (set-buffer buffer) + (when (and (buffer-live-p buffer) + (buffer-modified-p buffer)) + (with-current-buffer buffer (if (> (buffer-size) 0) ;; Non-empty overview, write it to a file. (let ((coding-system-for-write @@ -140,7 +140,10 @@ it's not cached." ;; of any inconsistencies (articles w/o nov entries?). ;; for now, just be conservative...delete only if safe -- sj (delete-directory (file-name-directory overview-file)) - (error nil))))) + (error))) + + (gnus-cache-update-overview-total-fetched-for + (car gnus-cache-buffer) overview-file))) ;; Kill the buffer -- it's either unmodified or saved. (gnus-kill-buffer buffer) (setq gnus-cache-buffer nil)))) @@ -150,7 +153,8 @@ it's not cached." (when (and (or force (not (eq gnus-use-cache 'passive))) (numberp article) (> article 0)) ; This might be a dummy article. - (let ((number article) file headers) + (let ((number article) + file headers lines-chars) ;; If this is a virtual group, we find the real group. (when (gnus-virtual-group-p group) (let ((result (nnvirtual-find-group-art @@ -178,9 +182,14 @@ it's not cached." (gnus-request-article-this-buffer number group)) (when (> (buffer-size) 0) (let ((coding-system-for-write gnus-cache-coding-system)) - (gnus-write-buffer file)) - (setq headers (nnheader-parse-head t)) + (gnus-write-buffer file) + (gnus-cache-update-file-total-fetched-for group file)) + (setq lines-chars (nnheader-get-lines-and-char)) + (nnheader-remove-body) + (setq headers (nnheader-parse-naked-head)) (mail-header-set-number headers number) + (mail-header-set-lines headers (car lines-chars)) + (mail-header-set-chars headers (cadr lines-chars)) (gnus-cache-change-buffer group) (set-buffer (cdr gnus-cache-buffer)) (goto-char (point-max)) @@ -330,14 +339,16 @@ Returns the list of articles entered." (when (gnus-cache-possibly-enter-article gnus-newsgroup-name article nil nil nil t) + (setq gnus-newsgroup-undownloaded (delq article gnus-newsgroup-undownloaded)) (push article out)) (gnus-message 2 "Can't cache article %d" article)) + (gnus-summary-update-download-mark article) (gnus-summary-update-secondary-mark article)) (gnus-summary-next-subject 1) (gnus-summary-position-point) (nreverse out))) -(defun gnus-cache-remove-article (n) +(defun gnus-cache-remove-article (&optional n) "Remove the next N articles from the cache. If not given a prefix, use the process marked articles instead. Returns the list of articles removed." @@ -349,7 +360,14 @@ Returns the list of articles removed." (setq article (pop articles)) (gnus-summary-remove-process-mark article) (when (gnus-cache-possibly-remove-article article nil nil nil t) + (when gnus-newsgroup-agentized + (let ((alist (gnus-agent-load-alist gnus-newsgroup-name))) + (unless (cdr (assoc article alist)) + (setq gnus-newsgroup-undownloaded + (gnus-add-to-sorted-list + gnus-newsgroup-undownloaded article))))) (push article out)) + (gnus-summary-update-download-mark article) (gnus-summary-update-secondary-mark article)) (gnus-summary-next-subject 1) (gnus-summary-position-point) @@ -362,15 +380,10 @@ Returns the list of articles removed." (defun gnus-summary-insert-cached-articles () "Insert all the articles cached for this group into the current buffer." (interactive) - (let ((cached gnus-newsgroup-cached) - (gnus-verbose (max 6 gnus-verbose))) - (if (not cached) + (let ((gnus-verbose (max 6 gnus-verbose))) + (if (not gnus-newsgroup-cached) (gnus-message 3 "No cached articles for this group") - (save-excursion - (while cached - (gnus-summary-goto-subject (pop cached) t))) - (gnus-summary-limit (append gnus-newsgroup-cached gnus-newsgroup-limit)) - (gnus-summary-position-point)))) + (gnus-summary-goto-subjects gnus-newsgroup-cached)))) (defun gnus-summary-limit-include-cached () "Limit the summary buffer to articles that are cached." @@ -460,14 +473,15 @@ Returns the list of articles removed." (gnus-cache-member-of-class gnus-cache-remove-articles ticked dormant unread))) (save-excursion + (gnus-cache-update-file-total-fetched-for group file t) (delete-file file) + (set-buffer (cdr gnus-cache-buffer)) (goto-char (point-min)) (when (or (looking-at (concat (int-to-string number) "\t")) (search-forward (concat "\n" (int-to-string number) "\t") (point-max) t)) - (delete-region (progn (beginning-of-line) (point)) - (progn (forward-line 1) (point))))) + (gnus-delete-line))) (unless (setq gnus-newsgroup-cached (delq article gnus-newsgroup-cached)) (gnus-sethash gnus-newsgroup-name nil gnus-cache-active-hashtb) @@ -518,7 +532,7 @@ Returns the list of articles removed." (set-buffer cache-buf) (if (search-forward (concat "\n" (int-to-string (car cached)) "\t") nil t) - (setq beg (progn (beginning-of-line) (point)) + (setq beg (point-at-bol) end (progn (end-of-line) (point))) (setq beg nil)) (set-buffer nntp-server-buffer) @@ -671,7 +685,7 @@ If LOW, update the lower bound instead." (gnus-message 5 "Generating the cache active file...") (setq gnus-cache-active-hashtb (gnus-make-hashtable 123))) (when (string-match "^\\(nn[^_]+\\)_" group) - (setq group (replace-match "\\1:" t t group))) + (setq group (replace-match "\\1:" t nil group))) ;; Separate articles from all other files and directories. (while files (if (string-match "^[0-9]+$" (file-name-nondirectory (car files))) @@ -701,6 +715,9 @@ If LOW, update the lower bound instead." (gnus-cache-close) (let ((nnml-generate-active-function 'identity)) (nnml-generate-nov-databases-1 dir)) + + (setq gnus-cache-total-fetched-hashtb nil) + (gnus-cache-open)) (defun gnus-cache-move-cache (dir) @@ -721,6 +738,127 @@ If GROUP is non-nil, also cater to `gnus-cacheable-groups' and (or (not gnus-uncacheable-groups) (not (string-match gnus-uncacheable-groups group))))))) +;;;###autoload +(defun gnus-cache-rename-group (old-group new-group) + "Rename OLD-GROUP as NEW-GROUP. Always updates the cache, even when +disabled, as the old cache files would corrupt gnus when the cache was +next enabled. Depends upon the caller to determine whether group renaming is supported." + (let ((old-dir (gnus-cache-file-name old-group "")) + (new-dir (gnus-cache-file-name new-group ""))) + (gnus-rename-file old-dir new-dir t)) + + (gnus-cache-rename-group-total-fetched-for old-group new-group) + + (let ((no-save gnus-cache-active-hashtb)) + (unless gnus-cache-active-hashtb + (gnus-cache-read-active)) + (let* ((old-group-hash-value (gnus-gethash old-group gnus-cache-active-hashtb)) + (new-group-hash-value (gnus-gethash new-group gnus-cache-active-hashtb)) + (delta (or old-group-hash-value new-group-hash-value))) + (gnus-sethash new-group old-group-hash-value gnus-cache-active-hashtb) + (gnus-sethash old-group nil gnus-cache-active-hashtb) + + (if no-save + (setq gnus-cache-active-altered delta) + (gnus-cache-write-active delta))))) + +;;;###autoload +(defun gnus-cache-delete-group (group) + "Delete GROUP. Always updates the cache, even when +disabled, as the old cache files would corrupt gnus when the cache was +next enabled. Depends upon the caller to determine whether group deletion is supported." + (let ((dir (gnus-cache-file-name group ""))) + (gnus-delete-file dir)) + + (gnus-cache-delete-group-total-fetched-for group) + + (let ((no-save gnus-cache-active-hashtb)) + (unless gnus-cache-active-hashtb + (gnus-cache-read-active)) + (let* ((group-hash-value (gnus-gethash group gnus-cache-active-hashtb))) + (gnus-sethash group nil gnus-cache-active-hashtb) + + (if no-save + (setq gnus-cache-active-altered group-hash-value) + (gnus-cache-write-active group-hash-value))))) + +(defvar gnus-cache-inhibit-update-total-fetched-for nil) +(defvar gnus-cache-need-update-total-fetched-for nil) + +(defmacro gnus-cache-with-refreshed-group (group &rest body) + `(prog1 (let ((gnus-cache-inhibit-update-total-fetched-for t)) + ,@body) + (when (and gnus-cache-need-update-total-fetched-for + (not gnus-cache-inhibit-update-total-fetched-for)) + (save-excursion + (set-buffer gnus-group-buffer) + (setq gnus-cache-need-update-total-fetched-for nil) + (gnus-group-update-group ,group t))))) + +(defun gnus-cache-update-file-total-fetched-for (group file &optional subtract) + (when gnus-cache-total-fetched-hashtb + (gnus-cache-with-refreshed-group + group + (let* ((entry (or (gnus-gethash group gnus-cache-total-fetched-hashtb) + (gnus-sethash group (make-vector 2 0) + gnus-cache-total-fetched-hashtb))) + size) + + (if file + (setq size (or (nth 7 (file-attributes file)) 0)) + (let ((files (directory-files (gnus-cache-file-name group "") + t nil t)) + file attrs) + (setq size 0.0) + (while (setq file (pop files)) + (setq attrs (file-attributes file)) + (unless (nth 0 attrs) + (incf size (float (nth 7 attrs))))))) + + (setq gnus-cache-need-update-total-fetched-for t) + + (incf (nth 1 entry) (if subtract (- size) size)))))) + +(defun gnus-cache-update-overview-total-fetched-for (group file) + (when gnus-cache-total-fetched-hashtb + (gnus-cache-with-refreshed-group + group + (let* ((entry (or (gnus-gethash group gnus-cache-total-fetched-hashtb) + (gnus-sethash group (make-list 2 0) + gnus-cache-total-fetched-hashtb))) + (size (or (nth 7 (file-attributes + (or file + (gnus-cache-file-name group ".overview")))) + 0))) + (setq gnus-cache-need-update-total-fetched-for t) + (setf (nth 0 entry) size))))) + +(defun gnus-cache-rename-group-total-fetched-for (old-group new-group) + "Record of disk space used by OLD-GROUP now associated with NEW-GROUP." + (when gnus-cache-total-fetched-hashtb + (let ((entry (gnus-gethash old-group gnus-cache-total-fetched-hashtb))) + (gnus-sethash new-group entry gnus-cache-total-fetched-hashtb) + (gnus-sethash old-group nil gnus-cache-total-fetched-hashtb)))) + +(defun gnus-cache-delete-group-total-fetched-for (group) + "Delete record of disk space used by GROUP being deleted." + (when gnus-cache-total-fetched-hashtb + (gnus-sethash group nil gnus-cache-total-fetched-hashtb))) + +(defun gnus-cache-total-fetched-for (group &optional no-inhibit) + "Get total disk space used by the cache for the specified GROUP." + (unless gnus-cache-total-fetched-hashtb + (setq gnus-cache-total-fetched-hashtb (gnus-make-hashtable 1024))) + + (let* ((entry (gnus-gethash group gnus-cache-total-fetched-hashtb))) + (if entry + (apply '+ entry) + (let ((gnus-cache-inhibit-update-total-fetched-for (not no-inhibit))) + (+ + (gnus-cache-update-overview-total-fetched-for group nil) + (gnus-cache-update-file-total-fetched-for group nil)))))) + (provide 'gnus-cache) +;;; arch-tag: 05a79442-8c58-4e65-bd0a-3cbb1b89a33a ;;; gnus-cache.el ends here