comparison lisp/gnus/gnus-cache.el @ 82951:0fde48feb604

Import Gnus 5.10 from the v5_10 branch of the Gnus repository.
author Andreas Schwab <schwab@suse.de>
date Thu, 22 Jul 2004 16:45:51 +0000
parents 695cf19ef79e
children c5e16264557d cce1c0ee76ee
comparison
equal deleted inserted replaced
56503:8bbd2323fbf2 82951:0fde48feb604
1 ;;; gnus-cache.el --- cache interface for Gnus 1 ;;; gnus-cache.el --- cache interface for Gnus
2 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 2 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 ;; Free Software Foundation, Inc. 3 ;; Free Software Foundation, Inc.
4 4
5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> 5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
6 ;; Keywords: news 6 ;; Keywords: news
7 7
31 (require 'gnus) 31 (require 'gnus)
32 (require 'gnus-int) 32 (require 'gnus-int)
33 (require 'gnus-range) 33 (require 'gnus-range)
34 (require 'gnus-start) 34 (require 'gnus-start)
35 (eval-when-compile 35 (eval-when-compile
36 (if (not (fboundp 'gnus-agent-load-alist))
37 (defun gnus-agent-load-alist (group)))
36 (require 'gnus-sum)) 38 (require 'gnus-sum))
37 39
38 (defcustom gnus-cache-active-file 40 (defcustom gnus-cache-active-file
39 (expand-file-name "active" gnus-cache-directory) 41 (expand-file-name "active" gnus-cache-directory)
40 "*The cache active file." 42 "*The cache active file."
158 (setq group (car result) 160 (setq group (car result)
159 number (cdr result)))) 161 number (cdr result))))
160 (when (and number 162 (when (and number
161 (> number 0) ; Reffed article. 163 (> number 0) ; Reffed article.
162 (or force 164 (or force
163 (and (or (not gnus-cacheable-groups) 165 (and (gnus-cache-fully-p group)
164 (string-match gnus-cacheable-groups group))
165 (or (not gnus-uncacheable-groups)
166 (not (string-match
167 gnus-uncacheable-groups group)))
168 (gnus-cache-member-of-class 166 (gnus-cache-member-of-class
169 gnus-cache-enter-articles ticked dormant unread))) 167 gnus-cache-enter-articles ticked dormant unread)))
170 (not (file-exists-p (setq file (gnus-cache-file-name 168 (not (file-exists-p (setq file (gnus-cache-file-name
171 group number))))) 169 group number)))))
172 ;; Possibly create the cache directory. 170 ;; Possibly create the cache directory.
181 (gnus-article-decode-hook nil)) 179 (gnus-article-decode-hook nil))
182 (gnus-request-article-this-buffer number group)) 180 (gnus-request-article-this-buffer number group))
183 (when (> (buffer-size) 0) 181 (when (> (buffer-size) 0)
184 (let ((coding-system-for-write gnus-cache-coding-system)) 182 (let ((coding-system-for-write gnus-cache-coding-system))
185 (gnus-write-buffer file)) 183 (gnus-write-buffer file))
186 (setq headers (nnheader-parse-head t)) 184 (nnheader-remove-body)
185 (setq headers (nnheader-parse-naked-head))
187 (mail-header-set-number headers number) 186 (mail-header-set-number headers number)
188 (gnus-cache-change-buffer group) 187 (gnus-cache-change-buffer group)
189 (set-buffer (cdr gnus-cache-buffer)) 188 (set-buffer (cdr gnus-cache-buffer))
190 (goto-char (point-max)) 189 (goto-char (point-max))
191 (forward-line -1) 190 (forward-line -1)
207 (forward-line 1)) 206 (forward-line 1))
208 (beginning-of-line) 207 (beginning-of-line)
209 (nnheader-insert-nov headers) 208 (nnheader-insert-nov headers)
210 ;; Update the active info. 209 ;; Update the active info.
211 (set-buffer gnus-summary-buffer) 210 (set-buffer gnus-summary-buffer)
212 (gnus-cache-update-active group number) 211 (gnus-cache-possibly-update-active group (cons number number))
213 (push article gnus-newsgroup-cached) 212 (setq gnus-newsgroup-cached
213 (gnus-add-to-sorted-list gnus-newsgroup-cached article))
214 (gnus-summary-update-secondary-mark article)) 214 (gnus-summary-update-secondary-mark article))
215 t)))))) 215 t))))))
216 216
217 (defun gnus-cache-enter-remove-article (article) 217 (defun gnus-cache-enter-remove-article (article)
218 "Mark ARTICLE for later possible removal." 218 "Mark ARTICLE for later possible removal."
233 (gnus-cache-possibly-remove-articles-1))))) 233 (gnus-cache-possibly-remove-articles-1)))))
234 (setq gnus-cache-removable-articles nil))) 234 (setq gnus-cache-removable-articles nil)))
235 235
236 (defun gnus-cache-possibly-remove-articles-1 () 236 (defun gnus-cache-possibly-remove-articles-1 ()
237 "Possibly remove some of the removable articles." 237 "Possibly remove some of the removable articles."
238 (unless (eq gnus-use-cache 'passive) 238 (when (gnus-cache-fully-p gnus-newsgroup-name)
239 (let ((articles gnus-cache-removable-articles) 239 (let ((articles gnus-cache-removable-articles)
240 (cache-articles gnus-newsgroup-cached) 240 (cache-articles gnus-newsgroup-cached)
241 article) 241 article)
242 (gnus-cache-change-buffer gnus-newsgroup-name) 242 (gnus-cache-change-buffer gnus-newsgroup-name)
243 (while articles 243 (while articles
281 (if (not cached) 281 (if (not cached)
282 ;; No cached articles here, so we just retrieve them 282 ;; No cached articles here, so we just retrieve them
283 ;; the normal way. 283 ;; the normal way.
284 (let ((gnus-use-cache nil)) 284 (let ((gnus-use-cache nil))
285 (gnus-retrieve-headers articles group fetch-old)) 285 (gnus-retrieve-headers articles group fetch-old))
286 (let ((uncached-articles (gnus-sorted-intersection 286 (let ((uncached-articles (gnus-sorted-difference articles cached))
287 (gnus-sorted-complement articles cached)
288 articles))
289 (cache-file (gnus-cache-file-name group ".overview")) 287 (cache-file (gnus-cache-file-name group ".overview"))
290 type) 288 type)
291 ;; We first retrieve all the headers that we don't have in 289 ;; We first retrieve all the headers that we don't have in
292 ;; the cache. 290 ;; the cache.
293 (let ((gnus-use-cache nil)) 291 (let ((gnus-use-cache nil))
333 (gnus-summary-remove-process-mark article) 331 (gnus-summary-remove-process-mark article)
334 (if (natnump article) 332 (if (natnump article)
335 (when (gnus-cache-possibly-enter-article 333 (when (gnus-cache-possibly-enter-article
336 gnus-newsgroup-name article 334 gnus-newsgroup-name article
337 nil nil nil t) 335 nil nil nil t)
336 (setq gnus-newsgroup-undownloaded (delq article gnus-newsgroup-undownloaded))
338 (push article out)) 337 (push article out))
339 (gnus-message 2 "Can't cache article %d" article)) 338 (gnus-message 2 "Can't cache article %d" article))
339 (gnus-summary-update-download-mark article)
340 (gnus-summary-update-secondary-mark article)) 340 (gnus-summary-update-secondary-mark article))
341 (gnus-summary-next-subject 1) 341 (gnus-summary-next-subject 1)
342 (gnus-summary-position-point) 342 (gnus-summary-position-point)
343 (nreverse out))) 343 (nreverse out)))
344 344
345 (defun gnus-cache-remove-article (n) 345 (defun gnus-cache-remove-article (&optional n)
346 "Remove the next N articles from the cache. 346 "Remove the next N articles from the cache.
347 If not given a prefix, use the process marked articles instead. 347 If not given a prefix, use the process marked articles instead.
348 Returns the list of articles removed." 348 Returns the list of articles removed."
349 (interactive "P") 349 (interactive "P")
350 (gnus-cache-change-buffer gnus-newsgroup-name) 350 (gnus-cache-change-buffer gnus-newsgroup-name)
352 article out) 352 article out)
353 (while articles 353 (while articles
354 (setq article (pop articles)) 354 (setq article (pop articles))
355 (gnus-summary-remove-process-mark article) 355 (gnus-summary-remove-process-mark article)
356 (when (gnus-cache-possibly-remove-article article nil nil nil t) 356 (when (gnus-cache-possibly-remove-article article nil nil nil t)
357 (when gnus-newsgroup-agentized
358 (let ((alist (gnus-agent-load-alist gnus-newsgroup-name)))
359 (unless (cdr (assoc article alist))
360 (setq gnus-newsgroup-undownloaded
361 (gnus-add-to-sorted-list
362 gnus-newsgroup-undownloaded article)))))
357 (push article out)) 363 (push article out))
364 (gnus-summary-update-download-mark article)
358 (gnus-summary-update-secondary-mark article)) 365 (gnus-summary-update-secondary-mark article))
359 (gnus-summary-next-subject 1) 366 (gnus-summary-next-subject 1)
360 (gnus-summary-position-point) 367 (gnus-summary-position-point)
361 (nreverse out))) 368 (nreverse out)))
362 369
365 (memq article gnus-newsgroup-cached)) 372 (memq article gnus-newsgroup-cached))
366 373
367 (defun gnus-summary-insert-cached-articles () 374 (defun gnus-summary-insert-cached-articles ()
368 "Insert all the articles cached for this group into the current buffer." 375 "Insert all the articles cached for this group into the current buffer."
369 (interactive) 376 (interactive)
370 (let ((cached (sort (copy-sequence gnus-newsgroup-cached) '>)) 377 (let ((gnus-verbose (max 6 gnus-verbose)))
371 (gnus-verbose (max 6 gnus-verbose))) 378 (if (not gnus-newsgroup-cached)
372 (unless cached 379 (gnus-message 3 "No cached articles for this group")
373 (gnus-message 3 "No cached articles for this group")) 380 (gnus-summary-goto-subjects gnus-newsgroup-cached))))
374 (while cached 381
375 (gnus-summary-goto-subject (pop cached) t)))) 382 (defun gnus-summary-limit-include-cached ()
376 383 "Limit the summary buffer to articles that are cached."
377 (defalias 'gnus-summary-limit-include-cached 384 (interactive)
378 'gnus-summary-insert-cached-articles) 385 (let ((gnus-verbose (max 6 gnus-verbose)))
386 (if gnus-newsgroup-cached
387 (progn
388 (gnus-summary-limit gnus-newsgroup-cached)
389 (gnus-summary-position-point))
390 (gnus-message 3 "No cached articles for this group"))))
379 391
380 ;;; Internal functions. 392 ;;; Internal functions.
381 393
382 (defun gnus-cache-change-buffer (group) 394 (defun gnus-cache-change-buffer (group)
383 (and gnus-cache-buffer 395 (and gnus-cache-buffer
420 (let ((group (nnheader-replace-duplicate-chars-in-string 432 (let ((group (nnheader-replace-duplicate-chars-in-string
421 (nnheader-replace-chars-in-string group ?/ ?_) 433 (nnheader-replace-chars-in-string group ?/ ?_)
422 ?. ?_))) 434 ?. ?_)))
423 ;; Translate the first colon into a slash. 435 ;; Translate the first colon into a slash.
424 (when (string-match ":" group) 436 (when (string-match ":" group)
425 (aset group (match-beginning 0) ?/)) 437 (setq group (concat (substring group 0 (match-beginning 0))
438 "/" (substring group (match-end 0)))))
426 (nnheader-replace-chars-in-string group ?. ?/))) 439 (nnheader-replace-chars-in-string group ?. ?/)))
427 t) 440 t)
428 gnus-cache-directory)))) 441 gnus-cache-directory))))
429 442
430 (defun gnus-cache-update-article (group article) 443 (defun gnus-cache-update-article (group article)
458 (set-buffer (cdr gnus-cache-buffer)) 471 (set-buffer (cdr gnus-cache-buffer))
459 (goto-char (point-min)) 472 (goto-char (point-min))
460 (when (or (looking-at (concat (int-to-string number) "\t")) 473 (when (or (looking-at (concat (int-to-string number) "\t"))
461 (search-forward (concat "\n" (int-to-string number) "\t") 474 (search-forward (concat "\n" (int-to-string number) "\t")
462 (point-max) t)) 475 (point-max) t))
463 (delete-region (progn (beginning-of-line) (point)) 476 (gnus-delete-line)))
464 (progn (forward-line 1) (point))))) 477 (unless (setq gnus-newsgroup-cached
465 (setq gnus-newsgroup-cached 478 (delq article gnus-newsgroup-cached))
466 (delq article gnus-newsgroup-cached)) 479 (gnus-sethash gnus-newsgroup-name nil gnus-cache-active-hashtb)
480 (setq gnus-cache-active-altered t))
467 (gnus-summary-update-secondary-mark article) 481 (gnus-summary-update-secondary-mark article)
468 t))) 482 t)))
469 483
470 (defun gnus-cache-articles-in-group (group) 484 (defun gnus-cache-articles-in-group (group)
471 "Return a sorted list of cached articles in GROUP." 485 "Return a sorted list of cached articles in GROUP."
475 (setq articles 489 (setq articles
476 (sort (mapcar (lambda (name) (string-to-int name)) 490 (sort (mapcar (lambda (name) (string-to-int name))
477 (directory-files dir nil "^[0-9]+$" t)) 491 (directory-files dir nil "^[0-9]+$" t))
478 '<)) 492 '<))
479 ;; Update the cache active file, just to synch more. 493 ;; Update the cache active file, just to synch more.
480 (when articles 494 (if articles
481 (gnus-cache-update-active group (car articles) t) 495 (progn
482 (gnus-cache-update-active group (car (last articles)))) 496 (gnus-cache-update-active group (car articles) t)
497 (gnus-cache-update-active group (car (last articles))))
498 (when (gnus-gethash group gnus-cache-active-hashtb)
499 (gnus-sethash group nil gnus-cache-active-hashtb)
500 (setq gnus-cache-active-altered t)))
483 articles))) 501 articles)))
484 502
485 (defun gnus-cache-braid-nov (group cached &optional file) 503 (defun gnus-cache-braid-nov (group cached &optional file)
486 (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*")) 504 (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*"))
487 beg end) 505 beg end)
501 (while cached 519 (while cached
502 (while (and (not (eobp)) 520 (while (and (not (eobp))
503 (< (read (current-buffer)) (car cached))) 521 (< (read (current-buffer)) (car cached)))
504 (forward-line 1)) 522 (forward-line 1))
505 (beginning-of-line) 523 (beginning-of-line)
506 (save-excursion 524 (set-buffer cache-buf)
507 (set-buffer cache-buf) 525 (if (search-forward (concat "\n" (int-to-string (car cached)) "\t")
508 (if (search-forward (concat "\n" (int-to-string (car cached)) "\t") 526 nil t)
509 nil t) 527 (setq beg (gnus-point-at-bol)
510 (setq beg (progn (beginning-of-line) (point)) 528 end (progn (end-of-line) (point)))
511 end (progn (end-of-line) (point))) 529 (setq beg nil))
512 (setq beg nil))) 530 (set-buffer nntp-server-buffer)
513 (when beg 531 (when beg
514 (insert-buffer-substring cache-buf beg end) 532 (insert-buffer-substring cache-buf beg end)
515 (insert "\n")) 533 (insert "\n"))
516 (setq cached (cdr cached))) 534 (setq cached (cdr cached)))
517 (kill-buffer cache-buf))) 535 (kill-buffer cache-buf)))
529 (< (progn (goto-char (match-beginning 1)) 547 (< (progn (goto-char (match-beginning 1))
530 (read (current-buffer))) 548 (read (current-buffer)))
531 (car cached))) 549 (car cached)))
532 (search-forward "\n.\n" nil 'move)) 550 (search-forward "\n.\n" nil 'move))
533 (beginning-of-line) 551 (beginning-of-line)
534 (save-excursion 552 (set-buffer cache-buf)
535 (set-buffer cache-buf) 553 (erase-buffer)
536 (erase-buffer) 554 (let ((coding-system-for-read
537 (let ((coding-system-for-read 555 gnus-cache-coding-system))
538 gnus-cache-coding-system)) 556 (insert-file-contents (gnus-cache-file-name group (car cached))))
539 (insert-file-contents (gnus-cache-file-name group (car cached)))) 557 (goto-char (point-min))
540 (goto-char (point-min)) 558 (insert "220 ")
541 (insert "220 ") 559 (princ (car cached) (current-buffer))
542 (princ (car cached) (current-buffer)) 560 (insert " Article retrieved.\n")
543 (insert " Article retrieved.\n") 561 (search-forward "\n\n" nil 'move)
544 (search-forward "\n\n" nil 'move) 562 (delete-region (point) (point-max))
545 (delete-region (point) (point-max)) 563 (forward-char -1)
546 (forward-char -1) 564 (insert ".")
547 (insert ".")) 565 (set-buffer nntp-server-buffer)
548 (insert-buffer-substring cache-buf) 566 (insert-buffer-substring cache-buf)
549 (setq cached (cdr cached))) 567 (setq cached (cdr cached)))
550 (kill-buffer cache-buf))) 568 (kill-buffer cache-buf)))
551 569
552 ;;;###autoload 570 ;;;###autoload
602 gnus-cache-active-altered)) 620 gnus-cache-active-altered))
603 (gnus-write-active-file gnus-cache-active-file gnus-cache-active-hashtb t) 621 (gnus-write-active-file gnus-cache-active-file gnus-cache-active-hashtb t)
604 ;; Mark the active hashtb as unaltered. 622 ;; Mark the active hashtb as unaltered.
605 (setq gnus-cache-active-altered nil))) 623 (setq gnus-cache-active-altered nil)))
606 624
625 (defun gnus-cache-possibly-update-active (group active)
626 "Update active info bounds of GROUP with ACTIVE if necessary.
627 The update is performed if ACTIVE contains a higher or lower bound
628 than the current."
629 (let ((lower t) (higher t))
630 (if gnus-cache-active-hashtb
631 (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb)))
632 (when cache-active
633 (unless (< (car active) (car cache-active))
634 (setq lower nil))
635 (unless (> (cdr active) (cdr cache-active))
636 (setq higher nil))))
637 (gnus-cache-read-active))
638 (when lower
639 (gnus-cache-update-active group (car active) t))
640 (when higher
641 (gnus-cache-update-active group (cdr active)))))
642
607 (defun gnus-cache-update-active (group number &optional low) 643 (defun gnus-cache-update-active (group number &optional low)
608 "Update the upper bound of the active info of GROUP to NUMBER. 644 "Update the upper bound of the active info of GROUP to NUMBER.
609 If LOW, update the lower bound instead." 645 If LOW, update the lower bound instead."
610 (let ((active (gnus-gethash group gnus-cache-active-hashtb))) 646 (let ((active (gnus-gethash group gnus-cache-active-hashtb)))
611 (if (null active) 647 (if (null active)
639 nums alphs) 675 nums alphs)
640 (when top 676 (when top
641 (gnus-message 5 "Generating the cache active file...") 677 (gnus-message 5 "Generating the cache active file...")
642 (setq gnus-cache-active-hashtb (gnus-make-hashtable 123))) 678 (setq gnus-cache-active-hashtb (gnus-make-hashtable 123)))
643 (when (string-match "^\\(nn[^_]+\\)_" group) 679 (when (string-match "^\\(nn[^_]+\\)_" group)
644 (setq group (replace-match "\\1:" t t group))) 680 (setq group (replace-match "\\1:" t nil group)))
645 ;; Separate articles from all other files and directories. 681 ;; Separate articles from all other files and directories.
646 (while files 682 (while files
647 (if (string-match "^[0-9]+$" (file-name-nondirectory (car files))) 683 (if (string-match "^[0-9]+$" (file-name-nondirectory (car files)))
648 (push (string-to-int (file-name-nondirectory (pop files))) nums) 684 (push (string-to-int (file-name-nondirectory (pop files))) nums)
649 (push (pop files) alphs))) 685 (push (pop files) alphs)))
668 (defun gnus-cache-generate-nov-databases (dir) 704 (defun gnus-cache-generate-nov-databases (dir)
669 "Generate NOV files recursively starting in DIR." 705 "Generate NOV files recursively starting in DIR."
670 (interactive (list gnus-cache-directory)) 706 (interactive (list gnus-cache-directory))
671 (gnus-cache-close) 707 (gnus-cache-close)
672 (let ((nnml-generate-active-function 'identity)) 708 (let ((nnml-generate-active-function 'identity))
673 (nnml-generate-nov-databases-1 dir))) 709 (nnml-generate-nov-databases-1 dir))
710 (gnus-cache-open))
674 711
675 (defun gnus-cache-move-cache (dir) 712 (defun gnus-cache-move-cache (dir)
676 "Move the cache tree to somewhere else." 713 "Move the cache tree to somewhere else."
677 (interactive "FMove the cache tree to: ") 714 (interactive "FMove the cache tree to: ")
678 (rename-file gnus-cache-directory dir)) 715 (rename-file gnus-cache-directory dir))
679 716
717 (defun gnus-cache-fully-p (&optional group)
718 "Returns non-nil if the cache should be fully used.
719 If GROUP is non-nil, also cater to `gnus-cacheable-groups' and
720 `gnus-uncacheable-groups'."
721 (and gnus-use-cache
722 (not (eq gnus-use-cache 'passive))
723 (if (null group)
724 t
725 (and (or (not gnus-cacheable-groups)
726 (string-match gnus-cacheable-groups group))
727 (or (not gnus-uncacheable-groups)
728 (not (string-match gnus-uncacheable-groups group)))))))
729
680 (provide 'gnus-cache) 730 (provide 'gnus-cache)
681 731
682 ;;; arch-tag: 05a79442-8c58-4e65-bd0a-3cbb1b89a33a 732 ;;; arch-tag: 05a79442-8c58-4e65-bd0a-3cbb1b89a33a
683 ;;; gnus-cache.el ends here 733 ;;; gnus-cache.el ends here