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
223
224
225
226
227
228
229
|
#!/bin/sh
# Remove comment from next line if this script fails and you need more
# information of what's going on
#set -x -v
set -e
silent="-s"
if [ -z "$maria_path" ]
then
maria_path="."
fi
# test data is always put in the current directory or a tmp subdirectory of it
tmp="./tmp"
if test '!' -d $tmp
then
mkdir $tmp
fi
echo "MARIA RECOVERY TESTS"
if $maria_path/maria_read_log --help | grep IDENTICAL_PAGES_AFTER_RECOVERY
then
echo "Recovery tests require compilation with DBUG"
echo "Aborting test"
exit 0
fi
check_table_is_same()
{
# Computes checksum of new table and compares to checksum of old table
# Shows any difference in table's state (info from the index's header)
# Data/key file length is random in ma_test2 (as it uses srand() which
# may differ between machines).
$maria_path/maria_chk -dvv $table | grep -v "Creation time:" | grep -v "file length"> $tmp/maria_chk_message.txt 2>&1
$maria_path/maria_chk -s -e --read-only $table
checksum2=`$maria_path/maria_chk -dss $table`
if test "$checksum" != "$checksum2"
then
echo "checksum differs for $table before and after recovery"
return 1;
fi
diff $tmp/maria_chk_message.good.txt $tmp/maria_chk_message.txt > $tmp/maria_chk_diff.txt || true
if [ -s $tmp/maria_chk_diff.txt ]
then
echo "Differences in maria_chk -dvv, recovery not yet perfect !"
echo "========DIFF START======="
cat $tmp/maria_chk_diff.txt
echo "========DIFF END======="
fi
}
apply_log()
{
# applies log, can verify if applying did write to log or not
shouldchangelog=$1
if [ "$shouldchangelog" != "shouldnotchangelog" ] &&
[ "$shouldchangelog" != "shouldchangelog" ] &&
[ "$shouldchangelog" != "dontknow" ]
then
echo "bad argument '$shouldchangelog'"
return 1
fi
log_md5=`md5sum maria_log.*`
echo "applying log"
$maria_path/maria_read_log -a > $tmp/maria_read_log_$table.txt
log_md5_2=`md5sum maria_log.*`
if [ "$log_md5" != "$log_md5_2" ]
then
if [ "$shouldchangelog" == "shouldnotchangelog" ]
then
echo "maria_read_log should not have modified the log"
return 1
fi
else
if [ "$shouldchangelog" == "shouldchangelog" ]
then
echo "maria_read_log should have modified the log"
return 1
fi
fi
}
# To not flood the screen, we redirect all the commands below to a text file
# and just give a final error if their output is not as expected
(
echo "Testing the REDO PHASE ALONE"
# runs a program inserting/deleting rows, then moves the resulting table
# elsewhere; applies the log and checks that the data file is
# identical to the saved original.
# Does not test the index file as we don't have logging for it yet.
set -- "ma_test1 $silent -M -T -c" "ma_test2 $silent -L -K -W -P -M -T -c -d500" "ma_test2 $silent -M -T -c -b65000" "ma_test2 $silent -M -T -c -b65000 -d800"
while [ $# != 0 ]
do
prog=$1
rm -f maria_log.* maria_log_control
echo "TEST WITH $prog"
$maria_path/$prog
# derive table's name from program's name
table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' `
$maria_path/maria_chk -dvv $table | grep -v "Creation time:" | grep -v "file length"> $tmp/maria_chk_message.good.txt 2>&1
checksum=`$maria_path/maria_chk -dss $table`
mv $table.MAD $tmp/$table-good.MAD
mv $table.MAI $tmp/$table-good.MAI
apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table-good.MAD
cmp $table.MAI $tmp/$table-good.MAI
check_table_is_same
echo "testing idempotency"
apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table-good.MAD
cmp $table.MAI $tmp/$table-good.MAI
check_table_is_same
shift
done
echo "Testing the REDO AND UNDO PHASE"
# The test programs look like:
# work; commit (time T1); work; exit-without-commit (time T2)
# We first run the test program and let it exit after T1's commit.
# Then we run it again and let it exit at T2. Then we compare
# and expect identity.
for take_checkpoint in "no" "yes"
do
# we test table without blobs and then table with blobs
for blobs in "" "-b32768"
do
for test_undo in 1 2 3 4
do
# first iteration tests rollback of insert, second tests rollback of delete
set -- "ma_test1 $silent -M -T -c -N $blobs -H1" "--testflag=1" "--testflag=2 --test-undo=" "ma_test1 $silent -M -T -c -N $blobs -H2" "--testflag=3" "--testflag=4 --test-undo=" "ma_test1 $silent -M -T -c -N $blobs -H2" "--testflag=2" "--testflag=3 --test-undo=" "ma_test2 $silent -L -K -W -P -M -T -c $blobs -H1" "-t1" "-t2 -A" "ma_test2 $silent -L -K -W -P -M -T -c $blobs -H1" "-t1" "-t6 -A"
# -N (create NULL fields) is needed because --test-undo adds it anyway
while [ $# != 0 ]
do
prog=$1
if [ "$take_checkpoint" == "no" ]
then
prog=`echo $prog | sed 's/ -H[0-9]//'`
fi
commit_run_args=$2
abort_run_args=$3;
rm -f maria_log.* maria_log_control
echo "TEST WITH $prog $commit_run_args (commit at end)"
$maria_path/$prog $commit_run_args
# derive table's name from program's name
table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' `
$maria_path/maria_chk -dvv $table | grep -v "Creation time:" | grep -v "file length"> $tmp/maria_chk_message.good.txt 2>&1
checksum=`$maria_path/maria_chk -dss $table`
mv $table.MAD $tmp/$table-good.MAD
mv $table.MAI $tmp/$table-good.MAI
rm maria_log.* maria_log_control
echo "TEST WITH $prog $abort_run_args$test_undo (additional aborted work)"
$maria_path/$prog $abort_run_args$test_undo
cp $table.MAD $tmp/$table-before_undo.MAD
cp $table.MAI $tmp/$table-before_undo.MAI
# The lines below seem unneeded, will be removed soon
# We have to copy and restore logs, as running maria_read_log will
# change the maria_control_file
# rm -f $tmp/maria_log.* $tmp/maria_log_control
# cp $maria_path/maria_log* $tmp
if [ "$test_undo" != "3" ]
then
apply_log "shouldchangelog" # should undo aborted work
else
# probably nothing to undo went to log or data file
apply_log "dontknow"
fi
cp $table.MAD $tmp/$table-after_undo.MAD
cp $table.MAI $tmp/$table-after_undo.MAI
# It is impossible to do a "cmp" between .good and .after_undo,
# because the UNDO phase generated log
# records whose LSN tagged pages. Another reason is that rolling back
# INSERT only marks the rows free, does not empty them (optimization), so
# traces of the INSERT+rollback remain.
check_table_is_same
echo "testing idempotency"
apply_log "shouldnotchangelog"
# We can't do a binary compary as there may have been different number
# of calls to compact_page. We can enable this if we first call
# maria-check to generate identically compacted pages.
# cmp $table.MAD $tmp/$table-after_undo.MAD
cmp $table.MAI $tmp/$table-after_undo.MAI
check_table_is_same
echo "testing applying of CLRs to recreate table"
rm $table.MA?
# cp $tmp/maria_log* $maria_path #unneeded
apply_log "shouldnotchangelog"
# cmp $table.MAD $tmp/$table-after_undo.MAD
cmp $table.MAI $tmp/$table-after_undo.MAI
check_table_is_same
shift 3
done
rm -f $table.* $tmp/$table* $tmp/maria_chk_*.txt $tmp/maria_read_log_$table.txt
done
done
done
) 2>&1 > $tmp/ma_test_recovery.output
if [ "$?" != 0 ]
then
echo "Some test failed"
exit 1
fi
# also note that maria_chk -dvv shows differences for ma_test2 in UNDO phase,
# this is normal: removing records does not shrink the data/key file,
# does not put back the "analyzed,optimized keys"(etc) index state.
diff $maria_path/ma_test_recovery.expected $tmp/ma_test_recovery.output > /dev/null || diff_failed=1
if [ "$diff_failed" == "1" ]
then
echo "UNEXPECTED OUTPUT OF TESTS, FAILED"
echo "For more info, do diff $maria_path/ma_test_recovery.expected $tmp/ma_test_recovery.output"
exit 1
fi
echo "ALL RECOVERY TESTS OK"
|