branch: externals/org
commit 38cd9b0a3a789ca7e49a1bb98d5b3c4b2257fe4a
Author: Ihor Radchenko <yanta...@posteo.net>
Commit: Ihor Radchenko <yanta...@posteo.net>

    org-persist: Avoid writing index frequently
    
    * lisp/org-persist.el (org-persist--write-elisp-file):
    Do not write index every time.  Remove optional argument.
    (org-persist-write:index): Update call.
    (org-persist--merge-index): When BASE is nil, just return OTHER.  This
    speeds things up when we have no index loaded.
    (org-persist-register):
    (org-persist-unregister):
    (org-persist-read):
    (org-persist-load-all):
    (org-persist-write-all):
    (org-persist-gc): Make sure that index is synchronized with disk and
    conflicting (non-equal) entries are dropped.  This is an alternative
    approach compared to 7999433067 that avoid frequent idnex
    writes (which are slow).  We instead _read_ index solving the problem
    of multiple Emacs instances writing to cache in different, faster,
    way.
    
    Link: https://orgmode.org/list/87h63cj1c5....@gmail.com
---
 lisp/org-persist.el | 104 +++++++++++++++++++++++++++-------------------------
 1 file changed, 54 insertions(+), 50 deletions(-)

diff --git a/lisp/org-persist.el b/lisp/org-persist.el
index d96a303820..ae75ab7afc 100644
--- a/lisp/org-persist.el
+++ b/lisp/org-persist.el
@@ -454,15 +454,12 @@ FORMAT and ARGS are passed to `message'."
 
 ;; FIXME: `pp' is very slow when writing even moderately large datasets
 ;; We should probably drop it or find some fast formatter.
-(defun org-persist--write-elisp-file
-    (file data &optional no-circular pp inhibit-writing-index)
+(defun org-persist--write-elisp-file (file data &optional no-circular pp)
   "Write to index and then write elisp DATA to FILE.
 When optional argument NO-CIRCULAR is non-nil, do not bind
 `print-circle' to t.
 When optional argument PP is non-nil, pretty-print the data (slow on
-moderately large data).
-INHIBIT-WRITING-INDEX will disable writing index file.
-"
+moderately large data)."
   ;; Fsync slightly reduces the chance of an incomplete filesystem
   ;; write, however on modern hardware its effectiveness is
   ;; questionable and it is insufficient to guarantee complete writes.
@@ -488,28 +485,23 @@ INHIBIT-WRITING-INDEX will disable writing index file.
         print-number-table
         (start-time (float-time))
         (tmp-file (make-temp-file "org-persist-")))
-    ;; Every time we write cache data, make sure that index is up to
-    ;; date. This prevents situation when two Emacs sessions are writing
-    ;; different data under the same cache key, but do not update the
-    ;; index metadata about the cache data written (e.g. hash).
-    (when (or inhibit-writing-index (org-persist--save-index))
-      (unless (file-exists-p (file-name-directory file))
-        (make-directory (file-name-directory file) t))
-      ;; Do not write to FILE directly.  Another Emacs instance may be
-      ;; doing the same at the same time.  Instead, write to new
-      ;; temporary file and then rename it (renaming is atomic
-      ;; operation that does not create data races).
-      ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75209#35
-      (with-temp-file tmp-file
-        (insert ";;   -*- mode: lisp-data; -*-\n")
-        (if pp
-            (let ((pp-use-max-width nil)) ; Emacs bug#58687
-              (pp data (current-buffer)))
-          (prin1 data (current-buffer))))
-      (rename-file tmp-file file 'overwrite)
-      (org-persist--display-time
-       (- (float-time) start-time)
-       "Writing to %S" file))))
+    (unless (file-exists-p (file-name-directory file))
+      (make-directory (file-name-directory file) t))
+    ;; Do not write to FILE directly.  Another Emacs instance may be
+    ;; doing the same at the same time.  Instead, write to new
+    ;; temporary file and then rename it (renaming is atomic
+    ;; operation that does not create data races).
+    ;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75209#35
+    (with-temp-file tmp-file
+      (insert ";;   -*- mode: lisp-data; -*-\n")
+      (if pp
+          (let ((pp-use-max-width nil)) ; Emacs bug#58687
+            (pp data (current-buffer)))
+        (prin1 data (current-buffer))))
+    (rename-file tmp-file file 'overwrite)
+    (org-persist--display-time
+     (- (float-time) start-time)
+     "Writing to %S" file)))
 
 (defmacro org-persist-gc:generic (container collection)
   "Garbage collect CONTAINER data from COLLECTION."
@@ -944,7 +936,7 @@ Otherwise, return t."
     (let ((index-file
            (org-file-name-concat org-persist-directory 
org-persist-index-file)))
       (org-persist--merge-index-with-disk)
-      (org-persist--write-elisp-file index-file org-persist--index t nil t)
+      (org-persist--write-elisp-file index-file org-persist--index t nil)
       (setq org-persist--index-age
             (file-attribute-modification-time (file-attributes index-file)))
       index-file)))
@@ -973,26 +965,28 @@ Otherwise, return t."
   "Attempt to merge new index items in OTHER into BASE.
 Items with different details are considered too difficult, and skipped."
   (if other
-      (let ((new (cl-set-difference other base :test #'equal))
-            (base-files (mapcar (lambda (s) (plist-get s :persist-file)) base))
-            (combined (reverse base)))
-        (dolist (item (nreverse new))
-          (unless (or (memq 'index (mapcar #'car (plist-get item :container)))
-                      (not (file-exists-p
+      (if (not base) other
+        (let ((new (cl-set-difference other base :test #'equal))
+              (base-files (mapcar (lambda (s) (plist-get s :persist-file)) 
base))
+              (combined (reverse base)))
+          (dolist (item (nreverse new))
+            (unless (or (memq 'index (mapcar #'car (plist-get item 
:container)))
+                        (not (file-exists-p
                             (org-file-name-concat org-persist-directory
                                                   (plist-get item 
:persist-file))))
-                      (member (plist-get item :persist-file) base-files))
-            (push item combined)))
-        (nreverse combined))
+                        (member (plist-get item :persist-file) base-files))
+              (push item combined)))
+          (nreverse combined)))
     base))
 
 ;;;; Public API
 
-(cl-defun org-persist-register (container &optional associated &rest misc
-                               &key inherit
-                               &key (expiry org-persist-default-expiry)
-                               &key (write-immediately nil)
-                               &allow-other-keys)
+(cl-defun org-persist-register
+    ( container &optional associated &rest misc
+      &key inherit
+      &key (expiry org-persist-default-expiry)
+      &key (write-immediately nil)
+      &allow-other-keys)
   "Register CONTAINER in ASSOCIATED to be persistent across Emacs sessions.
 Optional key INHERIT makes CONTAINER dependent on another container.
 Such dependency means that data shared between variables will be
@@ -1007,7 +1001,9 @@ MISC will be appended to the collection.  It must be 
alternating :KEY
 VALUE pairs.
 When WRITE-IMMEDIATELY is non-nil, the return value will be the same
 with `org-persist-write'."
-  (unless org-persist--index (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (setq container (org-persist--normalize-container container))
   (setq associated (org-persist--normalize-associated associated))
   (when inherit
@@ -1035,7 +1031,9 @@ with `org-persist-write'."
 When ASSOCIATED is `all', unregister CONTAINER everywhere.
 When REMOVE-RELATED is non-nil, remove all the containers stored with
 the CONTAINER as well."
-  (unless org-persist--index (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (setq container (org-persist--normalize-container container))
   (if (eq associated 'all)
       (mapc (lambda (collection)
@@ -1072,7 +1070,9 @@ CONTAINER as well.  For example:
     (org-persist-read \"My data\") ; => \"My data\"
     (org-persist-read \"My data\" nil nil nil
                       :read-related t) ; => (\"My data\" \"test\")"
-  (unless org-persist--index (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (setq associated (org-persist--normalize-associated associated))
   (setq container (org-persist--normalize-container container))
   (let* ((collection (org-persist--find-index `(:container ,container 
:associated ,associated)))
@@ -1120,7 +1120,9 @@ have the same meaning as in `org-persist-read'."
 
 (defun org-persist-load-all (&optional associated)
   "Restore all the persistent data associated with ASSOCIATED."
-  (unless org-persist--index (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (setq associated (org-persist--normalize-associated associated))
   (let (all-containers)
     (dolist (collection org-persist--index)
@@ -1175,7 +1177,9 @@ When IGNORE-RETURN is non-nil, just return t on success 
without calling
 (defun org-persist-write-all (&optional associated)
   "Save all the persistent data.
 When ASSOCIATED is non-nil, only save the matching data."
-  (unless org-persist--index (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (setq associated (org-persist--normalize-associated associated))
   (if
       (and (equal 1 (length org-persist--index))
@@ -1287,9 +1291,9 @@ Remove current sessions from `org-persist-gc-lock-file'."
 (defun org-persist-gc ()
   "Remove expired or unregistered containers and orphaned files.
 Also, remove containers associated with non-existing files."
-  (if org-persist--index
-      (org-persist--merge-index-with-disk)
-    (org-persist--load-index))
+  ;; Sync cache with disk, dropping conflicting items between multiple
+  ;; Emacsen.
+  (org-persist--merge-index-with-disk)
   (let (new-index
         (remote-files-num 0)
         (orphan-files

Reply via email to