Revert "hold my beer, let's remove *DB-LOCK*"

This reverts commit f6561a64a3.
This commit is contained in:
eta 2020-04-06 21:23:52 +01:00
parent 2a1e7303d0
commit 2f4e78bc8c

View file

@ -2,6 +2,8 @@
(defvar *db* nil (defvar *db* nil
"Connection to the database.") "Connection to the database.")
(defvar *db-lock* (bt:make-recursive-lock "sqlite3 lock")
"Lock for *DB*.")
(defparameter *default-database-path* "data.sqlite3" (defparameter *default-database-path* "data.sqlite3"
"Default path to the SQLite database file.") "Default path to the SQLite database file.")
(defvar *prepared-statements* nil (defvar *prepared-statements* nil
@ -18,11 +20,12 @@
(defun connect-database (&optional (path *default-database-path*)) (defun connect-database (&optional (path *default-database-path*))
"Establish a connection to the database." "Establish a connection to the database."
(bt:with-recursive-lock-held (*db-lock*)
(setf *db* (sqlite:connect path)) (setf *db* (sqlite:connect path))
(run-pragmas) (run-pragmas)
(loop for sym in *prepared-statements* (loop for sym in *prepared-statements*
do (eval `(setf ,sym nil))) do (eval `(setf ,sym nil)))
(setf *prepared-statements* nil)) (setf *prepared-statements* nil)))
(defmacro prepared-statement (statement) (defmacro prepared-statement (statement)
"Caches the creation of a prepared statement with SQL text STATEMENT. "Caches the creation of a prepared statement with SQL text STATEMENT.
@ -38,11 +41,12 @@ In other words, prepares STATEMENT once, then returns the prepared statement aft
(defmacro with-prepared-statement ((name statement) &body forms) (defmacro with-prepared-statement ((name statement) &body forms)
"Evaluates FORMS, binding a prepared statement with SQL text STATEMENT to NAME, and ensuring it is reset when control is transferred." "Evaluates FORMS, binding a prepared statement with SQL text STATEMENT to NAME, and ensuring it is reset when control is transferred."
`(let ((,name (prepared-statement ,statement))) `(bt:with-recursive-lock-held (*db-lock*)
(let ((,name (prepared-statement ,statement)))
(multiple-value-prog1 (multiple-value-prog1
(unwind-protect (unwind-protect
(progn ,@forms) (progn ,@forms)
(ignore-errors (sqlite:reset-statement ,name)))))) (ignore-errors (sqlite:reset-statement ,name)))))))
(defmacro with-prepared-statements (statements &body forms) (defmacro with-prepared-statements (statements &body forms)
"Like WITH-PREPARED-STATEMENT, but takes multiple statements." "Like WITH-PREPARED-STATEMENT, but takes multiple statements."
@ -50,11 +54,12 @@ In other words, prepares STATEMENT once, then returns the prepared statement aft
collect `(,name (prepared-statement ,statement)))) collect `(,name (prepared-statement ,statement))))
(reset-forms (loop for (name statement) in statements (reset-forms (loop for (name statement) in statements
collect `(ignore-errors (sqlite:reset-statement ,name))))) collect `(ignore-errors (sqlite:reset-statement ,name)))))
`(let (,@let-forms) `(bt:with-recursive-lock-held (*db-lock*)
(let (,@let-forms)
(multiple-value-prog1 (multiple-value-prog1
(unwind-protect (unwind-protect
(progn ,@forms)) (progn ,@forms))
(ignore-errors (progn ,@reset-forms)))))) (ignore-errors (progn ,@reset-forms)))))))
(defmacro column-values (statement) (defmacro column-values (statement)
"Returns the values in the current row of the STATEMENT." "Returns the values in the current row of the STATEMENT."