mariadb/storage/maria/ma_test_recovery
unknown 0f1feefa03 WL#3071 Maria checkpoint
Ability for flush_pagecache_blocks() to flush only certain pages of
a file, as instructed by an option "filter" pointer-to-function argument;
Checkpoint and background dirty page flushing use that to flush only
pages which have been dirty for long enough and bitmap pages.
Fix for a bug in flush_cached_blocks() (no idea if it could produce
a bug in real life, but theoretically it is).
Testing checkpoint in ma_test_recovery via ma_test1 and ma_test2.
Background checkpoint & dirty pages flush thread is still disabled
by default in ha_maria.


mysql-test/r/maria.result:
  result update
storage/maria/ha_maria.cc:
  blank after function comment
storage/maria/ma_checkpoint.c:
  Using an enum instead of 0/1/2 (applying Sanja's review comments).
  The comment about "this is an horizon" can be removed as Sanja
  created translog_next_LSN() which parse_checkpoint_record() uses.
  Variables in ma_checkpoint_background() cannot be declared in the
  for() as their value must not be reset at each iteration!
storage/maria/ma_pagecache.c:
  adding to flush_pagecache_blocks() optional arguments 'filter'
  (pointer to function) and 'filter_arg'; if filter!=NULL this function
  will be called for each block of the file and will reply if this
  block and following ones should be flushed or not (3 possible
  replies).
  Fixing a bug when flush_cached_blocks() skips a pinned page: it has
  to unset PCBLOCK_IN_FLUSH set by flush_pagecache_blocks_int().
storage/maria/ma_pagecache.h:
  flush_pagecache_blocks() is changed to take "filter" and "filter_arg"
  arguments. "filter", if it is not NULL, may return one value
  among enum pagecache_flush_filter_result.
storage/maria/ma_recovery.c:
  open_count=0 when closing tables at the end of recovery.
storage/maria/ma_test1.c:
  Optional checkpoints (-H#) at various stages (stages similar
  to --testflag), for testing of checkpoints.
storage/maria/ma_test2.c:
  Optional checkpoints (-H#) at various stages (stages similar
  to -t), for testing of checkpoints.
storage/maria/ma_test_recovery.expected:
  Result update: the results of the additional test run with -H#
  (checkpoints) are added here. They are exactly identical to without
  checkpoints except that the index's Root (printed by maria_chk)
  is more correct when using checkpoints. This is because checkpoint
  flushed the state, so it happens to be correct, while no-checkpoint
  does not flush the state, and recovery does not recover indexes
  so Root is never fixed. When we recover indices, this will go away.
storage/maria/ma_test_recovery:
  We duplicate the loop of tests to add an additional run with
  checkpoints at various stages, to see if maria_read_log
  uses them fine.
2007-10-17 16:55:26 +02:00

217 lines
7.6 KiB
Bash
Executable file

#!/bin/sh
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"
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)
$maria_path/maria_chk -dvv $table | grep -v "Creation time:" > $tmp/maria_chk_message.txt 2>&1
# save the index file (because we want to test idempotency afterwards)
cp $table.MAI tmp/
# In the repair below it's good to use -q because it will die on any
# incorrectness of the data file if UNDO was badly applied.
# QQ: Remove the following line when we also can recover the index file
$maria_path/maria_chk -s -rq $table
$maria_path/maria_chk -s -e $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
mv tmp/$table.MAI .
}
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
(
# this message is to remember about the problem with -b (see @todo below)
echo "!!!!!!!! REMEMBER to FIX this BLOB issue !!!!!!!"
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" "ma_test2 $silent -M -T -c -b"
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:"> $tmp/maria_chk_message.good.txt 2>&1
checksum=`$maria_path/maria_chk -dss $table`
mv $table.MAD $tmp/$table.MAD.good
rm $table.MAI
apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table.MAD.good
check_table_is_same
echo "testing idempotency"
apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table.MAD.good
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
for blobs in "" "-b" # we test table without blobs and then table with blobs
do
for test_undo in 1 2 3
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 -u"
# -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:"> $tmp/maria_chk_message.good.txt 2>&1
checksum=`$maria_path/maria_chk -dss $table`
mv $table.MAD $tmp/$table.MAD.good
rm $table.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.MAD.before_undo
if [ $test_undo -lt 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.MAD.after_undo
# 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"
cmp $table.MAD $tmp/$table.MAD.after_undo
check_table_is_same
echo "testing applying of CLRs to recreate table"
rm $table.MA?
apply_log "shouldnotchangelog"
# the cmp below fails with ma_test1+blobs! @todo RECOVERY BUG why?
# It is probably serious; REDOs shouldn't place rows in different
# positions from what the run-time code did. Indeed it may lead to
# more or less free space...
# Execution of UNDO re-inserted rows at different positions than
# originally. This generated REDOs which do not insert at the same
# positions as the execution of UNDOs, but at the same positions
# as before the row was originally deleted.
if [ "$blobs" == "" ]
then
cmp $table.MAD $tmp/$table.MAD.after_undo
fi
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
# 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"
# this message is to remember about the problem with -b (see @todo above)
echo "!!!!!!!! BUT REMEMBER to FIX this BLOB issue !!!!!!!"