From: Martin Schwenke Date: Wed, 2 Aug 2023 03:23:58 +0000 (+1000) Subject: ctdb-scripts: Improve update and listing code X-Git-Tag: tdb-1.4.13~342 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e6a85d128f7ada419fc13ca72a295533674e7840;p=thirdparty%2Fsamba.git ctdb-scripts: Improve update and listing code Drop the complexity associated with using awk to escape dots in IPv4 addresses to protect them from sed, and generate a grep -F filter instead. For listing, the pipeline is now longer, but the steps are now clearer: 1. List DB records 2. Extract keys 3. Keep only keys machine hosted public IPs 4. Parse out server IP and client IP 5. Sort Performance here isn't critical, so having clearer code is preferable. Use temporary files to avoid command-line length limits. Also, drop the cd to the queue directory during update. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- diff --git a/ctdb/tools/statd_callout_helper b/ctdb/tools/statd_callout_helper index 7bf747d1b25..b29515c9993 100755 --- a/ctdb/tools/statd_callout_helper +++ b/ctdb/tools/statd_callout_helper @@ -172,6 +172,17 @@ ${CTDB_MY_PUBLIC_IPS_CACHE} EOF } +# Used via 'grep -F -f "$persistent_db_grep_filter"' to match database +# keys currently hosted public IPs +persistent_db_grep_filter="${statd_callout_state_dir}/.grep_filter" + +persistent_db_make_grep_filter() +{ + while read -r _ip; do + echo "statd-state@${_ip}@" + done <"$CTDB_MY_PUBLIC_IPS_CACHE" >"$persistent_db_grep_filter" +} + ############################################################ case "$1" in @@ -180,25 +191,28 @@ startup) ;; update) - cd "$statd_callout_queue_dir" || - die "Failed to change directory to \"${statd_callout_queue_dir}\"" - files=$(echo statd-state@*) - if [ "$files" = "statd-state@*" ]; then + files="${statd_callout_state_dir}/.file_list" + find "$statd_callout_queue_dir" -name "statd-state@*" >"$files" + if [ ! -s "$files" ]; then # No files! + rm "$files" exit 0 fi - sed_expr=$(awk '{ - ip = $1; gsub(/\./, "\\.", ip); - printf "/statd-state@%s@/p\n", ip }' "$CTDB_MY_PUBLIC_IPS_CACHE") - # Intentional multi-word expansion for multiple files - # shellcheck disable=SC2086 - items=$(sed -n "$sed_expr" $files) - if [ -n "$items" ]; then - if echo "$items" | $CTDB ptrans "$statd_callout_db"; then - # shellcheck disable=SC2086 - rm $files + + persistent_db_make_grep_filter + + # Use cat instead of direct grep since POSIX grep does not + # have -h + items="${statd_callout_state_dir}/.items" + xargs cat <"$files" | grep -F -f "$persistent_db_grep_filter" >"$items" + + if [ -s "$items" ]; then + if $CTDB ptrans "$statd_callout_db" <"$items"; then + xargs rm -f <"$files" fi fi + + rm -f "$files" "$persistent_db_grep_filter" "$items" ;; notify) @@ -222,21 +236,27 @@ notify) sleep 2 "$CTDB_NFS_CALLOUT" "start" "nlockmgr" >/dev/null 2>&1 - # Construct a sed expression to take catdb output and produce pairs of: - # server-IP client-IP - # but only for the server-IPs that are hosted on this node. - sed_expr=$(awk '{ - ip = $1; gsub(/\./, "\\.", ip); - printf "s/^key.*=.*statd-state@\\(%s\\)@\\([^\"]*\\).*/\\1 \\2/p\n", ip }' \ - "$CTDB_MY_PUBLIC_IPS_CACHE") - - statd_state=$($CTDB catdb "$statd_callout_db" | - sed -n "$sed_expr" | - sort) - [ -n "$statd_state" ] || exit 0 - - echo "$statd_state" | send_notifies - echo "$statd_state" | delete_records + persistent_db_make_grep_filter + + # Produce "server-IP client-IP" per-line in .statd_state + statd_state="${statd_callout_state_dir}/.statd_state" + $CTDB catdb "$statd_callout_db" | + sed -n -e 's|^key([0-9]*) = "\([^"]*\)".*|\1|p' | + grep -F -f "$persistent_db_grep_filter" | + sed -e 's|statd-state@\([^@]*\)@\(.*\)|\1 \2|' | + sort >"$statd_state" + + rm -f "$persistent_db_grep_filter" + + if [ ! -s "$statd_state" ]; then + rm -f "$statd_state" + exit 0 + fi + + send_notifies <"$statd_state" + delete_records <"$statd_state" + + rm -f "$statd_state" # Remove any stale touch files (i.e. for IPs not currently # hosted on this node and created since the last "update").