diff --git a/doc/6_reference.md b/doc/6_reference.md index 79c1fd6..44a67ac 100644 --- a/doc/6_reference.md +++ b/doc/6_reference.md @@ -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 diff --git a/modules/jsonDB.sh b/modules/jsonDB.sh index 2648e80..d737147 100644 --- a/modules/jsonDB.sh +++ b/modules/jsonDB.sh @@ -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 +} +