From 209576016144d331e4329c772989ef19d2e5c961 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Mon, 24 Feb 2020 02:40:28 +0100 Subject: [PATCH] Import a new helper for job management This currently depends on DeforaOS libDatabase. --- src/deforaos-jobs.sh | 197 +++++++++++++++++++++++++++++++++++++++++++ src/project.conf | 6 +- 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100755 src/deforaos-jobs.sh diff --git a/src/deforaos-jobs.sh b/src/deforaos-jobs.sh new file mode 100755 index 0000000..53185ae --- /dev/null +++ b/src/deforaos-jobs.sh @@ -0,0 +1,197 @@ +#!/bin/sh +#Copyright (c) 2020 Pierre Pronchery +#Error codes: +# 1 Usage error +# 2 Generic error +# 3 Could not lock the database +# 4 Could not unlock the database + + + +#variables +DATABASE_CONFFILE="deforaos-jobs.conf" +DATABASE_ENGINE="sqlite3" +DATABASE_FILE="deforaos-jobs.db" +DATABASE_INITFILE="deforaos-jobs.sql" +DEVNULL="/dev/null" +PROGNAME_JOBS="defora-jobs" +QUERY_ADD_BEGIN="INSERT INTO jobs (command) VALUES ('" +QUERY_ADD_END="')" +QUERY_EXEC_SELECT="SELECT jobs_id, command FROM jobs WHERE started IS NULL ORDER BY jobs_id ASC LIMIT 1" +QUERY_INIT="CREATE TABLE jobs (jobs_id INTEGER PRIMARY KEY, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, command VARCHAR(255), started TIMESTAMP DEFAULT NULL, pid INTEGER DEFAULT NULL, code INTEGER DEFAULT NULL, completed TIMESTAMP DEFAULT NULL)" +QUERY_LIST="SELECT * FROM jobs" +#executables +DATABASE="database" +DEBUG= +LOCK="mkdir" +UNLOCK="rmdir" +SED="sed" + + +#functions +#database_add +_database_add() +{ + if [ $# -ne 1 ]; then + _usage + return $? + fi + command="$1" + query="$QUERY_ADD_BEGIN$(echo "$command" | _database_escape)$QUERY_ADD_END" + + _database_init || return 2 + _database_query "$query" > "$DEVNULL" || return 2 +} + + +#database_escape +_database_escape() +{ + $SED -e "s,',''," +} + + +#database_exec +_database_exec() +{ + if [ $# -ne 0 ]; then + _usage + return $? + fi + + _database_init || return 2 + _database_lock || return 3 + _database_query "$QUERY_EXEC_SELECT" | (IFS="|" + read header + read empty jobs_id command empty + if [ -z "$jobs_id" ]; then + _database_unlock || return 4 + return 0 + fi + #XXX TOCTOU + QUERY="UPDATE jobs SET started=datetime() WHERE jobs_id='$jobs_id'" + _database_query "$QUERY" > "$DEVNULL" + _database_unlock + code=-1 + if [ -n "$command" ]; then + $DEBUG sh -c "$command" & + pid=$! + QUERY="UPDATE jobs SET pid='$pid' WHERE jobs_id='$jobs_id'" + _database_query "$QUERY" > "$DEVNULL" + wait $pid + code=$? + fi + QUERY="UPDATE jobs SET completed=datetime(), code='$code' WHERE jobs_id='$jobs_id'" + _database_query "$QUERY" > "$DEVNULL") +} + + +#database_init +_database_init() +{ + if [ ! -f "$DATABASE_CONFFILE" ]; then + echo "filename=$DATABASE_FILE" > "$DATABASE_CONFFILE" + fi + if [ ! -f "$DATABASE_FILE" ]; then + _database_lock || return 3 + _database_query "$QUERY_INIT" > "$DEVNULL" || return 2 + _database_unlock || return 4 + fi + return 0 +} + + +#database_list +_database_list() +{ + if [ $# -ne 0 ]; then + _usage + return $? + fi + _database_init || return 2 + _database_query "$QUERY_LIST" || return 2 +} + + +#database_lock +_database_lock() +{ + $DEBUG $LOCK "${DATABASE_FILE%.db}" +} + + +#database_query +_database_query() +{ + $DEBUG $DATABASE -d "$DATABASE_ENGINE" -C "$DATABASE_CONFFILE" "$@" +} + + +#database_unlock +_database_unlock() +{ + $DEBUG $UNLOCK "${DATABASE_FILE%.db}" +} + + +#debug +_debug() +{ + echo "$@" 1>&3 + "$@" +} + + +#error +_error() +{ + echo "$PROGNAME_JOBS: $@" 1>&2 + return 2 +} + + +#usage +_usage() +{ + echo "Usage: $PROGNAME_JOBS add command" 1>&2 + echo " $PROGNAME_JOBS list" 1>&2 + echo " $PROGNAME_JOBS exec" 1>&2 + return 1 +} + + +#main +while getopts "DO:" name; do + case "$name" in + D) + DEBUG="_debug" + ;; + O) + export "${OPTARG%%=*}"="${OPTARG#*=}" + ;; + ?) + _usage + exit $? + ;; + esac +done +shift $((OPTIND - 1)) +if [ $# -lt 1 ]; then + _usage + exit $? +fi + +exec 3>&1 + +method="_usage" +case "$1" in + add|list|exec) + method="_database_$1" + ;; + *) + _error "$1: Operation not supported" + ;; +esac +shift + +"$method" "$@" diff --git a/src/project.conf b/src/project.conf index 16cd355..f8eaab9 100644 --- a/src/project.conf +++ b/src/project.conf @@ -1,4 +1,4 @@ -dist=Makefile,deforaos-build.sh,deforaos-document.sh,deforaos-git-hook.sh,deforaos-git-message.sh,deforaos-irc.sh,deforaos-lock.sh,deforaos-package.sh,deforaos-release.sh,deforaos-update.sh +dist=Makefile,deforaos-build.sh,deforaos-document.sh,deforaos-git-hook.sh,deforaos-git-message.sh,deforaos-irc.sh,deforaos-jobs.sh,deforaos-lock.sh,deforaos-package.sh,deforaos-release.sh,deforaos-update.sh [deforaos-build.sh] install=$(PREFIX)/bin @@ -20,6 +20,10 @@ mode=0755 install=$(PREFIX)/libexec mode=0755 +[deforaos-jobs.sh] +install=$(PREFIX)/bin +mode=0755 + [deforaos-lock.sh] install=$(PREFIX)/bin mode=0755