Start locking
This commit is contained in:
parent
65af602dd4
commit
e5e2d2e780
91
src/g.bash
91
src/g.bash
@ -12,7 +12,7 @@ export PS4='+(${BASH_SOURCE##*/}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
|
||||
export g__EXISTS=true
|
||||
|
||||
g__PATH="${BASH_SOURCE[0]}"
|
||||
g__CALLER_PATH="${BASH_SOURCE[1]}"
|
||||
g__CALLER_PATH="${BASH_SOURCE[1]:-shell}"
|
||||
|
||||
# The global logging level. Lower the number, higher the priority.
|
||||
g__LOGGING_LEVEL=2
|
||||
@ -64,6 +64,12 @@ g__APP_LAST_ARGPARSE=''
|
||||
|
||||
g__APP_LAST_ALIAS=''
|
||||
|
||||
g__LOCKING_FILE_DIR="/tmp"
|
||||
|
||||
g__LOCKING_NAME_X_DESCRIPTOR=()
|
||||
|
||||
g__LOCKING_NEXT_DESCRIPTOR=100
|
||||
|
||||
|
||||
##
|
||||
# Initialize the framework
|
||||
@ -92,6 +98,8 @@ function g::internals::cleanup() {
|
||||
for file in "${g__FILES_TO_CLEANUP[@]}"; do
|
||||
rm -rf "$file"
|
||||
done
|
||||
|
||||
g::lock::cleanupForExit
|
||||
}
|
||||
|
||||
|
||||
@ -1982,14 +1990,89 @@ function g::flag::has() {
|
||||
return $(g::app::command::parse::has::flag "$nameOrPosition" "$uuid")
|
||||
}
|
||||
|
||||
# logging/debug flags
|
||||
|
||||
g::log::all # TODO remove
|
||||
|
||||
function g::lock::file() {
|
||||
local callerName="$(basename "$g__CALLER_PATH")"
|
||||
local name="${1:-$callerName}"
|
||||
|
||||
g::internal "Resolving lock file path for name: $name" g::lock
|
||||
g::path::resolve "$g__LOCKING_FILE_DIR" "${name}.lock"
|
||||
}
|
||||
|
||||
function g::arr::assoc::hasKey() {
|
||||
local key="$1"
|
||||
shift
|
||||
local array="$@"
|
||||
|
||||
for possibleKey in "${!array[@]}"; do
|
||||
if [[ "$key" == "$possibleKey" ]]; then
|
||||
return $(g::util::true)
|
||||
fi
|
||||
done
|
||||
|
||||
return $(g::util::false)
|
||||
}
|
||||
|
||||
function g::lock::descriptor() {
|
||||
local callerName="$(basename "$g__CALLER_PATH")"
|
||||
local name="${1:-$callerName}"
|
||||
local file="$(g::lock::file "$name")"
|
||||
|
||||
g::internal "Resolving lock file descriptor for file: $file" g::lock
|
||||
if g::arr::assoc::hasKey "$name" "${g__LOCKING_NAME_X_DESCRIPTOR[@]}"; then
|
||||
printf $fd
|
||||
return $(g::util::true)
|
||||
fi
|
||||
|
||||
local fd=$g__LOCKING_NEXT_DESCRIPTOR
|
||||
g__LOCKING_NEXT_DESCRIPTOR=$(($g__LOCKING_NEXT_DESCRIPTOR + 1))
|
||||
g__LOCKING_NAME_X_DESCRIPTOR+=( ["$name"]=$fd )
|
||||
|
||||
g::internal "Mapped FD $fd to lock file: $file" g::lock
|
||||
|
||||
exec $fd>"$file" || return $(g::util::false)
|
||||
printf $fd
|
||||
}
|
||||
|
||||
function g::lock::acquire() {
|
||||
local callerName="$(basename "$g__CALLER_PATH")"
|
||||
local name="${1:-$callerName}"
|
||||
local descriptor=$(g::lock::descriptor "$name")
|
||||
|
||||
flock $descriptor || g::error::throw "Unable to acquire lock: ${name} (${descriptor})"
|
||||
}
|
||||
|
||||
function g::lock::try() {
|
||||
local callerName="$(basename "$g__CALLER_PATH")"
|
||||
local name="${1:-$callerName}"
|
||||
local descriptor=$(g::lock::descriptor "$name")
|
||||
|
||||
g::internal "Got descriptor for lock: ${descriptor}"
|
||||
|
||||
flock -n $descriptor || return $(g::util::false)
|
||||
return $(g::util::true)
|
||||
}
|
||||
|
||||
function g::lock::release() {
|
||||
local callerName="$(basename "$g__CALLER_PATH")"
|
||||
local name="${1:-$callerName}"
|
||||
local file=$(g::lock::file "$name")
|
||||
|
||||
rm -rf "$file"
|
||||
}
|
||||
|
||||
function g::lock::cleanupForExit() {
|
||||
for file in "${!g__LOCKING_NAME_X_DESCRIPTOR[@]}"; do
|
||||
rm -rf "$file"
|
||||
done
|
||||
}
|
||||
|
||||
# dependency declarations
|
||||
|
||||
# output helpers
|
||||
|
||||
# argument parsing
|
||||
|
||||
# exception handling
|
||||
|
||||
# JSON parsing, INI parsing, rich data types (named parameters & arrays/maps)
|
||||
|
Loading…
Reference in New Issue
Block a user