mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-09-29 11:36:56 +00:00
394 lines
12 KiB
Tcl
394 lines
12 KiB
Tcl
|
# See the file LICENSE for redistribution information.
|
||
|
#
|
||
|
# Copyright (c) 2004, 2011 Oracle and/or its affiliates. All rights reserved.
|
||
|
#
|
||
|
# $Id$
|
||
|
#
|
||
|
# TEST env012
|
||
|
# TEST Test DB_REGISTER.
|
||
|
# TEST
|
||
|
# TEST DB_REGISTER will fail on systems without fcntl. If it
|
||
|
# TEST fails, make sure we got the expected DB_OPNOTSUP return.
|
||
|
# TEST
|
||
|
# TEST Then, the real tests:
|
||
|
# TEST For each test, we start a process that opens an env with -register.
|
||
|
# TEST
|
||
|
# TEST 1. Verify that a 2nd process can enter the existing env with -register.
|
||
|
# TEST
|
||
|
# TEST 2. Kill the 1st process, and verify that the 2nd process can enter
|
||
|
# TEST with "-register -recover".
|
||
|
# TEST
|
||
|
# TEST 3. Kill the 1st process, and verify that the 2nd process cannot
|
||
|
# TEST enter with just "-register".
|
||
|
# TEST
|
||
|
# TEST 4. While the 1st process is still running, a 2nd process enters
|
||
|
# TEST with "-register". Kill the 1st process. Verify that a 3rd process
|
||
|
# TEST can enter with "-register -recover". Verify that the 3rd process,
|
||
|
# TEST entering, causes process 2 to fail with the message DB_RUNRECOVERY.
|
||
|
# TEST
|
||
|
# TEST 5. We had a bug where recovery was always run with -register
|
||
|
# TEST if there were empty slots in the process registry file. Verify
|
||
|
# TEST that recovery doesn't automatically run if there is an empty slot.
|
||
|
# TEST
|
||
|
# TEST 6. Verify process cannot connect when specifying -failchk and an
|
||
|
# TEST isalive function has not been declared.
|
||
|
# TEST
|
||
|
# TEST 7. Verify that a 2nd process can enter the existing env with -register
|
||
|
# TEST and -failchk and having specified an isalive function
|
||
|
# TEST
|
||
|
# TEST 8. Kill the 1st process, and verify that the 2nd process can enter
|
||
|
# TEST with "-register -failchk -recover"
|
||
|
# TEST
|
||
|
# TEST 9. 2nd process enters with "-register -failchk". Kill the 1st process.
|
||
|
# TEST 2nd process may get blocked on a mutex held by process one. Verify
|
||
|
# TEST 3rd process can enter with "-register -recover -failchk". 3rd process
|
||
|
# TEST should run failchk, clear out open txn/log from process 1. It will
|
||
|
# TEST enter env without need for any additional recovery. We look for
|
||
|
# TEST "Freeing log information .." sentence in the log for 3rd process as
|
||
|
# TEST an indication that failchk ran. If DB_RUNRECOVERY were returned
|
||
|
# TEST instead it would mean failchk could not recover.
|
||
|
|
||
|
proc env012 { } {
|
||
|
source ./include.tcl
|
||
|
set tnum "012"
|
||
|
|
||
|
puts "Env$tnum: Test of DB_REGISTER."
|
||
|
|
||
|
puts "\tEnv$tnum.a: Platforms without fcntl fail with DB_OPNOTSUP."
|
||
|
env_cleanup $testdir
|
||
|
if {[catch {eval {berkdb_env} \
|
||
|
-create -home $testdir -txn -register -recover} env]} {
|
||
|
error_check_good fail_OPNOTSUP [is_substr $env DB_OPNOTSUP] 1
|
||
|
puts "Skipping env$tnum; DB_REGISTER is not supported."
|
||
|
}
|
||
|
error_check_good env_close [$env close] 0
|
||
|
|
||
|
puts "\tEnv$tnum.b: Second process can join with -register."
|
||
|
env_cleanup $testdir
|
||
|
set testfile TESTFILE
|
||
|
set key KEY
|
||
|
set data DATA1
|
||
|
|
||
|
puts "\t\tEnv$tnum.b1: Start process 1."
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER 0 10 &]
|
||
|
|
||
|
# Wait a while so process 1 has a chance to get going.
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.b2: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data 0 0 0 &]
|
||
|
|
||
|
watch_procs $p1 1 120
|
||
|
watch_procs $p2 1 120
|
||
|
|
||
|
# Check log files for failures.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
|
||
|
puts "\tEnv$tnum.c: Second process can join with -register\
|
||
|
-recover after first process is killed."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
puts "\t\tEnv$tnum.c1: Start process 1."
|
||
|
set pids {}
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER 0 10 &]
|
||
|
lappend pids $p1
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.c2: Kill process 1."
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
puts "\t\tEnv$tnum.c3: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data RECOVER 0 0 &]
|
||
|
|
||
|
watch_procs $p2 1 120
|
||
|
|
||
|
# Check log files for failures.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
|
||
|
if { $is_windows_test == 1 } {
|
||
|
puts "Skipping sections .d and .e on Windows platform."
|
||
|
} else {
|
||
|
puts "\tEnv$tnum.d: Second process cannot join without -recover\
|
||
|
after first process is killed."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
puts "\t\tEnv$tnum.d1: Start process 1."
|
||
|
set pids {}
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER 0 10 &]
|
||
|
lappend pids $p1
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.d2: Kill process 1."
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
puts "\t\tEnv$tnum.d3: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data 0 0 0 &]
|
||
|
tclsleep 2
|
||
|
watch_procs $p2 1 120
|
||
|
|
||
|
# Check log files. Log p1 should be clean, but we
|
||
|
# expect DB_RUNRECOVERY in log p2.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheckfails $testdir/env$tnum.log.p2 DB_RUNRECOVERY
|
||
|
|
||
|
puts "\tEnv$tnum.e: Running registered process detects failure."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
puts "\t\tEnv$tnum.e1: Start process 1."
|
||
|
set pids {}
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER 0 10 &]
|
||
|
lappend pids $p1
|
||
|
tclsleep 2
|
||
|
|
||
|
# Identify child process to kill later.
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
|
||
|
puts "\t\tEnv$tnum.e2: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile LOOP $key $data 0 0 10 &]
|
||
|
|
||
|
puts "\t\tEnv$tnum.e3: Kill process 1."
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
puts "\t\tEnv$tnum.e4: Start process 3."
|
||
|
set p3 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p3 \
|
||
|
$testdir $testfile GET $key $data RECOVER 0 0 &]
|
||
|
tclsleep 2
|
||
|
|
||
|
watch_procs $p2 1 120
|
||
|
watch_procs $p3 1 120
|
||
|
|
||
|
# Check log files. Logs p1 and p3 should be clean, but we
|
||
|
# expect DB_RUNRECOVERY in log p2.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheckfails $testdir/env$tnum.log.p2 DB_RUNRECOVERY
|
||
|
logcheck $testdir/env$tnum.log.p3
|
||
|
}
|
||
|
|
||
|
puts "\tEnv$tnum.f: Empty slot shouldn't cause automatic recovery."
|
||
|
|
||
|
# Create 2 empty slots in the registry by letting two processes
|
||
|
# run to completion.
|
||
|
puts "\t\tEnv$tnum.f1: Start process 1."
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER 0 1 &]
|
||
|
|
||
|
puts "\t\tEnv$tnum.f2: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data 0 0 1 &]
|
||
|
|
||
|
watch_procs $p1 1 60
|
||
|
watch_procs $p2 1 60
|
||
|
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
|
||
|
# Start two more process. Neither should signal a need for recovery.
|
||
|
puts "\t\tEnv$tnum.f3: Start process 3."
|
||
|
set p3 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p3 \
|
||
|
$testdir $testfile GET $key $data RECOVER 0 10 &]
|
||
|
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.f4: Start process 4."
|
||
|
set p4 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p4 \
|
||
|
$testdir $testfile PUT $key $data 0 0 10 &]
|
||
|
|
||
|
watch_procs $p3 1 120
|
||
|
watch_procs $p4 1 120
|
||
|
|
||
|
# Check log files: neither process should have returned DB_RUNRECOVERY.
|
||
|
logcheck $testdir/env$tnum.log.p3
|
||
|
logcheck $testdir/env$tnum.log.p4
|
||
|
|
||
|
puts "\tEnv$tnum.g: One process with -register & -failchk & no isalive"
|
||
|
|
||
|
# use -failchk only, test will fail as isalive function is needed
|
||
|
puts "\t\tEnv$tnum.g1: Start process 1."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER FAILCHK0 10 &]
|
||
|
|
||
|
watch_procs $p1 1 60
|
||
|
|
||
|
# Check log files for failures. Expect to see a failure.
|
||
|
logcheckfails $testdir/env$tnum.log.p1 DB_FAILCHK
|
||
|
|
||
|
puts "\tEnv$tnum.h: Second process joins with -register and -failchk."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
# use -failchk and -isalive flags
|
||
|
puts "\t\tEnv$tnum.h1: Start process 1."
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER FAILCHK1 10 &]
|
||
|
|
||
|
# Wait a while so process 1 has a chance to get going.
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.h2: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data 0 FAILCHK1 0 &]
|
||
|
|
||
|
watch_procs $p1 1 120
|
||
|
watch_procs $p2 1 120
|
||
|
|
||
|
# Check log files for failures.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
|
||
|
puts "\tEnv$tnum.i: Second process can join with -register\
|
||
|
-recover -failchk after first process is killed."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
puts "\t\tEnv$tnum.i1: Start process 1."
|
||
|
set pids {}
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile PUT $key $data RECOVER FAILCHK1 10 &]
|
||
|
lappend pids $p1
|
||
|
tclsleep 2
|
||
|
|
||
|
puts "\t\tEnv$tnum.i2: Kill process 1."
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
puts "\t\tEnv$tnum.i3: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile GET $key $data RECOVER FAILCHK1 0 &]
|
||
|
|
||
|
watch_procs $p2 1 120
|
||
|
|
||
|
# Check log files for failures.
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
|
||
|
if { $is_windows_test == 1 } {
|
||
|
puts "Skipping sections .j on Windows platform."
|
||
|
} else {
|
||
|
puts "\tEnv$tnum.j: Running registered process detects failure and recovers."
|
||
|
env_cleanup $testdir
|
||
|
|
||
|
puts "\t\tEnv$tnum.j1: Start process 1."
|
||
|
set pids {}
|
||
|
set p1 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p1 \
|
||
|
$testdir $testfile LOOP $key $data RECOVER FAILCHK1 5 &]
|
||
|
lappend pids $p1
|
||
|
tclsleep 2
|
||
|
|
||
|
# Identify child process to kill later.
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
|
||
|
puts "\t\tEnv$tnum.j2: Start process 2."
|
||
|
set p2 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p2 \
|
||
|
$testdir $testfile LOOP $key $data 0 0 10 &]
|
||
|
|
||
|
puts "\t\tEnv$tnum.j3: Kill process 1."
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
#identify child process 2, do after process 1 has died
|
||
|
lappend pids $p2
|
||
|
|
||
|
# Identify child process to kill later.
|
||
|
set pids [findprocessids $testdir $pids]
|
||
|
|
||
|
puts "\t\tEnv$tnum.j4: Start process 3."
|
||
|
set p3 [exec $tclsh_path $test_path/wrap.tcl envscript.tcl \
|
||
|
$testdir/env$tnum.log.p3 \
|
||
|
$testdir $testfile GET $key $data RECOVER FAILCHK1 0 &]
|
||
|
#sleep for approx 20 seconds -- process 2 should still be going
|
||
|
tclsleep 20
|
||
|
|
||
|
puts "\t\tEnv$tnum.j5: Kill process 2."
|
||
|
foreach pid $pids {
|
||
|
tclkill $pid
|
||
|
}
|
||
|
|
||
|
watch_procs $p3 1 30
|
||
|
|
||
|
# Check log files. Logs p1 and p2 should be clean, but we
|
||
|
# expect failchk messages in p3 from cleanup
|
||
|
logcheckfails $testdir/env$tnum.log.p3 Freeing
|
||
|
logcheck $testdir/env$tnum.log.p2
|
||
|
logcheck $testdir/env$tnum.log.p1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Check log file and report failures with FAIL. Use this when
|
||
|
# we don't expect failures.
|
||
|
proc logcheck { logname } {
|
||
|
set errstrings [eval findfail $logname]
|
||
|
foreach errstring $errstrings {
|
||
|
puts "FAIL: error in $logname : $errstring"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# When we expect a failure, verify we find the one we expect.
|
||
|
proc logcheckfails { logname message } {
|
||
|
set f [open $logname r]
|
||
|
while { [gets $f line] >= 0 } {
|
||
|
if { [is_substr $line $message] == 1 } {
|
||
|
close $f
|
||
|
return 0
|
||
|
}
|
||
|
}
|
||
|
close $f
|
||
|
puts "FAIL: Did not find expected error $message."
|
||
|
}
|
||
|
|
||
|
# The script wrap.tcl creates a parent and a child process. We
|
||
|
# can't see the child pids, so find them by their sentinel files.
|
||
|
# This creates a list where the parent pid is always listed
|
||
|
# before the child pid.
|
||
|
proc findprocessids { testdir plist } {
|
||
|
set beginfiles [glob $testdir/begin.*]
|
||
|
foreach b $beginfiles {
|
||
|
regsub $testdir/begin. $b {} pid
|
||
|
if { [lsearch -exact $plist $pid] == -1 } {
|
||
|
lappend plist $pid
|
||
|
}
|
||
|
}
|
||
|
return $plist
|
||
|
}
|
||
|
|