Changeset - 58349059257f
[Not reviewed]
0 1 0
Branko Majic (branko) - 4 years ago 2020-07-06 14:44:41
branko@majic.rs
Noticket: Deduplicate locking code in Factorio Manager:

- Introduce helper function for cleaning-up any registered locks.
- Introduce helper function for calling flock that exits in case of an
error as well.
- Make existing code use the new locking function.
1 file changed with 62 insertions and 65 deletions:
0 comments (0 inline, 0 general)
games/factorio_manager.sh
Show inline comments
 
@@ -1077,6 +1077,63 @@ function select_factorio_version() {
 
    return 0
 
}
 

	
 
#
 
# Removes all registered lock files. Lock files are registered via the
 
# global array variable "lock_files". This function is meant to be
 
# used in conjunction with trap built-in to clean-up the files on exit.
 
#
 
# Arguments (globals):
 
#
 
#   lock_files
 
#     Array listing all the lock files that should be removed.
 
#
 
function remove_lock_files() {
 
    local lock
 

	
 
    for lock in "${lock_files[@]}"; do
 
        rm -f "$lock"
 
    done
 
}
 
declare -a lock_files=()
 
trap remove_lock_files EXIT
 

	
 
#
 
# Acquires an exclusive lock via flock call using the specified file
 
# and file descriptor. If it is not possible to acquire a lock,
 
# terminates the script, and registers the lock file for removal.
 
#
 
# The function should be used in conjunction with subshell as follows:
 
#
 
# (
 
#     lock "$HOME/.mylock" 200
 
#
 
#     do_my_stuff_here
 
#
 
# ) 200>"$HOME/.mylock"
 
#
 
#
 
# Arguments:
 
#
 
# $1 (lock_file)
 
#   Path to lock file.
 
#
 
# $2 (fd)
 
#   File descriptor number to use for the lock.
 
#
 
function lock() {
 
    local lock_file="$1"
 
    local fd="$2"
 

	
 
    lock_files+=("$lock_file")
 

	
 
    # Obtain lock - Factorio uses the same mechanism, so we should
 
    # be able to detect the game is running in this way.
 
    flock --exclusive --nonblock "$fd"
 
    if [[ $? != 0 ]]; then
 
        error "Could not acquire lock via lock file '$lock_file'. Is Factorio still running?"
 
        exit "$ERROR_GENERAL"
 
    fi
 
}
 

	
 
# Define error codes.
 
SUCCESS=0
 
@@ -1392,19 +1449,7 @@ elif [[ $command == backup ]]; then
 

	
 
    (
 

	
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        function remove_lock() {
 
            rm "$lock_file"
 
        }
 

	
 
        trap remove_lock EXIT
 
        lock "$lock_file" 200
 

	
 
        # Backup the instance. Clean-up the backup destination in case of failure.
 
        mkdir -p "$backup_destination"
 
@@ -1525,18 +1570,7 @@ elif [[ $command == restore ]]; then
 
    validate_path_or_terminate "backup_directory" "$restore_source" "$ERROR_ARGUMENTS"
 

	
 
    (
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        function remove_lock() {
 
            rm "$lock_file"
 
        }
 
        trap remove_lock EXIT
 
        lock "$lock_file" 200
 

	
 
        # Set-up a list of files and directories that will get removed.
 
        shopt -s nullglob
 
@@ -1883,20 +1917,7 @@ elif [[ $command == remove ]]; then
 
    validate_path_or_terminate "instance_directory" "$instance_directory" "$ERROR_ARGUMENTS"
 

	
 
    (
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        # Removing lock file will most likely fail if we manage to
 
        # remove the instance.
 
        function remove_lock() {
 
            rm -f "$lock_file"
 
        }
 
        trap remove_lock EXIT
 
        lock "$lock_file" 200
 

	
 
        # Set-up a list of files and directories that will get removed.
 
        shopt -s nullglob dotglob
 
@@ -1999,19 +2020,7 @@ elif [[ $command == copy ]]; then
 
    validate_path_or_terminate "instance_directory_new" "$destination_instance_directory" "$ERROR_ARGUMENTS"
 

	
 
    (
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $source_lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        function remove_lock() {
 
            rm "$source_lock_file"
 
        }
 

	
 
        trap remove_lock EXIT
 
        lock "$source_lock_file" 200
 

	
 
        # Load source instance configuration.
 
        source "$source_instance_config"
 
@@ -2123,19 +2132,7 @@ elif [[ $command == import ]]; then
 

	
 
    (
 

	
 
        # Obtain lock - Factorio uses the same mechanism, so we should
 
        # be able to detect the game is running in this way.
 
        flock --exclusive --nonblock 200
 
        if [[ $? != 0 ]]; then
 
            error "Could not lock instance directory via lock file $source_lock_file. Is Factorio instance still running?"
 
            exit "$ERROR_GENERAL"
 
        fi
 

	
 
        function remove_lock() {
 
            rm "$source_lock_file"
 
        }
 

	
 
        trap remove_lock EXIT
 
        lock "$source_lock_file" 200
 

	
 
        # Create instance directory.
 
        mkdir "$instance_directory"
0 comments (0 inline, 0 general)