use flock for atomic, update doc

This commit is contained in:
Kay Marquardt (Gnadelwartz) 2020-05-15 17:45:23 +02:00
parent 52bde30271
commit c02327f7a1
2 changed files with 76 additions and 29 deletions

View File

@ -468,6 +468,11 @@ The file extions is '.jssh' and for security reasons location of jssh files is r
Note: File names containg '..' and absolute file names pointing outside BASHBOT_ETC or BASHBOT_DATA are refused by jsshDB functions.
Note2: Since version 0.94 jsshDB functions support file locking with flock. Write / Update operations use flock to wait until
previous operations are finished. see "man flock" for more information. Bashbot uses a maximum timeout of 10 seconds for flock.
If you don't want atomic write / update operations use the *_async variant of jsshDB functions. If flock is not availible
the *_async variant is automatically used.
*Example:* for file name:
```bash
@ -514,6 +519,8 @@ Note: Existing content is overwritten.
*usage:* jssh_writeDB "ARRAY" "filename"
*usage:* jssh_writeDB_async "ARRAY" "filename"
*example:*
```bash
# Prepare array to store vaules
@ -570,6 +577,8 @@ Note: Existing content not in ARRAY is kept in file.
*usage:* jssh_updateDB "ARRAY" "filename"
*usage:* jssh_updateDB_async "ARRAY" "filename"
*example:*
```bash
# continued example from writeDB
@ -595,35 +604,16 @@ cat "$DBfile"
```
##### jssh_insertDB
Insert, update, append a key=value pair to a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_insertDB "key" "value" "filename"
*example:*
```bash
jssh_insertDB "newkey" "an other value" "${DATADIR:-.}/myvalues"
```
##### jssh_getDB
Read a key=value pair from a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_getDB "key" "filename"
*example:*
```bash
result="$(jssh_getDB "newvalue" "${DATADIR:-.}/myvalues")"
# lets see whats the value of key newvalue
echo "$result"
this is new
```
##### jssh_readDB
Read content of a file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" upfront,
*usage:* jssh_readDB "ARRAY" "filename"
*usage:* jssh_readDB_async "ARRAY" "filename"
Note: readDB uses concurrent / shared locking from flock so multiple proceses can read from file, as long no process is writing.
Maximum timeour for reading is 1s to not block readers.
*example:*
```bash
# Prepare array to read vaules
@ -669,7 +659,34 @@ jssh_printDB READVALUES
["whynot","subindex1"] "whynot A"
```
##### jssh_insertDB
Insert, update, append a key=value pair to a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_insertDB "key" "value" "filename"
*usage:* jssh_insertDB_asnyc "key" "value" "filename"
Note: insertDB uses also excusiv write locking, but with a maximum timeout of 2s. insertDB is a "fast" operation, simply adding the value to the end of the file.
*example:*
```bash
jssh_insertDB "newkey" "an other value" "${DATADIR:-.}/myvalues"
```
##### jssh_deleteKeyDB
Deleted a key=value pair froma jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_deleteKeyDB "key" "filename"
*usage:* jssh_deleteKeyDB_async "key" "filename"
*example:*
```bash
jssh_deleteKeyDB "delkey"" "${DATADIR:-.}/myvalues"
```
https://linuxhint.com/associative_array_bash/
https://linuxconfig.org/how-to-use-arrays-in-bash-script
@ -956,5 +973,5 @@ The name of your bot is availible as bash variable "$ME", there is no need to ca
#### [Prev Best Practice](5_practice.md)
#### [Next Notes for Developers](7_develop.md)
#### $$VERSION$$ v0.94-pre-9-gd1f509a
#### $$VERSION$$ v0.94-pre-13-g52bde30

View File

@ -5,7 +5,7 @@
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#
#### $$VERSION$$ v0.94-pre-10-g23a3d4b
#### $$VERSION$$ v0.94-pre-13-g52bde30
#
# source from commands.sh to use jsonDB functions
#
@ -103,6 +103,23 @@ if _exists flock; then
}
# delete key/value from jsshDB
# $1 key name, can onyl contain -a-zA-Z0-9,._
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_deleteKeyDB() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
declare -A oldARR
# start atomic delete here, exclusive max wait 10s
{ flock -e -w 10 200
Json2Array "oldARR" <"${DB}"
if [[ -v "oldAR[$1]" ]] ; then
unset oldARR["$1"]
Array2Json "oldARR" >"${DB}"
fi
} 200>"${DB}${BASHBOT_LOCKNAME}"
}
else
#########
# we have no flock, use "old" not atomic functions
@ -123,6 +140,9 @@ else
}
jssh_deleteKeyDB() {
jssh_deleteKeyDB_async "$@"
}
fi
##############
@ -188,10 +208,10 @@ jssh_updateDB_async() {
declare -n ARRAY="$1"
[ -z "${ARRAY[*]}" ] && return 1
declare -A oldARR newARR
jssh_readDB "oldARR" "$2" || return "$?"
jssh_readDB_async "oldARR" "$2" || return "$?"
if [ -z "${oldARR[*]}" ]; then
# no old content
jssh_writeDB "$1" "$2"
jssh_writeDB_async "$1" "$2"
else
# merge arrays
local o1 o2 n1 n2
@ -201,7 +221,7 @@ jssh_updateDB_async() {
#shellcheck disable=SC2034,SC2190,SC2206
newARR=( ${o2:0:${#o2}-1} ${n2:0:${#n2}-1} )
set +f
jssh_writeDB "newARR" "$2"
jssh_writeDB_async "newARR" "$2"
fi
}
@ -216,3 +236,13 @@ jssh_insertDB_async() {
}
jssh_deleteKeyDB_async() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
declare -A oldARR
jssh_readDB_async "oldARR" "$2" || return "$?"
if [[ -v "oldAR[$1]" ]] ; then
unset oldARR["$1"]
jssh_writeDB_async "oldARR" "$2"
fi
}