forked from mongodb-labs/mongoreplay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreplay_test.sh
executable file
·222 lines (195 loc) · 5.04 KB
/
replay_test.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PORT=28080
INTERFACE=lo
KEEP=false
DBPATH="$SCRIPT_DIR/data/mongoreplay"
SILENT="--silent"
EXPLICIT=
VERBOSE=
DEBUG=
WORKLOADS=()
ASSERTIONS=()
log() {
>&2 echo $@
}
while test $# -gt 0; do
case "$1" in
-h|--help)
>&2 cat <<< "Usage: `basename $0` [OPTIONS]
-a, --assert JS-BOOL condition for assertion after workload (used with -w);
can be specified in multiplicity
--dbpath path for mongod, can be cleared by program
(defaults to $DBPATH)
-e, --explicit show comparison scores for all individual metrics
-i, --interface NI network interface (defaults to $INTERFACE)
-k, --keep keep temp files
-p, --port PORT use port PORT (defaults to $PORT)
-v, --verbose unsilence mongoreplay and make it slightly loud
-w, --workload JS-FILE mongo shell workload script (used with -a);
runs concurrent workloads when specified in
multiplicity
"
exit 1
;;
-a|--assert)
shift
ASSERTIONS+=("$1")
shift
;;
-e|--explicit)
shift
EXPLICIT="--explicit"
;;
-i|--interface)
shift
INTERFACE="$1"
shift
;;
-k|--keep)
shift
KEEP=true
;;
-p|--port)
shift
PORT="$1"
shift
;;
-v|--verbose)
shift
SILENT=
VERBOSE="-vv"
DEBUG="-dd"
;;
-w|--workload)
shift
WORKLOADS+=("$1")
shift
;;
--dbpath)
shift
DBPATH="$1"
shift
;;
*)
log "Unknown arg: $1"
exit 1
esac
done
if [ ${#WORKLOADS[@]} -eq 0 ]; then
# default workload/assert
WORKLOADS=( "$SCRIPT_DIR/testWorkloads/crud.js" )
MONGOASSERT=( 'db.bench.count() === 15000' )
elif [ ${#ASSERTIONS[@]} -eq 0 ]; then
log "must specify BOTH -a/--assert AND -w/--workload"
exit 1
fi
command -v mongoreplay >/dev/null
if [ $? != 0 ]; then
log "mongoreplay must be in PATH"
exit 1
fi
command -v ftdc >/dev/null
if [ $? != 0 ]; then
log "ftdc command (github.com/10gen/ftdc-utils) must be in PATH"
exit 1
fi
set -e
rm -rf $DBPATH
mkdir $DBPATH
log "starting MONGOD"
mongod --port=$PORT --dbpath=$DBPATH >/dev/null &
MONGOPID=$!
check_integrity() {
set +e
for ((i = 0; i < ${#ASSERTIONS[@]}; i++))
do
assertion="${ASSERTIONS[$i]}"
mongo --port=$PORT --quiet mongoreplay_test --eval "assert($assertion)" >/dev/null
STATUS=$?
if [ $STATUS != 0 ]; then
log "integrity check FAILED: $assertion"
log "for further analysis, check db at localhost:$PORT, pid=$MONGOPID"
exit 1
fi
done
set -e
}
sleep 1
mongo --port=$PORT mongoreplay_test --eval "db.dropDatabase()" >/dev/null 2>&1
log "starting TCPDUMP"
sudo tcpdump -i "$INTERFACE" port "$PORT" -w tmp.pcap &
TCPDUMPPID=$!
sleep 1 # make sure it actually starts capturing
log "starting WORKLOAD"
START=`date`
sleep 1
# fork
WorkerPIDs=()
for ((i = 0; i < ${#WORKLOADS[@]}; i++))
do
script="${WORKLOADS[$i]}"
mongo --port=$PORT --quiet mongoreplay_test "$script" >/dev/null &
WorkerPIDs+=("$!")
done
# join
for pid in "${WorkerPIDs[@]}"
do wait $pid
done
sleep 1
END=`date`
log "finished WORKLOAD"
log "stopping TCPDUMP"
( sleep 1 ; sudo kill $TCPDUMPPID) &
wait $TCPDUMPPID
check_integrity
# clean up database
mongo --port=$PORT mongoreplay_test --eval "db.dropDatabase()" >/dev/null 2>&1
sleep 1 # mongoreplay play should certainly happen after the drop
log "running mongoreplay RECORD"
mongoreplay record $SILENT $VERBOSE $DEBUG -f=tmp.pcap -p=tmp.playback >/dev/null
TAPECODE=$?
if [ "$TAPECODE" != 0 ]; then
log "mongoreplay failed with code $TAPECODE"
exit 1
fi
log # newline to separate replay
log "starting mongoreplay PLAY"
REPLAY_START=`date`
sleep 1
mongoreplay play $SILENT $VERBOSE $DEBUG --host "localhost:$PORT" -p=tmp.playback --report tmp.report >/dev/null
sleep 1
REPLAY_END=`date`
log "finished mongoreplay PLAY"
check_integrity
log "flushing FTDC diagnostic files (15 sec)"
sleep 15
log "killing MONGOD"
mongo --port=$PORT mongoreplay_test --eval "db.dropDatabase()" >/dev/null 2>&1
sleep 1
kill $MONGOPID
sleep 2 # give it a chance to dump FTDC
log "gathering FTDC statistics"
if $KEEP; then
# dump raw ftdc
ftdc decode -ms $DBPATH/diagnostic.data/* --start="$START" --end="$END" --out="tmp.base.json"
ftdc decode -ms $DBPATH/diagnostic.data/* --start="$REPLAY_START" --end="$REPLAY_END" --out="tmp.play.json"
fi
log "base time START: $START"
log "base time END: $END"
log "replay time START: $REPLAY_START"
log "replay time END: $REPLAY_END"
log -n "base: "
ftdc stats $DBPATH/diagnostic.data/* --start="$START" --end="$END" --out="tmp.base.stat.json"
log -n "replay: "
ftdc stats $DBPATH/diagnostic.data/* --start="$REPLAY_START" --end="$REPLAY_END" --out="tmp.play.stat.json"
set +e
ftdc compare $EXPLICIT tmp.base.stat.json tmp.play.stat.json
CODE=$?
if [ ! $KEEP ]; then
rm tmp.playback
rm tmp.base.stat.json
rm tmp.play.stat.json
rm tmp.report
fi
exit $CODE