-(defun elmo-dop-prefetch-msgs (folder msgs)
- (save-match-data
- (elmo-dop-queue-append folder "prefetch-msgs" msgs)))
-
-(defun elmo-dop-list-folder (folder)
- (if (or (memq (elmo-folder-get-type folder)
- '(imap4 nntp pop3 filter pipe))
- (and (elmo-multi-p folder) (not (elmo-folder-local-p folder))))
- (if elmo-enable-disconnected-operation
- (let* ((number-alist (elmo-msgdb-number-load
- (elmo-msgdb-expand-path folder)))
- (number-list (mapcar 'car number-alist))
- (append-list (elmo-dop-append-list-load folder))
- (append-num (length append-list))
- alreadies
- (i 0)
- max-num)
- (while append-list
- (if (rassoc (car append-list) number-alist)
- (setq alreadies (append alreadies
- (list (car append-list)))))
- (setq append-list (cdr append-list)))
- (setq append-num (- append-num (length alreadies)))
- (setq max-num
- (or (nth (max (- (length number-list) 1) 0)
- number-list) 0))
- (while (< i append-num)
- (setq number-list
- (append number-list
- (list (+ max-num i 1))))
- (setq i (+ 1 i)))
- number-list)
- (error "Unplugged"))
- ;; not imap4 folder...list folder
- (elmo-call-func folder "list-folder")))
-
-(defun elmo-dop-count-appended (folder)
- (length (elmo-dop-append-list-load folder)))
-
-(defun elmo-dop-call-func-on-msgs (folder func-name msgs msgdb)
- (let ((append-list (elmo-dop-append-list-load folder))
- (number-alist (elmo-msgdb-get-number-alist msgdb))
- matched)
- (if (eq (elmo-folder-get-type folder) 'imap4)
- (progn
- (while append-list
- (if (setq matched (car (rassoc (car append-list) number-alist)))
- (setq msgs (delete matched msgs)))
- (setq append-list (cdr append-list)))
- (if msgs
- (elmo-dop-queue-append folder func-name msgs)))
- ;; maildir... XXX hard coding.....
- (if (not (featurep 'elmo-maildir))
- (require 'maildir))
- (funcall (intern (format "elmo-maildir-%s" func-name))
- (elmo-folder-get-spec folder)
- msgs msgdb))))
-
-(defun elmo-dop-max-of-folder (folder)
- (if (eq (elmo-folder-get-type folder) 'imap4)
- (if elmo-enable-disconnected-operation
- (let* ((number-alist (elmo-msgdb-number-load
- (elmo-msgdb-expand-path folder)))
- (number-list (mapcar 'car number-alist))
- (append-list (elmo-dop-append-list-load folder))
- (append-num (length append-list))
- alreadies
- (i 0)
- max-num)
- (while append-list
- (if (rassoc (car append-list) number-alist)
- (setq alreadies (append alreadies
- (list (car append-list)))))
- (setq append-list (cdr append-list)))
- (setq max-num
- (or (nth (max (- (length number-list) 1) 0) number-list)
- 0))
- (cons (- (+ max-num append-num) (length alreadies))
- (- (+ (length number-list) append-num) (length alreadies))))
- (error "Unplugged"))
- ;; not imap4 folder.
- (elmo-call-func folder "max-of-folder")))
-
-(defun elmo-dop-save-pending-messages (folder)
- (message (format "Saving queued message in %s..." elmo-lost+found-folder))
- (let* ((append-list (elmo-dop-append-list-load folder))
- file-string)
- (while append-list
- (when (setq file-string (elmo-get-file-string ; message string
- (elmo-cache-get-path
- (car append-list))))
- (elmo-append-msg elmo-lost+found-folder file-string)
- (elmo-dop-unlock-message (car append-list)))
- (setq append-list (cdr append-list))
- (elmo-dop-append-list-save folder nil)))
- (message (format "Saving queued message in %s...done."
- elmo-lost+found-folder)))
-
-(defun elmo-dop-flush-pending-append-operations (folder &optional appends resume)
- (message "Appending queued messages...")
- (let* ((append-list (or appends
- (elmo-dop-append-list-load folder)))
- (appendings append-list)
- (i 0)
- (num (length append-list))
- failure file-string)
- (when resume
- ;; Resume msgdb changed by elmo-dop-msgdb-create.
- (let* ((resumed-list (elmo-dop-append-list-load folder t))
- (number-alist (elmo-msgdb-number-load
- (elmo-msgdb-expand-path folder)))
- (appendings append-list)
- pair dels)
- (while appendings
- (if (setq pair (rassoc (car appendings) number-alist))
- (setq resumed-list (append resumed-list
- (list (car appendings)))))
- (setq appendings (cdr appendings)))
- (elmo-dop-append-list-save folder resumed-list t)))
- (while appendings
- (setq failure nil)
- (setq file-string (elmo-get-file-string ; message string
- (elmo-cache-get-path
- (car appendings))))
- (when file-string
- (condition-case ()
- (elmo-append-msg folder file-string (car appendings))
- (quit (setq failure t))
- (error (setq failure t)))
- (setq i (+ 1 i))
- (message (format "Appending queued messages...%d" i))
- (if failure
- (elmo-append-msg elmo-lost+found-folder
- file-string (car appendings))))
- (elmo-dop-unlock-message (car appendings))
- (setq appendings (cdr appendings)))
- ;; All pending append operation is flushed.
- (elmo-dop-append-list-save folder nil)
- (elmo-commit folder)
- (unless resume
- ;; delete '(folder "append-operations") in elmo-dop-queue.
- (let (elmo-dop-queue)
- (elmo-dop-queue-load)
- (setq elmo-dop-queue (delete (list folder "append-operations" nil)
- elmo-dop-queue))
- (elmo-dop-queue-save))))
- (message "Appending queued messages...done."))
-
-(defun elmo-dop-folder-exists-p (folder)
- (if (and elmo-enable-disconnected-operation
- (eq (elmo-folder-get-type folder) 'imap4))
- (file-exists-p (elmo-msgdb-expand-path folder))
- (elmo-call-func folder "folder-exists-p")))
-
-(defun elmo-dop-create-folder (folder)
- (if (eq (elmo-folder-get-type folder) 'imap4)
- (if elmo-enable-disconnected-operation
- (elmo-dop-queue-append folder "create-folder-maybe" nil)
- (error "Unplugged"))
- (elmo-call-func folder "create-folder")))
-
-(defun elmo-dop-delete-folder (folder)
- (error "Unplugged"))
-
-(defun elmo-dop-rename-folder (old-folder new-folder)
- (error "Unplugged"))
-
-(defun elmo-dop-append-msg (folder string message-id &optional msg)
- (if elmo-enable-disconnected-operation
- (if message-id
- (progn
- (unless (elmo-cache-exists-p message-id)
- (elmo-set-work-buf
- (insert string)
- (elmo-cache-save message-id nil folder msg (current-buffer))))
- (let ((append-list (elmo-dop-append-list-load folder))
- (number-alist (elmo-msgdb-number-load
- (elmo-msgdb-expand-path folder))))
- (when (and ; not in current folder.
- (not (rassoc message-id number-alist))
- (not (member message-id append-list)))
- (setq append-list
- (append append-list (list message-id)))
- (elmo-dop-lock-message message-id)
- (elmo-dop-append-list-save folder append-list)
- (elmo-dop-queue-append folder "append-operations" nil))
- t))
- nil)
- (error "Unplugged")))
-
-(defalias 'elmo-dop-msgdb-create 'elmo-dop-msgdb-create-as-numlist)
-
-(defun elmo-dop-msgdb-create-as-numlist (folder numlist new-mark already-mark
- seen-mark important-mark
- seen-list)
- (if (or (eq (elmo-folder-get-type folder) 'imap4)
- (eq (elmo-folder-get-type folder) 'nntp))
- (if elmo-enable-disconnected-operation
- (let* ((num-alist (elmo-msgdb-number-load
- (elmo-msgdb-expand-path folder)))
- (number-list (mapcar 'car num-alist))
- (ov (elmo-msgdb-overview-load
- (elmo-msgdb-expand-path folder)))
- (append-list (elmo-dop-append-list-load folder))
- (num (length numlist))
- (i 0)
- overview number-alist mark-alist msgid ov-entity
- max-num percent seen gmark)
- (setq max-num
- (or (nth (max (- (length number-list) 1) 0) number-list)
- 0))
- (while numlist
- (if (setq msgid
- (nth (+ (length append-list)
- (- (car numlist) max-num 1 num))
- append-list))
- (progn
- (setq overview
- (elmo-msgdb-append-element
- overview
- (elmo-localdir-msgdb-create-overview-entity-from-file
- (car numlist)
- (elmo-cache-get-path msgid))))
- (setq number-alist
- (elmo-msgdb-number-add number-alist
- (car numlist) msgid))
- (setq seen (member msgid seen-list))
- (if (setq gmark
- (or (elmo-msgdb-global-mark-get msgid)
- (if (elmo-cache-exists-p
- msgid
- folder
- (car number-alist))
- (if seen
- nil
- already-mark)
- (if seen
- seen-mark)
- new-mark)))
- (setq mark-alist
- (elmo-msgdb-mark-append
- mark-alist (car numlist) gmark))))
-
- (when (setq ov-entity (assoc
- (cdr (assq (car numlist) num-alist))
- ov))
- (setq overview
- (elmo-msgdb-append-element
- overview ov-entity))
- (setq number-alist
- (elmo-msgdb-number-add number-alist
- (car numlist)
- (car ov-entity)))
- (setq seen (member ov-entity seen-list))
- (if (setq gmark
- (or (elmo-msgdb-global-mark-get (car ov-entity))
- (if (elmo-cache-exists-p
- msgid
- folder
- (car ov-entity))
- (if seen
- nil
- already-mark)
- (if seen
- seen-mark)
- new-mark)))
- (setq mark-alist
- (elmo-msgdb-mark-append
- mark-alist (car numlist) gmark)))))
- (setq i (1+ i))
- (setq percent (/ (* i 100) num))
- (elmo-display-progress
- 'elmo-dop-msgdb-create-as-numlist "Creating msgdb..."
- percent)
- (setq numlist (cdr numlist)))
- (list overview number-alist mark-alist))
- (error "Unplugged"))
- ;; not imap4 folder...
- (elmo-call-func folder "msgdb-create" numlist new-mark already-mark
- seen-mark important-mark seen-list)))
-
-(provide 'elmo-dop)
+(defsubst elmo-message-encache-dop (folder number &optional read)
+ (elmo-dop-queue-append folder 'elmo-message-encache (list number read)))
+
+(defsubst elmo-folder-create-dop (folder)
+ (elmo-dop-queue-append folder 'elmo-folder-create-dop-delayed nil))
+
+(defsubst elmo-folder-set-flag-dop (folder numbers flag)
+ (when (setq numbers (elmo-dop-filter-pending-messages numbers))
+ (let ((method (case flag
+ (unread
+ 'elmo-folder-unset-read-delayed)
+ (read
+ 'elmo-folder-set-read-delayed)
+ (important
+ 'elmo-folder-set-important-delayed)
+ (answered
+ 'elmo-folder-set-answered-delayed))))
+ (if method
+ (elmo-dop-queue-append folder method (list numbers))
+ (elmo-dop-queue-append folder 'elmo-folder-set-flag
+ (list numbers flag))))))
+
+(defsubst elmo-folder-unset-flag-dop (folder numbers flag)
+ (when (setq numbers (elmo-dop-filter-pending-messages numbers))
+ (let ((method (case flag
+ (unread
+ 'elmo-folder-set-read-delayed)
+ (read
+ 'elmo-folder-unset-read-delayed)
+ (important
+ 'elmo-folder-unset-important-delayed)
+ (answered
+ 'elmo-folder-unset-answered-delayed))))
+ (if method
+ (elmo-dop-queue-append folder method (list numbers))
+ (elmo-dop-queue-append folder 'elmo-folder-unset-flag
+ (list numbers flag))))))
+
+;;; Execute as subsutitute for plugged operation.
+(defun elmo-folder-status-dop (folder)
+ (let ((number-list (elmo-folder-list-messages folder nil 'in-msgdb))
+ (spool-folder (elmo-dop-spool-folder folder))
+ spool-length
+ max-num)
+ (setq spool-length (or (if (elmo-folder-exists-p spool-folder)
+ (car (elmo-folder-status spool-folder)))
+ 0))
+ (setq max-num (if number-list (apply #'max number-list) 0))
+ (cons (+ max-num spool-length) (+ (length number-list) spool-length))))
+
+(defun elmo-folder-next-message-number-dop (folder)
+ (let ((number-list (elmo-folder-list-messages folder nil 'in-msgdb))
+ (spool-folder (elmo-dop-spool-folder folder))
+ spool-length
+ max-num)
+ (setq spool-length (or (if (elmo-folder-exists-p spool-folder)
+ (car (elmo-folder-status spool-folder)))
+ 0))
+ (setq max-num (if number-list (apply #'max number-list) 0))
+ (+ max-num spool-length)))
+
+;;; Delayed operation (executed at online status).
+(defun elmo-folder-append-buffer-dop-delayed (folder flag number set-number)
+ (let ((spool-folder (elmo-dop-spool-folder folder))
+ flags)
+ (with-temp-buffer
+ (when (elmo-message-fetch spool-folder number
+ (elmo-make-fetch-strategy 'entire)
+ 'unread)
+ (setq flags (or (elmo-message-flags-for-append folder (* -1 number))
+ (cond ((listp flag)
+ flag)
+ ;; for compatibility with 2.11.12 or earlier
+ ((eq flag t)
+ nil)
+ (t
+ (list flag)))))
+ (when (or (condition-case nil
+ (elmo-folder-append-buffer folder flags set-number)
+ (error))
+ ;; Append failed...
+ (elmo-folder-append-buffer
+ (elmo-make-folder elmo-lost+found-folder)
+ flags))
+ (elmo-folder-delete-messages spool-folder (list number)))))
+ ;; ignore failure (already dequed)
+ t))
+
+(defun elmo-folder-delete-messages-dop-delayed (folder number-alist)
+ (ignore-errors
+ (elmo-folder-delete-messages
+ folder
+ ;; messages are deleted only if message-id is not changed.
+ (mapcar 'car
+ (elmo-delete-if
+ (lambda (pair)
+ (not (string=
+ (cdr pair)
+ (elmo-message-fetch-field folder (car pair)
+ 'message-id))))
+ number-alist)))
+ t)) ; Always success (If failure, just remain)
+
+(defun elmo-folder-create-dop-delayed (folder)
+ (unless (elmo-folder-exists-p folder)
+ (elmo-folder-create folder)))
+
+(defun elmo-folder-set-important-delayed (folder numbers)
+ (elmo-folder-set-flag folder numbers 'important))
+
+(defun elmo-folder-unset-important-delayed (folder numbers)
+ (elmo-folder-unset-flag folder numbers 'important))
+
+(defun elmo-folder-set-read-delayed (folder numbers)
+ (elmo-folder-unset-flag folder numbers 'unread))
+
+(defun elmo-folder-unset-read-delayed (folder numbers)
+ (elmo-folder-set-flag folder numbers 'unread))
+
+(defun elmo-folder-set-answered-delayed (folder numbers)
+ (elmo-folder-set-flag folder numbers 'answered))
+
+(defun elmo-folder-unset-answered-delayed (folder numbers)
+ (elmo-folder-unset-flag folder numbers 'answered))
+
+;;; Util
+(defun elmo-dop-msgdb (msgdb)
+ (let ((new-db (elmo-make-msgdb))
+ entity)
+ (dolist (dop-entity (mapcar
+ (lambda (number)
+ (setq entity (elmo-msgdb-message-entity
+ msgdb number))
+ (elmo-message-entity-set-number
+ entity
+ (* -1 (elmo-message-entity-number entity)))
+ entity)
+ (elmo-msgdb-list-messages msgdb)))
+ (elmo-msgdb-append-entity new-db
+ dop-entity
+ (elmo-msgdb-flags
+ msgdb
+ (abs (elmo-message-entity-number
+ dop-entity)))))
+ new-db))
+
+(require 'product)
+(product-provide (provide 'elmo-dop) (require 'elmo-version))