mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2026-08-28 20:06:05 +00:00
feat: Use atomic writes for progress updates (#1319)
This commit is contained in:
+64
-5
@@ -2,6 +2,7 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
info="/run/shm/msg.html"
|
||||
info_tmp="${info}.${BASHPID}.tmp"
|
||||
|
||||
escape() {
|
||||
|
||||
@@ -17,6 +18,23 @@ escape() {
|
||||
return 0
|
||||
}
|
||||
|
||||
writeInfo() {
|
||||
|
||||
local content="$1"
|
||||
|
||||
if ! printf '%s\n' "$content" > "$info_tmp"; then
|
||||
rm -f -- "$info_tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! mv -f -- "$info_tmp" "$info"; then
|
||||
rm -f -- "$info_tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getBytes() {
|
||||
|
||||
local path="$1"
|
||||
@@ -48,6 +66,24 @@ getBytes() {
|
||||
return 0
|
||||
}
|
||||
|
||||
getStatus() {
|
||||
|
||||
local file="$1"
|
||||
local bytes total extra=""
|
||||
|
||||
[ -r "$file" ] || return 1
|
||||
read -r bytes total extra < "$file" || return 1
|
||||
|
||||
if [[ ! "$bytes" =~ ^[0-9]+$ ||
|
||||
! "$total" =~ ^[0-9]+$ ||
|
||||
-n "$extra" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s %s\n' "$bytes" "$total"
|
||||
return 0
|
||||
}
|
||||
|
||||
formatSize() {
|
||||
|
||||
local bytes="$1"
|
||||
@@ -117,7 +153,9 @@ printSizeProgress() {
|
||||
return 0
|
||||
}
|
||||
|
||||
finishLogProgress() {
|
||||
finishProgress() {
|
||||
|
||||
rm -f -- "$info_tmp"
|
||||
|
||||
if [[ "$output" == "log" && "$printed" == "Y" ]]; then
|
||||
printf '\n'
|
||||
@@ -132,6 +170,7 @@ body=$(escape "$3")
|
||||
output="${4:-}"
|
||||
step_bytes="${5:-536870912}"
|
||||
mode="${6:-apparent}"
|
||||
status_file="${7:-}"
|
||||
|
||||
if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then
|
||||
printf 'Invalid total size: %s\n' "$total" >&2
|
||||
@@ -168,7 +207,7 @@ if [ -z "$total" ] || [[ "$total" == "0" ]]; then
|
||||
log_mode="size"
|
||||
fi
|
||||
|
||||
trap finishLogProgress EXIT
|
||||
trap finishProgress EXIT
|
||||
trap 'exit 0' HUP INT QUIT TERM
|
||||
|
||||
if [[ "$body" == *"..." ]]; then
|
||||
@@ -178,12 +217,32 @@ fi
|
||||
while true; do
|
||||
|
||||
bytes=$(getBytes "$path" "$mode")
|
||||
effective_total="$total"
|
||||
|
||||
if [ -n "$status_file" ] && status=$(getStatus "$status_file"); then
|
||||
read -r status_bytes status_total <<< "$status"
|
||||
bytes="$status_bytes"
|
||||
|
||||
if (( status_total > 0 )); then
|
||||
effective_total="$status_total"
|
||||
fi
|
||||
fi
|
||||
|
||||
# A real total may become available shortly after aria2 starts.
|
||||
if [[ "$log_mode" == "size" &&
|
||||
"$printed" == "N" &&
|
||||
-n "$effective_total" &&
|
||||
"$effective_total" != "0" ]]; then
|
||||
log_mode="percent"
|
||||
fi
|
||||
|
||||
if (( bytes > 4096 )); then
|
||||
|
||||
write_html="Y"
|
||||
|
||||
if [ -z "$total" ] || [[ "$total" == "0" ]] || (( bytes > total )); then
|
||||
if [ -z "$effective_total" ] ||
|
||||
[[ "$effective_total" == "0" ]] ||
|
||||
(( bytes > effective_total )); then
|
||||
size=$(formatSize "$bytes")
|
||||
|
||||
if [[ "$output" == "log" ]]; then
|
||||
@@ -197,7 +256,7 @@ while true; do
|
||||
fi
|
||||
else
|
||||
# Truncate to one decimal so progress is never reported early.
|
||||
progress=$((bytes * 1000 / total))
|
||||
progress=$((bytes * 1000 / effective_total))
|
||||
(( progress > 1000 )) && progress=1000
|
||||
|
||||
percent=$((progress / 10))
|
||||
@@ -219,7 +278,7 @@ while true; do
|
||||
fi
|
||||
|
||||
if [[ "$write_html" == "Y" ]]; then
|
||||
printf '%s\n' "${body//(\[P\])/($size)}" > "$info"
|
||||
writeInfo "${body//(\[P\])/($size)}"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
+18
-5
@@ -3,6 +3,8 @@ set -Eeuo pipefail
|
||||
|
||||
lastmsg=""
|
||||
path="/run/shm/msg.html"
|
||||
dir=$(dirname -- "$path")
|
||||
name=$(basename -- "$path")
|
||||
|
||||
refresh() {
|
||||
|
||||
@@ -17,15 +19,26 @@ refresh() {
|
||||
|
||||
lastmsg="$msg"
|
||||
echo "s: $msg"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
refresh
|
||||
|
||||
inotifywait -m "$path" |
|
||||
while read -r fp event fn; do
|
||||
inotifywait \
|
||||
-m -q \
|
||||
-e close_write,moved_to,delete \
|
||||
--format '%e %f' \
|
||||
"$dir" |
|
||||
while read -r event file; do
|
||||
|
||||
[[ "$file" == "$name" ]] || continue
|
||||
|
||||
case "${event,,}" in
|
||||
"modify"* ) refresh ;;
|
||||
"delete_self" ) echo "c: vnc" ;;
|
||||
esac
|
||||
"delete"* )
|
||||
echo "c: vnc" ;;
|
||||
"close_write"* | "moved_to"* )
|
||||
refresh ;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
+21
-2
@@ -300,6 +300,25 @@ writeFile() {
|
||||
return 0
|
||||
}
|
||||
|
||||
writeAtomic() {
|
||||
|
||||
local path="$1"
|
||||
local content="$2"
|
||||
local tmp="${path}.${BASHPID}.tmp"
|
||||
|
||||
if ! printf '%s\n' "$content" > "$tmp"; then
|
||||
rm -f -- "$tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! mv -f -- "$tmp" "$path"; then
|
||||
rm -f -- "$tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
readFile() {
|
||||
|
||||
local path="$1"
|
||||
@@ -411,8 +430,8 @@ html() {
|
||||
HTML="${HTML/\[4\]/$footer}"
|
||||
HTML="${HTML/\[5\]/$FOOTER2}"
|
||||
|
||||
echo "$HTML" > "$PAGE" || return 1
|
||||
echo "$body" > "$INFO" || return 1
|
||||
writeAtomic "$PAGE" "$HTML" || return 1
|
||||
writeAtomic "$INFO" "$body" || return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user