Browse Source

new: database library provided to charm.

raw-remaining-args
Valentin Lab 9 years ago
parent
commit
d5f6a747d2
  1. 225
      bin/compose

225
bin/compose

@ -49,6 +49,18 @@ quick_cat_file() { quick_cat_stdin < "$1"; }
quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; } quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; }
export -f quick_cat_file quick_cat_stdin md5_compat export -f quick_cat_file quick_cat_stdin md5_compat
clean_cache() {
local i=0
for f in $(ls -t "$CACHEDIR/"*.cache.* 2>/dev/null | tail -n +500); do
((i++))
rm -f "$f"
done
if (( i > 0 )); then
debug "${WHITE}Cleaned cache:${NORMAL} Removed $((i)) elements (current cache size is $(du -sh "$CACHEDIR" | cut -f 1))"
fi
}
trap_add "EXIT" clean_cache trap_add "EXIT" clean_cache
usage="$exname CHARM"' usage="$exname CHARM"'
@ -330,6 +342,219 @@ get_file() {
export -f get_file export -f get_file
##
## Common database lib
##
_clean_docker() {
local _DB_NAME="$1" container_id="$2"
(
set +e
debug "Removing container $_DB_NAME"
docker stop "$container_id"
docker rm "$_DB_NAME"
rm -vf "/tmp/${_DB_NAME}.state"
)
}
export -f _clean_docker
are_files_locked_in_dir() {
local dir="$1" device hdev ldev
device=$(stat -c %d "$dir") || {
err "Can't stat %d."
return 1
}
device=$(printf "%04x" $device)
hdev=${device:0:2}
ldev=${device:2:2}
inodes=$(find "$dir" -printf ':%i:\n')
found=
while read -r inode; do
debug "try inode:$inode"
if [[ "$inodes" == *":$inode:"* ]]; then
found=1
break
fi
done < <(cat /proc/locks | grep " $hdev:$ldev:" | sed -r "s/^.*$hdev:$ldev:([0-9]+).*$/\1/g")
[ "$found" ]
}
export -f are_files_locked_in_dir
export _PID="$$"
ensure_db_docker_running () {
_DB_NAME="db_${DB_NAME}_${_PID}"
if [ -e "/tmp/${_DB_NAME}.state" ]; then
export DOCKER_IP="$(cat "/tmp/${_DB_NAME}.state")"
debug "Re-using previous docker/connection '$DOCKER_IP'."
_set_db_params "$DOCKER_IP"
return 0
fi
if [ -e "/tmp/${_DB_NAME}.working" ]; then
## avoid recursive calls.
if [ -z "$DOCKER_IP" ]; then
err "Currently figuring up DOCKER_IP, please set it yourself before this call if needed."
return 1
else
debug "Ignoring recursive call."
fi
return 0
fi
touch "/tmp/${_DB_NAME}.working"
docker rm "$_DB_NAME" 2>/dev/null || true
host_db_working_dir="$DATASTORE/${SERVICE_NAME}$DB_DATADIR"
if is_db_locked; then
info "Some process is using '$host_db_working_dir'. Trying to find a docker that would do this..."
found=
for docker_id in $(docker ps -q); do
has_volume_mounted=$(
docker inspect \
--format "{{range .Mounts}}{{if eq .Destination \"$DB_DATADIR\"}}{{.Source}}{{end}}{{end}}" \
"$docker_id")
if [ "$has_volume_mounted" == "$host_db_working_dir" ]; then
found="$docker_id"
break
fi
done
if [ -z "$found" ]; then
err "Please shutdown any other docker using this directory."
return 1
fi
export container_id="$found"
info "Found docker $docker_id is already running."
else
verb "Database is not locked."
if ! docker_has_image "$DOCKER_BASE_IMAGE"; then
docker pull "$DOCKER_BASE_IMAGE"
fi
docker_opts=
if [ -f "$DB_PASSFILE" ]; then
verb "Found and using '$DB_PASSFILE'."
docker_opts="$db_docker_opts -v $SERVER_ROOT_PREFIX$DB_PASSFILE:$DB_PASSFILE"
fi
debug docker run -d \
--name "$_DB_NAME" \
$docker_opts \
-v "$host_db_working_dir:$DB_DATADIR" \
"$DOCKER_BASE_IMAGE"
if ! container_id=$(
docker run -d \
--name "$_DB_NAME" \
$docker_opts \
-v "$host_db_working_dir:$DB_DATADIR" \
"$DOCKER_BASE_IMAGE"
); then
err "'docker run' failed !"
_clean_docker "$_DB_NAME" "$container_id"
rm "/tmp/${_DB_NAME}.working"
return 1
fi
trap_add EXIT,ERR "_clean_docker '$_DB_NAME' '$container_id'"
fi
if DOCKER_IP=$(wait_for_docker_ip "$container_id"); then
echo "$DOCKER_IP" > "/tmp/${_DB_NAME}.state"
debug "written /tmp/${_DB_NAME}.state"
rm "/tmp/${_DB_NAME}.working"
_set_db_params "$DOCKER_IP"
return 0
else
err "Db not found. Docker logs follows:"
docker logs --tail=5 "$container_id" 2>&1 | prefix " | " >&2
rm "/tmp/${_DB_NAME}.working"
return 1
fi
}
export -f ensure_db_docker_running
## Require to set $db_docker_opts if needed, and $DB_PASSFILE
##
_dcmd() {
local docker_opts command="$1"
shift
debug "Db> $command $@"
if [ -f "$DB_PASSFILE" ]; then
verb "Found and using '$DB_PASSFILE'."
db_docker_opts="$db_docker_opts -v $SERVER_ROOT_PREFIX$DB_PASSFILE:$DB_PASSFILE"
fi
debug docker run -i --rm \
$db_docker_opts \
--entrypoint "$command" "$DOCKER_BASE_IMAGE" $db_cmd_opts "$@"
docker run -i --rm \
$db_docker_opts \
--entrypoint "$command" "$DOCKER_BASE_IMAGE" $db_cmd_opts "$@"
}
export -f _dcmd
## Executes code through db
dcmd () {
[ "$DB_NAME" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_NAME."
[ "$DB_DATADIR" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_DATADIR."
[ "$DB_PASSFILE" ] || print_syntax_error "$FUNCNAME: You must provide \$DB_PASSFILE."
[ "$_PID" ] || print_syntax_error "$FUNCNAME: You must provide \$_PID."
[ "$(type -t is_db_locked)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function 'is_db_locked'."
[ "$(type -t _set_db_params)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function '_set_db_params'."
[ "$(type -t ddb)" == "function" ] || print_syntax_error "$FUNCNAME: You must provide function 'ddb'."
ensure_db_docker_running </dev/null || return 1
_dcmd "$@"
}
export -f dcmd
## Warning: requires a ``ddb`` matching current database to be checked
wait_for_docker_ip() {
local name=$1 timeout=5 timeout_count=0 DOCKER_IP= DB_OK=
while [ -z "$DOCKER_IP" ]; do
sleep 1
DOCKER_IP=$(docker inspect --format='{{.NetworkSettings.IPAddress}}' "$name" 2>/dev/null)
verb "[1/2] Waiting for docker $name... ($[timeout_count + 1]/$timeout)"
((timeout_count++)) || true
if [ "$timeout_count" == "$timeout" ]; then
err "${RED}timeout error${NORMAL}(${timeout}s):"\
"Could not find '$name' docker" \
"container's IP."
return 1
fi
done
verb "[1/2] Found docker $name IP: $DOCKER_IP"
timeout_count=0
DB_OK=
_set_db_params "$DOCKER_IP"
while [ -z "$DB_OK" ]; do
sleep 1
echo "SELECT 1;" | ddb >/dev/null && DB_OK=1
verb "[2/2] Waiting for db service from docker $name... ($[timeout_count + 1]/$timeout)"
((timeout_count++)) || true
if [ "$timeout_count" == "$timeout" ]; then
err "${RED}timeout error${NORMAL}(${timeout}s):"\
"Could not connect to db on $DOCKER_IP." \
"container's IP."
return 1
fi
done
verb "[2/2] Db is ready !"
echo "$DOCKER_IP"
return 0
}
export -f wait_for_docker_ip
## ##
## Arrays ## Arrays
## ##

Loading…
Cancel
Save