#!/usr/bin/env bash # Run the fetch_ring test, sanity check the output and check hot keys # statistics . "${TEST_SCRIPTS_DIR}/integration.bash" set -e ctdb_test_init testdb="fetch_ring.tdb" ctdb_get_all_pnns # $all_pnns is set above # shellcheck disable=SC2154 num_nodes=$(echo "$all_pnns" | wc -w | tr -d '[:space:]') first=$(echo "$all_pnns" | sed -n -e '1p') get_key () { _n="$1" echo "testkey${_n}" } run_fetch_ring () { _timelimit="$1" _key_num="$2" _key=$(get_key "$_key_num") _base_cmd="fetch_ring -n ${num_nodes} -D ${testdb}" _cmd="${_base_cmd} -t ${_timelimit} -k ${_key}" echo "Running \"${_cmd}\" on all $num_nodes nodes." testprog_onnode -v -p all "$_cmd" _pat='^(Waiting for cluster|Fetch\[[[:digit:]]+\]: [[:digit:]]+(\.[[:digit:]]+)? msgs/sec)$' sanity_check_output 1 "$_pat" # Get the last line of output. # $outfile is set above by testprog_onnode() # shellcheck disable=SC2154 _last=$(tail -n 1 "$outfile") # $last should look like this: # Fetch[1]: 10670.93 msgs/sec _stuff="${_last##*Fetch\[*\]: }" _mps="${_stuff% msgs/sec*}" if [ "${_mps%.*}" -ge 10 ] ; then echo "OK: ${_mps} msgs/sec >= 10 msgs/sec" else ctdb_test_fail "BAD: ${_mps} msgs/sec < 10 msgs/sec" fi } check_hot_keys () { _pnn="$1" _first_key="$2" _num_keys="$3" echo echo "Checking hot keys on node ${_pnn}" ctdb_onnode "$_pnn" dbstatistics "$testdb" # Get hot keys with a non-empty key _hotkeys=$(grep -Ex '[[:space:]]+Count:[[:digit:]]+ Key:[[:xdigit:]]+' \ "$outfile") || true # Check that there are the right number of non-empty slots if [ -z "$_hotkeys" ] ; then _num=0 else _num=$(echo "$_hotkeys" | wc -l | tr -d '[:space:]') fi _msg="hot key slots in use = ${_num}" if [ "$_num_keys" -ne "$_num" ] ; then echo cat "$outfile" ctdb_test_fail "BAD: ${_msg} (expected ${_num_keys})" fi echo "GOOD: ${_msg}" # No hot keys? Done... if [ "$_num" = 0 ] ; then return fi # Check that hot key counts are correctly sorted # # Try to be as POSIX as possible # shellcheck disable=SC2001 _counts=$(echo "$_hotkeys" | \ sed -e 's|.*Count:\([[:digit:]][[:digit:]]*\).*|\1|') _counts_sorted=$(echo "$_counts" | sort -n) if [ "$_counts" != "$_counts_sorted" ] ; then echo cat "$outfile" ctdb_test_fail "BAD: hot keys not sorted" fi echo "GOOD: hot key counts are correctly sorted" # Check that all keys are considered hot for _j in $(seq "$_first_key" $((_first_key + _num_keys - 1))) ; do _key=$(get_key "$_j") _key_hex=$(printf '%s' "$_key" | \ od -A n -t x1 | \ tr -d '[:space:]') if ! echo "$_hotkeys" | grep -q "Key:${_key_hex}\$" ; then echo cat "$outfile" ctdb_test_fail "BAD: key \"${_key}\" is not a hot key" fi done echo "GOOD: all keys are listed as hot keys" } # Run fetch_ring for each of 10 keys. After each run confirm that all # keys used so far are considered hot keys (and do other hot key # sanity checks) on all nodes. for i in $(seq 1 10) ; do run_fetch_ring 5 "$i" for pnn in $all_pnns ; do check_hot_keys "$pnn" 1 "$i" done echo done echo echo "Resetting statistics on node ${first}" ctdb_onnode "$first" statisticsreset # Ensure that only node $first has had statistics reset for pnn in $all_pnns ; do if [ "$pnn" = "$first" ] ; then check_hot_keys "$pnn" 1 0 else check_hot_keys "$pnn" 1 10 fi done echo # Run fetch_ring for each of 3 new keys. After each run confirm that # the new keys used so far are considered hot keys (and do other hot # key sanity checks) on node $first. # # Note that nothing can be said about hot keys on other nodes, since # they may be an arbitrary blend of old and new keys. for i in $(seq 1 3) ; do run_fetch_ring 5 $((100 + i)) check_hot_keys 0 101 "$i" echo done