Skip to content

Instantly share code, notes, and snippets.

@pydevops
Last active September 8, 2018 17:18
Show Gist options
  • Save pydevops/da4558bda308d274c4c3e5371f98f460 to your computer and use it in GitHub Desktop.
Save pydevops/da4558bda308d274c4c3e5371f98f460 to your computer and use it in GitHub Desktop.
GCS based locking function
#! /usr/bin/env bash
set -u
# constants
PROJECT=$(gcloud info --format='value(config.project)')
LOCKS_BUCKET=$PROJECT-db2-locks
# how long do we wait for lock or condition
SLEEP=5
# Check if a lock file exists
# Globals:
# None
# Arguments:
# LOCK_FILE_URL
# Returns:
# 0
function no_lock_yet() {
local LOCK_FILE_URL="$1"
# blocking till the lock is released by some other process
until ! gsutil ls $LOCK_FILE_URL >/dev/null 2>&1; do
sleep "${SLEEP}"
done
# no lock any more
echo 0
}
function lock() {
local LOCK_FILE_PREFIX="$1"
local LOCK_FILE="$2"
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE
# ONLY lock if there is no lock file exists
# mkdir -p the prefix and geneate the lock file, then rsync over to GCS
if ! gsutil ls "$LOCK_FILE_URL" >/dev/null 2>&1;then
local TEMP_DIR=$(mktemp -d)
local LOCK_DIR=${TEMP_DIR}/${LOCK_FILE_PREFIX}
mkdir -p $LOCK_DIR && touch $LOCK_DIR/$LOCK_FILE
(cd $TEMP_DIR && gsutil rsync -r . gs://$LOCKS_BUCKET)
else
echo "lock $LOCK_FILE_PREFIX/$LOCK_FILE exists already"
fi
}
# Acquire a lock
# Globals:
# LOCKS_BUCKET
# Arguments:
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE)
# Returns:
# 0
# blocking till we can lock
function db2_acquire_lock() {
local ENV=$1
local DB_INSTANCE_NAME=$2
local DB_NAME=$3
local LOCK_FILE=$4
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME}
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE
free_to_lock=$(no_lock_yet $LOCK_FILE_URL)
# echo "free_to_lock is $free_to_lock"
if [[ $free_to_lock -eq 0 ]];then
echo "$LOCK_FILE_URL is free to lock"
lock $LOCK_FILE_PREFIX $LOCK_FILE
fi
}
# Release a lock
# Globals:
# LOCKS_BUCKET
# Arguments:
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE)
# Returns:
# 0
function db2_release_lock() {
local ENV=$1
local DB_INSTANCE_NAME=$2
local DB_NAME=$3
local LOCK_FILE=$4
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME}
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE
# release the lock if there is a one
if gsutil ls "$LOCK_FILE_URL" >/dev/null 2>&1;then
echo "unlock $LOCK_FILE_URL"
gsutil rm "$LOCK_FILE_URL"
# error check here
fi
}
# wait for a lock to be acquired
# Globals:
# LOCKS_BUCKET
# Arguments:
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE)
# Returns:
# 0
function wait_for() {
local ENV=$1
local DB_INSTANCE_NAME=$2
local DB_NAME=$3
local LOCK_FILE=$4
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME}
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE
# blocking till the lock is acquired by some other process
until gsutil ls $LOCK_FILE_URL >/dev/null 2>&1; do
echo "wait_for $LOCK_FILE_URL"
sleep "${SLEEP}"
done
}
# notify that a lock is acquired
# Globals:
# LOCKS_BUCKET
# Arguments:
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE)
# Returns:
# 0
function notify() {
local ENV=$1
local DB_INSTANCE_NAME=$2
local DB_NAME=$3
local LOCK_FILE=$4
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME}
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE
lock $LOCK_FILE_PREFIX $LOCK_FILE
}
# test functions below
# function test_lock() {
# local LOCK_FILE_PREFIX=dev/primary-dbi-1/db-1
# lock $LOCK_FILE_PREFIX lock-1
# lock $LOCK_FILE_PREFIX lock-2
# }
# create the bucket for testing
if ! gsutil ls "gs://${LOCKS_BUCKET}";then
gsutil mb -c regional -l us-central1 gs://${LOCKS_BUCKET}
fi
# test the func used by the main backup script
#db2_acquire_lock dev primary-dbi-1 db-1 lock-backup
# gsutil ls -r gs://${LOCKS_BUCKET}
# test_release_lock
#db2_release_lock dev primary-dbi-1 db-1 lock-backup
# gsutil ls -r gs://${LOCKS_BUCKET}
# test_wait_for
#wait_for dev primary-dbi-1 db-1 lock-primary-ready
# gsutil ls -r gs://${LOCKS_BUCKET}
# test_notify
#notify dev primary-dbi-1 db-1 lock-primary-ready
# gsutil ls -r gs://${LOCKS_BUCKET}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment