2018-01-30 21:54:47 +00:00
#!/bin/bash
# (1) Init.
#--------------------------------------------------------#
# (1) Get current absolute dir
ROOT=$(dirname `realpath $0`);
# (2) Check argc
test $# -lt 2 && echo -e "error: too few arguments\n\n\e[1mUSAGE\e[0m\n\tmaster <key> <host> <port> <dir>\n\n\e[1mARGUMENTS\e[0m\n\t<key>\tThe key of the pool\n\t<host>\tThe host where the pool is hosted\n\t<port>\tTo port where the pool is bound\n\t<dir>\tThe folder containing ONLY the logger daemons\n" && exit 1;
# (3) Check @PORT range #
MIN_PORT=1024;
MAX_PORT=49151;
test "$3" -gt "$MAX_PORT" -o "$3" -lt "$MIN_PORT" && echo "error: <port> must be between $MIN_PORT and $MAX_PORT" && exit 1;
# (4) Set argument explicit names #
POOL_KEY="$1";
POOL_HOST="$2";
POOL_PORT="$3";
LOGGER_DIR="`realpath $4`";
# (5) Check @LOGGER_DIR #
test ! -d "$LOGGER_DIR" && echo "error: <dir> is not a valid folder." && exit 1;
# (6) init logger variables #
declare -A OUTPUT_PID; # will contain each bind-output PIDs
declare -A LOGGER_PID; # will contain each logger PIDs
# (7) get logger list #
LOGGERS=(`ls $LOGGER_DIR`);
# (8) If no logger -> exit #
test "${#LOGGERS[@]}" -eq 0 && echo "error: no logger found in <dir>." && exit 1;
# (9) Get local IP address #
LOCAL_IP="`ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'`";
test -z "$LOCAL_IP" && echo "error: cannot get local IP address." && exit 1;
2018-02-01 12:35:19 +00:00
# (10) Create a temporary file #
TMPFILE="/dev/shm/master_pid";
2018-01-30 21:54:47 +00:00
# (2) Set exit management
#--------------------------------------------------------#
# (1) On-Exit routine #
on_exit(){
2018-02-01 12:35:19 +00:00
echo "- killing ${#OUTPUT_PID[@]} output";
2018-01-30 21:54:47 +00:00
for logger_name in "${!OUTPUT_PID[@]}"; do
# kill each logger OUTPUT
2018-02-01 12:35:19 +00:00
echo " - killing $logger_name (${OUTPUT_PID[$logger_name]})";
2018-01-31 19:55:11 +00:00
kill -INT ${OUTPUT_PID[$logger_name]} 2>/dev/null;
2018-01-30 21:54:47 +00:00
done;
2018-02-01 12:35:19 +00:00
echo "- killing ${#LOGGER_PID[@]} loggers";
2018-01-30 21:54:47 +00:00
for logger_name in "${!LOGGER_PID[@]}"; do
# kill each logger OUTPUT
2018-02-01 12:35:19 +00:00
echo " - killing $logger_name (${LOGGER_PID[$logger_name]})";
2018-01-31 19:55:11 +00:00
kill -INT ${LOGGER_PID[$logger_name]} 2>/dev/null;
2018-01-30 21:54:47 +00:00
done;
2018-02-01 12:35:19 +00:00
echo "- killing main output";
2018-01-31 19:55:11 +00:00
kill -INT $MASTER_PID 2>/dev/null;
2018-01-30 21:54:47 +00:00
2018-02-01 12:35:19 +00:00
echo "- killing loop";
2018-01-31 19:55:11 +00:00
# kill -INT $LOOP_PID 2>/dev/null;
2018-01-30 21:54:47 +00:00
2018-02-01 12:35:19 +00:00
# delete tmp file
echo "- deleting tmp file";
rm $TMPFILE 2>/dev/null;
2018-01-30 21:54:47 +00:00
}
2018-01-31 19:55:11 +00:00
trap "on_exit;" HUP INT KILL TERM;
2018-01-30 21:54:47 +00:00
# (3) Connect to pool
#--------------------------------------------------------#
# (1) Bind-output #
2018-02-01 12:35:19 +00:00
echo -e "\e[32m+\e[0m connect to $POOL_HOST:$POOL_PORT";
$ROOT/bind-output master $POOL_HOST $POOL_PORT > $TMPFILE;
MASTER_PID="`cat $TMPFILE`";
2018-01-30 21:54:47 +00:00
2018-01-31 23:31:21 +00:00
echo " + flush connection before using it";
# $ROOT/write master "";
2018-01-30 21:54:47 +00:00
# (4) Launch master manager
#--------------------------------------------------------#
# (1) For each logger
for logger_name in "${LOGGERS[@]}"; do
2018-01-31 23:31:21 +00:00
echo " + logger '$logger_name'";
2018-01-30 21:54:47 +00:00
# Find an available port
2018-02-01 12:35:19 +00:00
PORT="$MIN_PORT";
2018-01-30 21:54:47 +00:00
while true; do
# if port not in use -> use it
ss -tl4 "( sport = :$PORT )" | grep "$PORT" >/dev/null 2>&1 || break;
# else try next port (+1)
PORT="`expr $PORT + 1`";
done;
2018-01-31 23:31:21 +00:00
# listen for pool response (port number)
2018-02-01 12:35:19 +00:00
echo -e " \e[32m+\e[0m listen $PORT";
$ROOT/bind-input freeport $PORT > $TMPFILE;
FREEPORT_PID="`cat $TMPFILE`";
sleep 1;
2018-01-31 23:31:21 +00:00
# send port request
echo " + sending port request";
2018-01-30 21:54:47 +00:00
$ROOT/write master "$POOL_KEY:$logger_name:$LOCAL_IP:$PORT";
2018-01-31 23:31:21 +00:00
echo " + waiting for response";
RESP="";
timeout=8; # 4sec = 8 x .5sec
while [ "$timeout" -gt "0" ]; do
RESP="`$ROOT/read freeport`";
# if empty answer, try again in .5 sec
if [ -z "$RESP" ]; then
# echo " + empty response (remaining $timeout)";
timeout="`expr $timeout - 1`";
sleep .5;
continue;
# else -> stop reading
else
# echo " + got response '$RESP'";
break;
fi
done;
# closing listen socket
2018-02-01 12:35:19 +00:00
echo -e " + received '\e[33m$RESP\e[0m'";
echo -e " \e[31m+\e[0m stop listening on $PORT";
2018-01-31 23:31:21 +00:00
kill -INT $FREEPORT_PID 2>/dev/null;
2018-01-30 21:54:47 +00:00
# empty response -> ignore
2018-02-01 12:35:19 +00:00
test -z "$RESP" && echo " + no answer" && continue;
2018-01-30 21:54:47 +00:00
# not a number -> ignore
2018-02-01 12:35:19 +00:00
echo -n "$RESP" | grep -P '^\d+$' >/dev/null || ( echo " + invalid format"; exit 1 ) || continue;
2018-01-30 21:54:47 +00:00
# Create output bound
2018-01-31 23:31:21 +00:00
echo " + connecting to $POOL_HOST:$RESP";
2018-02-01 12:35:19 +00:00
$ROOT/bind-output $logger_name $POOL_HOST $RESP > $TMPFILE;
OUTPUT_PID[$logger_name]="`cat $TMPFILE`";
2018-01-30 21:54:47 +00:00
2018-02-01 12:35:19 +00:00
echo " + logger launched in background";
2018-01-30 21:54:47 +00:00
# launch logger bound to output
2018-02-01 12:35:19 +00:00
( $LOGGER_DIR/$logger_name | cat > /tmp/outbuf_$logger_name )&
2018-01-30 21:54:47 +00:00
LOGGER_PID[$logger_name]=$!;
done;
2018-01-31 06:31:08 +00:00
# When all loggers are bound, destroy pool connection
2018-02-01 12:35:19 +00:00
# 1. Send END msg to pool (but wait for it to manage last logger)
sleep 2;
$ROOT/write master "END${POOL_KEY}END";
# 2. Close pool connection
echo -e "\e[31m+\e[0m close connection to $POOL_HOST:$POOL_PORT ";
2018-01-31 23:31:21 +00:00
kill -INT $MASTER_PID 2>/dev/null;
2018-01-31 19:55:11 +00:00
2018-02-01 12:35:19 +00:00
echo " + ${#LOGGER_PID[@]} loggers running in background";
2018-01-31 19:55:11 +00:00
for logger_name in "${!LOGGER_PID[@]}"; do
wait ${LOGGER_PID[$logger_name]};
2018-02-01 12:35:19 +00:00
done;
on_exit;