diff options
| author | 2025-10-19 07:49:30 +0300 | |
|---|---|---|
| committer | 2025-10-19 07:49:30 +0300 | |
| commit | a84cce2850dfce357ed5e37a3fb5ebba6ccad5bc (patch) | |
| tree | 4f9becf9746a7d3b7a7de75475370af1f1ecb541 | |
| parent | Added checks against releasing an untaken lock (diff) | |
| download | ukkoclot-a84cce2850dfce357ed5e37a3fb5ebba6ccad5bc.tar.gz ukkoclot-a84cce2850dfce357ed5e37a3fb5ebba6ccad5bc.tar.xz ukkoclot-a84cce2850dfce357ed5e37a3fb5ebba6ccad5bc.zip | |
Introduce locking in config
| -rw-r--r-- | .ocicl-lint.conf | 2 | ||||
| -rw-r--r-- | src/config.lisp | 45 |
2 files changed, 30 insertions, 17 deletions
diff --git a/.ocicl-lint.conf b/.ocicl-lint.conf index a24c746..3ad0e65 100644 --- a/.ocicl-lint.conf +++ b/.ocicl-lint.conf | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | # minus-one: I don't like 1- | 1 | # minus-one: I don't like 1- |
| 2 | suppress-rules = minus-one, missing-docstring | 2 | suppress-rules = minus-one |
| 3 | suggest-libraries = alexandria, uiop, serapeum | 3 | suggest-libraries = alexandria, uiop, serapeum |
diff --git a/src/config.lisp b/src/config.lisp index cf04c1c..7d841a2 100644 --- a/src/config.lisp +++ b/src/config.lisp | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | (defpackage :ukkoclot/src/config | 3 | (defpackage :ukkoclot/src/config |
| 4 | (:documentation "Stuff for loading the configuration of the bot") | 4 | (:documentation "Stuff for loading the configuration of the bot") |
| 5 | (:nicknames :conf) | 5 | (:nicknames :conf) |
| 6 | (:use :c2cl :iterate) | 6 | (:use :c2cl :iterate :ukkoclot/src/rw-lock) |
| 7 | (:export | 7 | (:export |
| 8 | #:*config* | 8 | #:*config* |
| 9 | #:config | 9 | #:config |
| @@ -20,6 +20,7 @@ | |||
| 20 | (in-package :ukkoclot/src/config) | 20 | (in-package :ukkoclot/src/config) |
| 21 | 21 | ||
| 22 | (defstruct config | 22 | (defstruct config |
| 23 | (lock (make-rw-lock :name "config's lock") :type rw-lock) | ||
| 23 | (bot-name "Ukko's Clot" :type string) | 24 | (bot-name "Ukko's Clot" :type string) |
| 24 | (bot-token "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi" :type string) | 25 | (bot-token "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi" :type string) |
| 25 | (db-path #P"./data.db" :type (or pathname string)) | 26 | (db-path #P"./data.db" :type (or pathname string)) |
| @@ -31,41 +32,53 @@ | |||
| 31 | 32 | ||
| 32 | (defun bot-name (&optional (config *config*)) | 33 | (defun bot-name (&optional (config *config*)) |
| 33 | "Get the desired name for the bot" | 34 | "Get the desired name for the bot" |
| 34 | (config-bot-name config)) | 35 | (with-slots (lock bot-name) config |
| 36 | (with-read-lock (lock) | ||
| 37 | bot-name))) | ||
| 35 | 38 | ||
| 36 | (defun bot-token (&optional (config *config*)) | 39 | (defun bot-token (&optional (config *config*)) |
| 37 | "Get the API token for the bot" | 40 | "Get the API token for the bot" |
| 38 | (config-bot-token config)) | 41 | (with-slots (lock bot-token) config |
| 42 | (with-read-lock (lock) | ||
| 43 | bot-token))) | ||
| 39 | 44 | ||
| 40 | (defun db-path (&optional (config *config*)) | 45 | (defun db-path (&optional (config *config*)) |
| 41 | "Get the path to the bot's database" | 46 | "Get the path to the bot's database" |
| 42 | (config-db-path config)) | 47 | (with-slots (lock db-path) config |
| 48 | (with-read-lock (lock) | ||
| 49 | db-path))) | ||
| 43 | 50 | ||
| 44 | (defun dev-group (&optional (config *config*)) | 51 | (defun dev-group (&optional (config *config*)) |
| 45 | "Get the ID of the dev/testing group" | 52 | "Get the ID of the dev/testing group" |
| 46 | (config-dev-group config)) | 53 | (with-slots (lock dev-group) config |
| 54 | (with-read-lock (lock) | ||
| 55 | dev-group))) | ||
| 47 | 56 | ||
| 48 | (defun owner (&optional (config *config*)) | 57 | (defun owner (&optional (config *config*)) |
| 49 | "Get the ID of the bot's owner" | 58 | "Get the ID of the bot's owner" |
| 50 | (config-owner config)) | 59 | (with-slots (lock owner) config |
| 60 | (with-read-lock (lock) | ||
| 61 | owner))) | ||
| 51 | 62 | ||
| 52 | (defun load-config (filename &optional (config *config*)) | 63 | (defun load-config (filename &optional (config *config*)) |
| 53 | "Load config from the given `filename'." | 64 | "Load config from the given `filename'." |
| 54 | (prog1 config | 65 | (prog1 config |
| 55 | (let ((data (with-open-file (f filename) (read f)))) | 66 | (let ((data (with-open-file (f filename) (read f)))) |
| 56 | (iter | 67 | (with-write-lock ((config-lock config)) |
| 57 | (for (kw-name value) on data by #'cddr) | 68 | (iter |
| 58 | (let ((name (intern (symbol-name kw-name) :ukkoclot/src/config))) | 69 | (for (kw-name value) on data by #'cddr) |
| 59 | (setf (slot-value config name) value)))))) | 70 | (let ((name (intern (symbol-name kw-name) :ukkoclot/src/config))) |
| 71 | (setf (slot-value config name) value))))))) | ||
| 60 | 72 | ||
| 61 | (defun serialize (config) | 73 | (defun serialize (config) |
| 62 | "Serializes the config to a plist." | 74 | "Serializes the config to a plist." |
| 63 | (iter | 75 | (with-read-lock ((config-lock config)) |
| 64 | (for slot in (class-direct-slots (class-of config))) | 76 | (iter |
| 65 | (appending | 77 | (for slot in (class-direct-slots (class-of config))) |
| 66 | (let* ((name (slot-definition-name slot)) | 78 | (let ((name (slot-definition-name slot))) |
| 67 | (kw-name (intern (symbol-name name) :keyword))) | 79 | (unless (eql name 'lock) |
| 68 | (list kw-name (slot-value config name)))))) | 80 | (let ((kw-name (intern (symbol-name name) :keyword))) |
| 81 | (appending (list kw-name (slot-value config name))))))))) | ||
| 69 | 82 | ||
| 70 | (defun print-default (filename) | 83 | (defun print-default (filename) |
| 71 | "Prints the default config to the given `filename'." | 84 | "Prints the default config to the given `filename'." |