diff --git a/master b/master index deb2a35..3926289 100755 --- a/master +++ b/master @@ -38,6 +38,8 @@ LOCAL_IP="`ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 test -z "$LOCAL_IP" && echo "error: cannot get local IP address." && exit 1; +# (10) Create a temporary file # +TMPFILE="/dev/shm/master_pid"; @@ -46,30 +48,34 @@ test -z "$LOCAL_IP" && echo "error: cannot get local IP address." && exit 1; # (1) On-Exit routine # on_exit(){ - echo "- killing 'bind-output' sub processes"; - + echo "- killing ${#OUTPUT_PID[@]} output"; for logger_name in "${!OUTPUT_PID[@]}"; do # kill each logger OUTPUT - echo " - killing output@$logger_name"; + echo " - killing $logger_name (${OUTPUT_PID[$logger_name]})"; kill -INT ${OUTPUT_PID[$logger_name]} 2>/dev/null; done; + echo "- killing ${#LOGGER_PID[@]} loggers"; for logger_name in "${!LOGGER_PID[@]}"; do # kill each logger OUTPUT - echo " - killing logger@$logger_name"; + echo " - killing $logger_name (${LOGGER_PID[$logger_name]})"; kill -INT ${LOGGER_PID[$logger_name]} 2>/dev/null; done; - echo "- killing 'master' output socket"; + echo "- killing main output"; kill -INT $MASTER_PID 2>/dev/null; - echo "- killing 'master' loop"; + echo "- killing loop"; # kill -INT $LOOP_PID 2>/dev/null; + # delete tmp file + echo "- deleting tmp file"; + rm $TMPFILE 2>/dev/null; + } trap "on_exit;" HUP INT KILL TERM; @@ -81,8 +87,9 @@ trap "on_exit;" HUP INT KILL TERM; # (3) Connect to pool #--------------------------------------------------------# # (1) Bind-output # -echo "+ connect to $POOL_HOST:$POOL_PORT"; -MASTER_PID="`$ROOT/bind-output master $POOL_HOST $POOL_PORT`"; +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`"; echo " + flush connection before using it"; # $ROOT/write master ""; @@ -90,12 +97,12 @@ echo " + flush connection before using it"; # (4) Launch master manager #--------------------------------------------------------# # (1) For each logger -PORT="$MIN_PORT"; for logger_name in "${LOGGERS[@]}"; do echo " + logger '$logger_name'"; # Find an available port + PORT="$MIN_PORT"; while true; do # if port not in use -> use it @@ -107,8 +114,11 @@ for logger_name in "${LOGGERS[@]}"; do done; # listen for pool response (port number) - echo " + listen $PORT"; - FREEPORT_PID="`$ROOT/bind-input freeport $PORT`"; + echo -e " \e[32m+\e[0m listen $PORT"; + $ROOT/bind-input freeport $PORT > $TMPFILE; + FREEPORT_PID="`cat $TMPFILE`"; + + sleep 1; # send port request echo " + sending port request"; @@ -137,40 +147,44 @@ for logger_name in "${LOGGERS[@]}"; do done; # closing listen socket - echo " + received '$RESP'"; - echo " + stop listening on $PORT"; + echo -e " + received '\e[33m$RESP\e[0m'"; + echo -e " \e[31m+\e[0m stop listening on $PORT"; kill -INT $FREEPORT_PID 2>/dev/null; # empty response -> ignore - test -z "$RESP" && echo " - no answer > aborting" && continue; + test -z "$RESP" && echo " + no answer" && continue; # not a number -> ignore - echo -n "$RESP" | grep -P '^\d+$' >/dev/null || ( echo " - invalid format > aborting"; exit 1 ) || continue; + echo -n "$RESP" | grep -P '^\d+$' >/dev/null || ( echo " + invalid format"; exit 1 ) || continue; # Create output bound echo " + connecting to $POOL_HOST:$RESP"; - OUTPUT_PID[$logger_name]="`$ROOT/bind-output master_$logger_name $POOL_HOST $RESP`"; + $ROOT/bind-output $logger_name $POOL_HOST $RESP > $TMPFILE; + OUTPUT_PID[$logger_name]="`cat $TMPFILE`"; - echo " + launching logger"; + echo " + logger launched in background"; # launch logger bound to output - ( $LOGGER_DIR/$logger_name | cat > /tmp/outbuf_master_$logger_name )& + ( $LOGGER_DIR/$logger_name | cat > /tmp/outbuf_$logger_name )& LOGGER_PID[$logger_name]=$!; - echo " + background proccess" - - # increment port for next logger - PORT="`expr $PORT + 1`"; - done; # When all loggers are bound, destroy pool connection -echo "+ close connection to $POOL_HOST:$POOL_PORT "; + +# 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 "; kill -INT $MASTER_PID 2>/dev/null; -echo " + waiting for ${#LOGGER_PID[@]} inputs/loggers to end"; +echo " + ${#LOGGER_PID[@]} loggers running in background"; for logger_name in "${!LOGGER_PID[@]}"; do wait ${LOGGER_PID[$logger_name]}; -done; \ No newline at end of file +done; + +on_exit; \ No newline at end of file diff --git a/pool b/pool index 908dc07..0ab8c8c 100755 --- a/pool +++ b/pool @@ -18,29 +18,35 @@ test "$2" -gt "$MAX_PORT" -o "$2" -lt "$MIN_PORT" && echo "error: must be POOL_KEY="$1"; POOL_PORT="$2"; -# (5) init logger variables # -declare -A INPUT_PID; # will contain each bind-input pid +# (5) Create a temporary file # +TMPFILE="/dev/shm/pool_pid"; + # (6) Define on-exit routine # LOOP_PID=""; on_exit(){ + test -f /dev/shm/pool_input_pid && source /dev/shm/pool_input_pid && rm /dev/shm/pool_input_pid; - echo "- killing 'pool' loop"; + echo "- killing oop"; kill -INT $LOOP_PID 2>/dev/null; - echo "- killing ${#INPUT_PID[@]} background listeners"; + echo "- killing ${#INPUT_PID[@]} loggers"; for logger_name in "${!INPUT_PID[@]}"; do # kill each logger input - echo " - killing input@$logger_name (${INPUT_PID[$logger_name]})"; + echo " - killing $logger_name (${INPUT_PID[$logger_name]})"; test ! -z "${INPUT_PID[$logger_name]}" && kill -INT ${INPUT_PID[$logger_name]} 2>/dev/null; done; - echo "- killing 'pool' input listener ($POOL_PID)"; + echo "- killing main listener ($POOL_PID)"; kill -INT $POOL_PID 2>/dev/null; + # delete tmp file + echo "- deleting tmp file"; + rm $TMPFILE 2>/dev/null; + exit 1; } @@ -51,16 +57,18 @@ on_exit(){ # (2) Launch pool listener #--------------------------------------------------------# # (1) Bind-input # -echo "+ listen $POOL_PORT"; -POOL_PID="`$ROOT/bind-input pool $POOL_PORT`"; +echo -e "\e[32m+\e[0m listen $POOL_PORT"; +$ROOT/bind-input pool $POOL_PORT > $TMPFILE; +POOL_PID="`cat $TMPFILE`"; -# (4) Launch pool manager +# (3) Launch pool manager #--------------------------------------------------------# # infinite listener -PORT="$MIN_PORT"; ( + USED_PORTS=($POOL_PORT); + declare -A INPUT_PID; # will contain each bind-input pid trap "on_exit;" HUP INT KILL TERM; @@ -72,7 +80,12 @@ PORT="$MIN_PORT"; # Do nothing if empty msg or invalid format test -z "$MSG" && sleep .5 && continue; - echo " + received '$MSG'"; + echo -e " + received '\e[33m$MSG\e[0m'"; + + # check if END msg + test "$MSG" = "END${POOL_KEY}END" && echo -e "\e[31m+\e[0m stop listening on $POOL_PORT" && break; + + # check format echo -n "$MSG" | grep -vP '^([^:]+):([^:]+):([^:]+):([^:]+)$' >/dev/null && echo ' + invalid format' && sleep .5 && continue; # Extract ID - PORT @@ -81,19 +94,24 @@ PORT="$MIN_PORT"; LOGGER_HOST="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\3/'`"; LOGGER_PORT="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\4/'`"; + # check port format + echo -n "$LOGGER_PORT" | grep -vP "^\d+$" >/dev/null && echo ' + invalid format: NaN' && sleep .5 && continue; + # if ID does not match test "$KEY" != "$POOL_KEY" && echo ' + wrong id' && sleep .5 && continue; # create new listening socket - echo " + received logger: $LOGGER_NAME on $LOGGER_HOST:$LOGGER_PORT"; + echo " + new logger '$LOGGER_NAME' from $LOGGER_HOST"; # Find an available port - PORT="`expr $PORT + 1`"; + PORT="$MIN_PORT"; while true; do - # ignore pool port - test "$PORT" = "$POOL_PORT" && PORT="`expr $PORT + 1`" && continue; + # ignore already used ports + for used in ${USED_PORTS[*]}; do + test "$PORT" = "$used" && PORT="`expr $PORT + 1`" && continue; + done # if port not in use -> use it ss -tl4 "( sport = :$PORT )" | grep "$PORT" >/dev/null 2>&1 || break; @@ -111,12 +129,17 @@ PORT="$MIN_PORT"; # Bind-input for the logger at the free port found # Store bind-input PID - echo " + listen $PORT"; - INPUT_PID["$LOGGER_NAME"]="`$ROOT/bind-input $LOGGER_NAME $PORT`"; + echo -e " \e[32m+\e[0m listen $PORT ($LOGGER_NAME)"; + $ROOT/bind-input $LOGGER_NAME $PORT > $TMPFILE; + INPUT_PID["$LOGGER_NAME"]="`cat $TMPFILE`"; + declare -p INPUT_PID > /dev/shm/pool_input_pid; + + # add @PORT to used ports + USED_PORTS="$USED_PORTS $PORT"; # Notify that input is active to MASTER - echo " + sending back to port '$PORT' $LOGGER_HOST:$LOGGER_PORT"; + echo " + sending '$PORT' to $LOGGER_HOST:$LOGGER_PORT"; bash -c "exec 4<>/dev/tcp/$LOGGER_HOST/$LOGGER_PORT; echo -n \"$PORT\" >&4;"; echo " + background process"; @@ -126,9 +149,25 @@ PORT="$MIN_PORT"; )& LOOP_PID=$!; -# (3) Set exit management +# (4) Set exit management #--------------------------------------------------------# -trap "kill -INT $LOOP_PID;" HUP INT KILL TERM; +# (1) Set trap for "exit" signals # +trap "kill -INT $LOOP_PID 2>/dev/null;" HUP INT KILL TERM; +# (2) Wait for main loop to end wait $LOOP_PID; + +# (3) Wait for each daemon input to end # +test -f /dev/shm/pool_input_pid && source /dev/shm/pool_input_pid; +echo " + ${#INPUT_PID[@]} loggers running in background"; +for logger_name in "${!INPUT_PID[@]}"; do + + while [ -e /proc/${INPUT_PID[$logger_name]} ]; do + sleep .5 + done + echo " + $logger_name terminated (${INPUT_PID[$logger_name]})"; + +done; + +on_exit; \ No newline at end of file