aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatsumi Yamaoka2011-04-18 22:59:02 +0000
committerKatsumi Yamaoka2011-04-18 22:59:02 +0000
commit8d6d9c8f8de3841257c0b74448a824583bbf2c01 (patch)
tree5aca2c7b78420db293f088f28fc41af100bfb174
parent7eed1860d8ed2ac70a333e05c99a6207c2d6c675 (diff)
downloademacs-8d6d9c8f8de3841257c0b74448a824583bbf2c01.tar.gz
emacs-8d6d9c8f8de3841257c0b74448a824583bbf2c01.zip
gnus-registry.el, registry.el: Silence the byte compiler.
gnus-registry.el: Eliminate cl functions. (gnus-registry-sort-addresses): New function that replaces mapcan. (gnus-registry-action, gnus-registry-spool-action) (gnus-registry-split-fancy-with-parent) (gnus-registry-fetch-recipients-fast): Use it. (gnus-registry-import-eld): Replace delete* with dolist + delq. registry.el (initialize-instance, registry-lookup) (registry-lookup-breaks-before-lexbind, registry-lookup-secondary) (registry-lookup-secondary-value, registry-search, registry-delete) (registry-insert, registry-reindex, registry-size, registry-prune): Use eval-and-compile.
-rw-r--r--lisp/gnus/ChangeLog15
-rw-r--r--lisp/gnus/gnus-registry.el48
-rw-r--r--lisp/gnus/registry.el320
3 files changed, 197 insertions, 186 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index eac53d413cc..8417d37cadf 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,18 @@
12011-04-18 Katsumi Yamaoka <yamaoka@jpl.org>
2
3 * gnus-registry.el: Eliminate cl functions.
4 (gnus-registry-sort-addresses): New function that replaces mapcan.
5 (gnus-registry-action, gnus-registry-spool-action)
6 (gnus-registry-split-fancy-with-parent)
7 (gnus-registry-fetch-recipients-fast): Use it.
8 (gnus-registry-import-eld): Replace delete* with dolist + delq.
9
10 * registry.el (initialize-instance, registry-lookup)
11 (registry-lookup-breaks-before-lexbind, registry-lookup-secondary)
12 (registry-lookup-secondary-value, registry-search, registry-delete)
13 (registry-insert, registry-reindex, registry-size, registry-prune):
14 Use eval-and-compile.
15
12011-04-16 Teodor Zlatanov <tzz@lifelogs.com> 162011-04-16 Teodor Zlatanov <tzz@lifelogs.com>
2 17
3 * registry.el (registry-reindex): New method to recreate the secondary 18 * registry.el (registry-reindex): New method to recreate the secondary
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index eab4403c34b..697dc373b1f 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -303,15 +303,9 @@ This is not required after changing `gnus-registry-cache-file'."
303(defun gnus-registry-action (action data-header from &optional to method) 303(defun gnus-registry-action (action data-header from &optional to method)
304 (let* ((id (mail-header-id data-header)) 304 (let* ((id (mail-header-id data-header))
305 (subject (mail-header-subject data-header)) 305 (subject (mail-header-subject data-header))
306 (recipients (sort (mapcan 'gnus-registry-extract-addresses 306 (recipients (gnus-registry-sort-addresses
307 (list 307 (or (ignore-errors (mail-header "Cc" data-header)) "")
308 (or (ignore-errors 308 (or (ignore-errors (mail-header "To" data-header)) "")))
309 (mail-header "Cc" data-header))
310 "")
311 (or (ignore-errors
312 (mail-header "To" data-header))
313 "")))
314 'string-lessp))
315 (sender (nth 0 (gnus-registry-extract-addresses 309 (sender (nth 0 (gnus-registry-extract-addresses
316 (mail-header-from data-header)))) 310 (mail-header-from data-header))))
317 (from (gnus-group-guess-full-name-from-command-method from)) 311 (from (gnus-group-guess-full-name-from-command-method from))
@@ -329,11 +323,9 @@ This is not required after changing `gnus-registry-cache-file'."
329(defun gnus-registry-spool-action (id group &optional subject sender recipients) 323(defun gnus-registry-spool-action (id group &optional subject sender recipients)
330 (let ((to (gnus-group-guess-full-name-from-command-method group)) 324 (let ((to (gnus-group-guess-full-name-from-command-method group))
331 (recipients (or recipients 325 (recipients (or recipients
332 (sort (mapcan 'gnus-registry-extract-addresses 326 (gnus-registry-sort-addresses
333 (list 327 (or (message-fetch-field "cc") "")
334 (or (message-fetch-field "cc") "") 328 (or (message-fetch-field "to") ""))))
335 (or (message-fetch-field "to") "")))
336 'string-lessp)))
337 (subject (or subject (message-fetch-field "subject"))) 329 (subject (or subject (message-fetch-field "subject")))
338 (sender (or sender (message-fetch-field "from")))) 330 (sender (or sender (message-fetch-field "from"))))
339 (when (and (stringp id) (string-match "\r$" id)) 331 (when (and (stringp id) (string-match "\r$" id))
@@ -409,11 +401,9 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details."
409 ;; these may not be used, but the code is cleaner having them up here 401 ;; these may not be used, but the code is cleaner having them up here
410 (sender (gnus-string-remove-all-properties 402 (sender (gnus-string-remove-all-properties
411 (message-fetch-field "from"))) 403 (message-fetch-field "from")))
412 (recipients (sort (mapcan 'gnus-registry-extract-addresses 404 (recipients (gnus-registry-sort-addresses
413 (list 405 (or (message-fetch-field "cc") "")
414 (or (message-fetch-field "cc") "") 406 (or (message-fetch-field "to") "")))
415 (or (message-fetch-field "to") "")))
416 'string-lessp))
417 (subject (gnus-string-remove-all-properties 407 (subject (gnus-string-remove-all-properties
418 (gnus-registry-simplify-subject 408 (gnus-registry-simplify-subject
419 (message-fetch-field "subject")))) 409 (message-fetch-field "subject"))))
@@ -719,6 +709,11 @@ Addresses without a name will say \"noname\"."
719 (format "%s <%s>" name addr)))) 709 (format "%s <%s>" name addr))))
720 (mail-extract-address-components text t))) 710 (mail-extract-address-components text t)))
721 711
712(defun gnus-registry-sort-addresses (&rest addresses)
713 "Return a normalized and sorted list of ADDRESSES."
714 (sort (apply 'nconc (mapcar 'gnus-registry-extract-addresses addresses))
715 'string-lessp))
716
722(defun gnus-registry-simplify-subject (subject) 717(defun gnus-registry-simplify-subject (subject)
723 (if (stringp subject) 718 (if (stringp subject)
724 (gnus-simplify-subject subject) 719 (gnus-simplify-subject subject)
@@ -738,15 +733,9 @@ Addresses without a name will say \"noname\"."
738 (gnus-registry-fetch-header-fast "from" article)) 733 (gnus-registry-fetch-header-fast "from" article))
739 734
740(defun gnus-registry-fetch-recipients-fast (article) 735(defun gnus-registry-fetch-recipients-fast (article)
741 (sort (mapcan 'gnus-registry-extract-addresses 736 (gnus-registry-sort-addresses
742 (list 737 (or (ignore-errors (gnus-registry-fetch-header-fast "Cc" article)) "")
743 (or (ignore-errors 738 (or (ignore-errors (gnus-registry-fetch-header-fast "To" article)) "")))
744 (gnus-registry-fetch-header-fast "Cc" article))
745 "")
746 (or (ignore-errors
747 (gnus-registry-fetch-header-fast "To" article))
748 "")))
749 'string-lessp))
750 739
751(defun gnus-registry-fetch-header-fast (article header) 740(defun gnus-registry-fetch-header-fast (article header)
752 "Fetch the HEADER quickly, using the internal gnus-data-list function" 741 "Fetch the HEADER quickly, using the internal gnus-data-list function"
@@ -982,7 +971,8 @@ only the last one's marks are returned."
982 collect p)) 971 collect p))
983 extra-cell key val) 972 extra-cell key val)
984 ;; remove all the strings from the entry 973 ;; remove all the strings from the entry
985 (delete* nil rest :test (lambda (a b) (stringp b))) 974 (dolist (elem rest)
975 (if (stringp elem) (setq rest (delq elem rest))))
986 (gnus-registry-set-id-key id 'group groups) 976 (gnus-registry-set-id-key id 'group groups)
987 ;; just use the first extra element 977 ;; just use the first extra element
988 (setq rest (car-safe rest)) 978 (setq rest (car-safe rest))
diff --git a/lisp/gnus/registry.el b/lisp/gnus/registry.el
index 3e638427897..1a18dbd50d2 100644
--- a/lisp/gnus/registry.el
+++ b/lisp/gnus/registry.el
@@ -131,58 +131,60 @@
131 :type hash-table 131 :type hash-table
132 :documentation "The data hashtable."))) 132 :documentation "The data hashtable.")))
133 133
134(defmethod initialize-instance :AFTER ((this registry-db) slots) 134(eval-and-compile
135 "Set value of data slot of THIS after initialization." 135 (defmethod initialize-instance :AFTER ((this registry-db) slots)
136 (with-slots (data tracker) this 136 "Set value of data slot of THIS after initialization."
137 (unless (member :data slots) 137 (with-slots (data tracker) this
138 (setq data (make-hash-table :size 10000 :rehash-size 2.0 :test 'equal))) 138 (unless (member :data slots)
139 (unless (member :tracker slots) 139 (setq data
140 (setq tracker (make-hash-table :size 100 :rehash-size 2.0))))) 140 (make-hash-table :size 10000 :rehash-size 2.0 :test 'equal)))
141 141 (unless (member :tracker slots)
142(defmethod registry-lookup ((db registry-db) keys) 142 (setq tracker (make-hash-table :size 100 :rehash-size 2.0)))))
143 "Search for KEYS in the registry-db THIS. 143
144 (defmethod registry-lookup ((db registry-db) keys)
145 "Search for KEYS in the registry-db THIS.
144Returns a alist of the key followed by the entry in a list, not a cons cell." 146Returns a alist of the key followed by the entry in a list, not a cons cell."
145 (let ((data (oref db :data))) 147 (let ((data (oref db :data)))
146 (delq nil 148 (delq nil
147 (mapcar 149 (mapcar
148 (lambda (k) 150 (lambda (k)
149 (when (gethash k data) 151 (when (gethash k data)
150 (list k (gethash k data)))) 152 (list k (gethash k data))))
151 keys)))) 153 keys))))
152 154
153(defmethod registry-lookup-breaks-before-lexbind ((db registry-db) keys) 155 (defmethod registry-lookup-breaks-before-lexbind ((db registry-db) keys)
154 "Search for KEYS in the registry-db THIS. 156 "Search for KEYS in the registry-db THIS.
155Returns a alist of the key followed by the entry in a list, not a cons cell." 157Returns a alist of the key followed by the entry in a list, not a cons cell."
156 (let ((data (oref db :data))) 158 (let ((data (oref db :data)))
157 (delq nil 159 (delq nil
158 (loop for key in keys 160 (loop for key in keys
159 when (gethash key data) 161 when (gethash key data)
160 collect (list key (gethash key data)))))) 162 collect (list key (gethash key data))))))
161 163
162(defmethod registry-lookup-secondary ((db registry-db) tracksym 164 (defmethod registry-lookup-secondary ((db registry-db) tracksym
163 &optional create) 165 &optional create)
164 "Search for TRACKSYM in the registry-db THIS. 166 "Search for TRACKSYM in the registry-db THIS.
165When CREATE is not nil, create the secondary index hashtable if needed." 167When CREATE is not nil, create the secondary index hashtable if needed."
166 (let ((h (gethash tracksym (oref db :tracker)))) 168 (let ((h (gethash tracksym (oref db :tracker))))
167 (if h 169 (if h
168 h 170 h
169 (when create 171 (when create
170 (puthash tracksym 172 (puthash tracksym
171 (make-hash-table :size 800 :rehash-size 2.0 :test 'equal) 173 (make-hash-table :size 800 :rehash-size 2.0 :test 'equal)
172 (oref db :tracker)) 174 (oref db :tracker))
173 (gethash tracksym (oref db :tracker)))))) 175 (gethash tracksym (oref db :tracker))))))
174 176
175(defmethod registry-lookup-secondary-value ((db registry-db) tracksym val 177 (defmethod registry-lookup-secondary-value ((db registry-db) tracksym val
176 &optional set) 178 &optional set)
177 "Search for TRACKSYM with value VAL in the registry-db THIS. 179 "Search for TRACKSYM with value VAL in the registry-db THIS.
178When SET is not nil, set it for VAL (use t for an empty list)." 180When SET is not nil, set it for VAL (use t for an empty list)."
179 ;; either we're asked for creation or there should be an existing index 181 ;; either we're asked for creation or there should be an existing index
180 (when (or set (registry-lookup-secondary db tracksym)) 182 (when (or set (registry-lookup-secondary db tracksym))
181 ;; set the entry if requested, 183 ;; set the entry if requested,
182 (when set 184 (when set
183 (puthash val (if (eq t set) '() set) 185 (puthash val (if (eq t set) '() set)
184 (registry-lookup-secondary db tracksym t))) 186 (registry-lookup-secondary db tracksym t)))
185 (gethash val (registry-lookup-secondary db tracksym)))) 187 (gethash val (registry-lookup-secondary db tracksym)))))
186 188
187(defun registry--match (mode entry check-list) 189(defun registry--match (mode entry check-list)
188 ;; for all members 190 ;; for all members
@@ -204,129 +206,133 @@ When SET is not nil, set it for VAL (use t for an empty list)."
204 (or found 206 (or found
205 (registry--match mode entry (cdr-safe check-list)))))) 207 (registry--match mode entry (cdr-safe check-list))))))
206 208
207(defmethod registry-search ((db registry-db) &rest spec) 209(eval-and-compile
208 "Search for SPEC across the registry-db THIS. 210 (defmethod registry-search ((db registry-db) &rest spec)
211 "Search for SPEC across the registry-db THIS.
209For example calling with :member '(a 1 2) will match entry '((a 3 1)). 212For example calling with :member '(a 1 2) will match entry '((a 3 1)).
210Calling with :all t (any non-nil value) will match all. 213Calling with :all t (any non-nil value) will match all.
211Calling with :regex '\(a \"h.llo\") will match entry '((a \"hullo\" \"bye\"). 214Calling with :regex '\(a \"h.llo\") will match entry '((a \"hullo\" \"bye\").
212The test order is to check :all first, then :member, then :regex." 215The test order is to check :all first, then :member, then :regex."
213 (when db 216 (when db
214 (let ((all (plist-get spec :all)) 217 (let ((all (plist-get spec :all))
215 (member (plist-get spec :member)) 218 (member (plist-get spec :member))
216 (regex (plist-get spec :regex))) 219 (regex (plist-get spec :regex)))
217 (loop for k being the hash-keys of (oref db :data) using (hash-values v) 220 (loop for k being the hash-keys of (oref db :data)
218 when (or 221 using (hash-values v)
219 ;; :all non-nil returns all 222 when (or
220 all 223 ;; :all non-nil returns all
221 ;; member matching 224 all
222 (and member (registry--match :member v member)) 225 ;; member matching
223 ;; regex matching 226 (and member (registry--match :member v member))
224 (and regex (registry--match :regex v regex))) 227 ;; regex matching
225 collect k)))) 228 (and regex (registry--match :regex v regex)))
226 229 collect k))))
227(defmethod registry-delete ((db registry-db) keys assert &rest spec) 230
228 "Delete KEYS from the registry-db THIS. 231 (defmethod registry-delete ((db registry-db) keys assert &rest spec)
232 "Delete KEYS from the registry-db THIS.
229If KEYS is nil, use SPEC to do a search. 233If KEYS is nil, use SPEC to do a search.
230Updates the secondary ('tracked') indices as well. 234Updates the secondary ('tracked') indices as well.
231With assert non-nil, errors out if the key does not exist already." 235With assert non-nil, errors out if the key does not exist already."
232 (let* ((data (oref db :data)) 236 (let* ((data (oref db :data))
233 (keys (or keys 237 (keys (or keys
234 (apply 'registry-search db spec))) 238 (apply 'registry-search db spec)))
235 (tracked (oref db :tracked))) 239 (tracked (oref db :tracked)))
236 240
237 (dolist (key keys) 241 (dolist (key keys)
238 (let ((entry (gethash key data))) 242 (let ((entry (gethash key data)))
239 (when assert 243 (when assert
240 (assert entry nil 244 (assert entry nil
241 "Key %s does not exists in database" key)) 245 "Key %s does not exists in database" key))
242 ;; clean entry from the secondary indices 246 ;; clean entry from the secondary indices
243 (dolist (tr tracked) 247 (dolist (tr tracked)
244 ;; is this tracked symbol indexed? 248 ;; is this tracked symbol indexed?
245 (when (registry-lookup-secondary db tr) 249 (when (registry-lookup-secondary db tr)
246 ;; for every value in the entry under that key... 250 ;; for every value in the entry under that key...
247 (dolist (val (cdr-safe (assq tr entry))) 251 (dolist (val (cdr-safe (assq tr entry)))
248 (let* ((value-keys (registry-lookup-secondary-value db tr val))) 252 (let* ((value-keys (registry-lookup-secondary-value
249 (when (member key value-keys) 253 db tr val)))
250 ;; override the previous value 254 (when (member key value-keys)
251 (registry-lookup-secondary-value 255 ;; override the previous value
252 db tr val 256 (registry-lookup-secondary-value
253 ;; with the indexed keys MINUS the current key 257 db tr val
254 ;; (we pass t when the list is empty) 258 ;; with the indexed keys MINUS the current key
255 (or (delete key value-keys) t))))))) 259 ;; (we pass t when the list is empty)
256 (remhash key data))) 260 (or (delete key value-keys) t)))))))
257 keys)) 261 (remhash key data)))
258 262 keys))
259(defmethod registry-insert ((db registry-db) key entry) 263
260 "Insert ENTRY under KEY into the registry-db THIS. 264 (defmethod registry-insert ((db registry-db) key entry)
265 "Insert ENTRY under KEY into the registry-db THIS.
261Updates the secondary ('tracked') indices as well. 266Updates the secondary ('tracked') indices as well.
262Errors out if the key exists already." 267Errors out if the key exists already."
263 268
264 (assert (not (gethash key (oref db :data))) nil 269 (assert (not (gethash key (oref db :data))) nil
265 "Key already exists in database") 270 "Key already exists in database")
266 271
267 (assert (< (registry-size db) 272 (assert (< (registry-size db)
268 (oref db :max-hard)) 273 (oref db :max-hard))
269 nil 274 nil
270 "max-hard size limit reached") 275 "max-hard size limit reached")
271 276
272 ;; store the entry 277 ;; store the entry
273 (puthash key entry (oref db :data)) 278 (puthash key entry (oref db :data))
274 279
275 ;; store the secondary indices 280 ;; store the secondary indices
276 (dolist (tr (oref db :tracked))
277 ;; for every value in the entry under that key...
278 (dolist (val (cdr-safe (assq tr entry)))
279 (let* ((value-keys (registry-lookup-secondary-value db tr val)))
280 (pushnew key value-keys :test 'equal)
281 (registry-lookup-secondary-value db tr val value-keys))))
282 entry)
283
284(defmethod registry-reindex ((db registry-db))
285 "Rebuild the secondary indices of registry-db THIS."
286 (let ((count 0)
287 (expected (* (length (oref db :tracked)) (registry-size db))))
288 (dolist (tr (oref db :tracked)) 281 (dolist (tr (oref db :tracked))
289 (let (values) 282 ;; for every value in the entry under that key...
290 (maphash 283 (dolist (val (cdr-safe (assq tr entry)))
291 (lambda (key v) 284 (let* ((value-keys (registry-lookup-secondary-value db tr val)))
292 (incf count) 285 (pushnew key value-keys :test 'equal)
293 (when (and (< 0 expected) 286 (registry-lookup-secondary-value db tr val value-keys))))
294 (= 0 (mod count 1000))) 287 entry)
295 (message "reindexing: %d of %d (%.2f%%)" 288
296 count expected (/ (* 1000 count) expected))) 289 (defmethod registry-reindex ((db registry-db))
297 (dolist (val (cdr-safe (assq tr v))) 290 "Rebuild the secondary indices of registry-db THIS."
298 (let* ((value-keys (registry-lookup-secondary-value db tr val))) 291 (let ((count 0)
299 (push key value-keys) 292 (expected (* (length (oref db :tracked)) (registry-size db))))
300 (registry-lookup-secondary-value db tr val value-keys)))) 293 (dolist (tr (oref db :tracked))
301 (oref db :data)))))) 294 (let (values)
302 295 (maphash
303(defmethod registry-size ((db registry-db)) 296 (lambda (key v)
304 "Returns the size of the registry-db object THIS. 297 (incf count)
298 (when (and (< 0 expected)
299 (= 0 (mod count 1000)))
300 (message "reindexing: %d of %d (%.2f%%)"
301 count expected (/ (* 1000 count) expected)))
302 (dolist (val (cdr-safe (assq tr v)))
303 (let* ((value-keys (registry-lookup-secondary-value db tr val)))
304 (push key value-keys)
305 (registry-lookup-secondary-value db tr val value-keys))))
306 (oref db :data))))))
307
308 (defmethod registry-size ((db registry-db))
309 "Returns the size of the registry-db object THIS.
305This is the key count of the :data slot." 310This is the key count of the :data slot."
306 (hash-table-count (oref db :data))) 311 (hash-table-count (oref db :data)))
307 312
308(defmethod registry-prune ((db registry-db)) 313 (defmethod registry-prune ((db registry-db))
309 "Prunes the registry-db object THIS. 314 "Prunes the registry-db object THIS.
310Removes only entries without the :precious keys." 315Removes only entries without the :precious keys."
311 (let* ((precious (oref db :precious)) 316 (let* ((precious (oref db :precious))
312 (precious-p (lambda (entry-key) (cdr (memq (car entry-key) precious)))) 317 (precious-p (lambda (entry-key)
313 (data (oref db :data)) 318 (cdr (memq (car entry-key) precious))))
314 (limit (oref db :max-soft)) 319 (data (oref db :data))
315 (size (registry-size db)) 320 (limit (oref db :max-soft))
316 (candidates (loop for k being the hash-keys of data 321 (size (registry-size db))
317 using (hash-values v) 322 (candidates (loop for k being the hash-keys of data
318 when (notany precious-p v) 323 using (hash-values v)
319 collect k)) 324 when (notany precious-p v)
320 (candidates-count (length candidates)) 325 collect k))
321 ;; are we over max-soft? 326 (candidates-count (length candidates))
322 (prune-needed (> size limit))) 327 ;; are we over max-soft?
323 328 (prune-needed (> size limit)))
324 ;; while we have more candidates than we need to remove... 329
325 (while (and (> candidates-count (- size limit)) candidates) 330 ;; while we have more candidates than we need to remove...
326 (decf candidates-count) 331 (while (and (> candidates-count (- size limit)) candidates)
327 (setq candidates (cdr candidates))) 332 (decf candidates-count)
328 333 (setq candidates (cdr candidates)))
329 (registry-delete db candidates nil))) 334
335 (registry-delete db candidates nil))))
330 336
331(ert-deftest registry-instantiation-test () 337(ert-deftest registry-instantiation-test ()
332 (should (registry-db "Testing"))) 338 (should (registry-db "Testing")))