Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/asynchronous-operations.lisp

KindCoveredAll%
expression538 13.2
branch02 0.0
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
2
 
3
 (in-package :org.datagraph.spocq.implementation)
4
 
5
 #|
6
 generate asynchronous notifications
7
 
8
 use file-system notifications to track changes to the repository lmdb file.
9
 permit repeated invocation of an operator with successive repository revision instances.
10
 
11
 with-repository-commit-notifications
12
 call-with-repository-commit-notifications
13
 -> make-inotify
14
 -> watch
15
 -> compute-repository-revision
16
 -> close-inotify
17
 
18
 |#
19
 
20
 (defvar *notification-monitor* nil)
21
 (defvar *notification-event*  nil)
22
 
23
 (defmacro with-repository-commit-notifications ((notification-revision initial-revision &rest args &key interval limit)
24
                                                 &body body)
25
   (declare (ignore interval limit))
26
   (let ((operator (gensym "notify")))
27
   `(flet ((,operator (,notification-revision)
28
             (declare (ignorable ,notification-revision))
29
             ,@body))
30
      (declare (dynamic-extent #',operator))
31
      (call-with-repository-commit-notifications #',operator ,initial-revision ,@args))))
32
 
33
 (defgeneric call-with-repository-commit-notifications (operator initial-revision &key interval limit)
34
   (:method (operator (initial-revision repository-revision) &key interval limit)
35
     (unless interval (setf interval 1))
36
     (let ((*notification-monitor* nil)
37
           (notify-pathname (merge-pathnames *lmdb-filename* (repository-pathname initial-revision))))
38
       (unwind-protect
39
           (progn
40
             (setf *notification-monitor* (cl-inotify:make-inotify))
41
             (cl-inotify:watch *notification-monitor* notify-pathname :modify)
42
             (loop while (or (null limit) (>= (decf limit) 0))
43
               do (loop for interval-index from 0 below interval
44
                    for *notification-event* =  (cl-inotify:read-event *notification-monitor*)
45
                    finally (funcall operator
46
                                     (compute-repository-revision (repository-revision-reference initial-revision)
47
                                                                  "HEAD")))))
48
         (when *notification-monitor*
49
           (cl-inotify:close-inotify *notification-monitor*))))))