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) First comment
games/factorio_manager.sh
Show inline comments
 
@@ -1074,12 +1074,69 @@ function select_factorio_version() {
 
        fi
 
    done
 

	
 
    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
 
ERROR_ARGUMENTS=1
 
ERROR_CONFIGURATION=2
 
ERROR_GENERAL=3
 
@@ -1389,25 +1446,13 @@ elif [[ $command == backup ]]; then
 

	
 
    # Validate destination path for backup directory can be used.
 
    validate_path_or_terminate "backup_directory_new" "$backup_destination" "$ERROR_GENERAL"
 

	
 
    (
 

	
 
        # 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"
 
        if ! cp -a "$instance_directory"/* "$backup_destination"; then
 
            error "Could not create backup under: $backup_destination"
 
            rm -rf "$backup_destination"
 
@@ -1522,24 +1567,13 @@ elif [[ $command == restore ]]; then
 
    validate_path_or_terminate "instance_directory" "$instance_directory" "$ERROR_ARGUMENTS"
 

	
 
    # Validate that backup directory contains valid backup.
 
    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
 
        entries_to_remove=($instance_directory/*)
 
        shopt -u nullglob
 

	
 
@@ -1880,26 +1914,13 @@ elif [[ $command == remove ]]; then
 
    lock_file="$instance_directory/.lock"
 

	
 
    # Validate that instance directory contains valid instance.
 
    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
 
        entries_to_remove=($instance_directory/*)
 
        shopt -u nullglob dotglob
 

	
 
@@ -1996,25 +2017,13 @@ elif [[ $command == copy ]]; then
 
    validate_path_or_terminate "instance_directory" "$source_instance_directory" "$ERROR_ARGUMENTS"
 

	
 
    # Make sure destination instance directory can be used.
 
    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"
 

	
 
        # Display list of available Factorio versions.
 
        echo
 
@@ -2120,25 +2129,13 @@ elif [[ $command == import ]]; then
 
    echo "Factorio version must  be selected manually for imported instances."
 
    echo
 
    select_factorio_version "$game_installations_directory" || exit "$ERROR_GENERAL"
 

	
 
    (
 

	
 
        # 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"
 

	
 
        # Sort the associative array keys.
 
        IFS=$'\n' import_entries_keys=($(sort <<<"${!import_entries[*]}"))
0 comments (0 inline, 0 general) First comment
You need to be logged in to comment. Login now