-
Notifications
You must be signed in to change notification settings - Fork 2
/
all_traces_generate_plots.sh
executable file
·149 lines (135 loc) · 4.47 KB
/
all_traces_generate_plots.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/bin/bash
# reliable way to get the directory where this file is stored
SCRIPT=$(readlink -f $0)
export SCRIPTPATH=`dirname $SCRIPT`
SCRIPTNAME=$(basename "$SCRIPT")
export STS_DIR=$SCRIPTPATH
if [ "$#" -lt 1 ]
then
echo "Usage: ./$SCRIPTNAME [-t threads] <sdnracer-traces folder path> [<pattern for matching directories, default is \"trace_*\">]"
echo "or ./$SCRIPTNAME -i <single trace folder path>"
exit 1
fi
# Note variables used here must have been exported before
run_per_trace_dir() {
# echo "Generating plots for trace $1"
pushd "$1" > /dev/null
TRACE_DIR=$(readlink -f $1)
echo "$STS_DIR/plot.py $TRACE_DIR"
$STS_DIR/plot.py "$TRACE_DIR"
popd > /dev/null
}
export -f run_per_trace_dir
trace_dirs_array=()
export IS_SINGLE_JOB=false
IS_OVERRIDE_NUM_THREADS=false
case "$1" in
-i)
if [ "$#" -eq 2 ]
then
trace_dirs_array+=("$2")
export IS_SINGLE_JOB=true
else
echo "No trace directory specified for option -i"
exit 1
fi
;;
-t)
if [ "$#" -eq 4 ]
then
IS_OVERRIDE_NUM_THREADS=true
NUM_THREADS=$2
shift # shift arguments to the left
shift
else
echo "Wrong number of arguments."
exit 1
fi
;& #fallthrough
*)
WORKSPACE=$1
# set default value if not set
MATCHPATTERN=${2:-"trace_*"}
# get trace directories, reads NUL-terminated strings of filenames into an array. This is the only way to do it safely.
# sort -z preserves NULs, -n sorts by name
while IFS= read -r -d $'\0'; do
trace_dirs_array+=("$REPLY")
done < <(find "$WORKSPACE" -maxdepth 1 -type d -name "$MATCHPATTERN" -print0 | sort -nz)
;;
esac
echo "${#trace_dirs_array[@]} directories to be processed:"
for i in "${trace_dirs_array[@]}"; do
echo " " "$i"
done;
pidtree(){
pids_for_ppid=(); while read pid ppid; do pids_for_ppid[$ppid]+=" $pid"; done < <(ps -e -o pid,ppid --no-headers)
print_children(){ for i in ${pids_for_ppid[$1]}; do ( (print_children $i) ); echo $i; done }
( (print_children $1) ); echo $1
}
export -f pidtree
# create tmp directory
export CURRENT_TMP_DIR=`mktemp -d`
# set trap to cleanup upon exit/CTRL-C. Note: not triggered when using kill -9.
trap 'echo "Received CTRL-C"; for i in $CURRENT_TMP_DIR/*.pid; do kill $(pidtree $(basename "${i%.pid}")) >> /dev/null 2>&1; rm -f "$i"; done; rm -rf "$CURRENT_TMP_DIR"' INT
func_call_by_name(){
if [ "$IS_SINGLE_JOB" = true ]
then
# no redirection, no tmpfile
# call function $1 with all remaining arguments
$1 "${@:2}" & FUNC_PID=$!; touch "$CURRENT_TMP_DIR/$FUNC_PID.pid"; wait $FUNC_PID; rm -f "$CURRENT_TMP_DIR/$FUNC_PID.pid"
else
# redirect output to tmpfile, then print out once done
FUNC_CALL_OUTPUT_TMPFILE=$(mktemp --tmpdir="$CURRENT_TMP_DIR")
# echo "Storing output temporarily in $FUNC_CALL_OUTPUT_TMPFILE"
$1 "${@:2}" >> "$FUNC_CALL_OUTPUT_TMPFILE" 2>&1 & FUNC_PID=$!; touch "$CURRENT_TMP_DIR/$FUNC_PID.pid"; wait $FUNC_PID; rm -f "$CURRENT_TMP_DIR/$FUNC_PID.pid"
# print output once done, if file still exists
[[ -f "$FUNC_CALL_OUTPUT_TMPFILE" ]] && cat "$FUNC_CALL_OUTPUT_TMPFILE"
# remove temp file
rm -f "$FUNC_CALL_OUTPUT_TMPFILE"
fi
}
export -f func_call_by_name
# How this works:
# (Equivalent to: parallel generate_plots ::: "${trace_dirs_array[@]}")
# 1. print each entry in the array followed by a NUL char (\x00)
# 2. xargs:
# -0 handle NUL chars as delimiter
# -i use {}
# -n 1 pass at most 1 entry from the array to each process
# -P N run N processes in parallel
NUM_CPU_CORES=$(cat /proc/cpuinfo | egrep ^processor | wc -l)
case $NUM_CPU_CORES in
''|*[!0-9]*)
# not a number, let's set it to 1
NUM_CPU_CORES=1
;;
*)
if [ "$NUM_CPU_CORES" -lt 1 ]
then
NUM_CPU_CORES=1
fi
;;
esac
if [ "$IS_OVERRIDE_NUM_THREADS" = false ]
then
NUM_THREADS=$NUM_CPU_CORES
fi
if [ "${#trace_dirs_array[@]}" -lt "$NUM_THREADS" ]
then
NUM_THREADS="${#trace_dirs_array[@]}"
fi
echo "NUM_CPU_CORES=$NUM_CPU_CORES, NUM_THREADS=$NUM_THREADS"
if [ "${#trace_dirs_array[@]}" -gt 0 ]
then
pushd "$WORKSPACE" > /dev/null
echo "cross_summary.sh"
pushd "$1" > /dev/null
find "$WORKSPACE" -maxdepth 1 -type d -name "$MATCHPATTERN" -print0 | sort -nz | xargs -0 -n "${#trace_dirs_array[@]}" -x $STS_DIR/cross_summary.sh
popd > /dev/null
fi
if [ "$NUM_THREADS" -gt 0 ]
then
printf "%s\x00" "${trace_dirs_array[@]}" | xargs -0 -I{} -n 1 -P $NUM_THREADS bash -c 'func_call_by_name run_per_trace_dir {}'
fi
rm -rf "$CURRENT_TMP_DIR"
echo "Done."