# See the file LICENSE for redistribution information. # # Copyright (c) 1996, 1997, 1998 # Sleepycat Software. All rights reserved. # # @(#)lock.tcl 10.6 (Sleepycat) 4/10/98 # # Test driver for lock tests. # General Multi Random # Options are: # -dir Y Y Y # -iterations Y N Y # -ldegree N N Y # -maxlocks Y Y Y # -objs N N Y # -procs N N Y # -reads N N Y # -seeds N N Y # -wait N N Y # -conflicts Y Y Y proc lock_usage {} { puts stderr "randomlock\n\t-dir \n\t-iterations " puts stderr "\t-conflicts " puts stderr "\t-ldegree \n\t-maxlocks " puts stderr "\t-objs \n\t-procs \n\t-reads <%reads>" puts stderr "\t-seeds \n\t-wait " return } proc locktest { args } { source ./include.tcl # Set defaults set conflicts { 0 0 0 0 0 1 0 1 1} set iterations 1000 set ldegree 5 set maxlocks 1000 set objs 75 set procs 5 set reads 65 set seeds {} set wait 5 for { set i 0 } { $i < [llength $args] } {incr i} { switch -regexp -- [lindex $args $i] { -c.* { incr i; set conflicts [linkdex $args $i] } -d.* { incr i; set testdir [lindex $args $i] } -i.* { incr i; set iterations [lindex $args $i] } -l.* { incr i; set ldegree [lindex $args $i] } -m.* { incr i; set maxlocks [lindex $args $i] } -o.* { incr i; set objs [lindex $args $i] } -p.* { incr i; set procs [lindex $args $i] } -r.* { incr i; set reads [lindex $args $i] } -s.* { incr i; set seeds [lindex $args $i] } -w.* { incr i; set wait [lindex $args $i] } default { lock_usage return } } } set nmodes [isqrt [llength $conflicts]] if { [file exists $testdir] != 1 } { exec $MKDIR $testdir } elseif { [file isdirectory $testdir ] != 1 } { error "$testdir is not a directory" } # Cleanup lock_cleanup $testdir # Open the lock lock001 $maxlocks $nmodes $conflicts # Now open the region we'll use for testing. set lp [lock_open "" $DB_CREATE 0644 \ -maxlocks $maxlocks -nmodes $nmodes -conflicts $conflicts] lock002 $lp $iterations $nmodes error_check_good lock_close [$lp close] 0 set ret [ lock_unlink $testdir 0 ] error_check_good lock_unlink $ret 0 lock003 $nmodes $conflicts lock004 $maxlocks $conflicts lock005 $testdir $iterations $maxlocks $procs $ldegree $objs \ $reads $wait $conflicts $seeds } # Make sure that we can create a region; destroy it, attach to it, # detach from it, etc. proc lock001 { maxl nmodes conf } { source ./include.tcl puts "Lock001: open/close test" # Lock without create should fail. set lp [lock_open "" 0 0644 -maxlocks $maxl -nmodes $nmodes \ -conflicts $conf] error_check_good lock_open $lp NULL # Now try to do open and create the region set lp [lock_open "" $DB_CREATE 0644 \ -maxlocks $maxl -nmodes $nmodes -conflicts $conf] error_check_bad lock_open $lp NULL # Now try closing the region set ret [ $lp close ] error_check_good lock_close $ret 0 # Try reopening the region set lp [lock_open "" 0 0644 -maxlocks $maxl -nmodes $nmodes \ -conflicts $conf] error_check_bad lock_open $lp NULL # Try unlinking without force (should fail) set ret [ lock_unlink $testdir 0 ] error_check_good lock_unlink $ret -1 # Close the region error_check_good lock_close [$lp close] 0 # Create/open a new region set lp [lock_open "" $DB_CREATE 0644 \ -maxlocks $maxl -nmodes $nmodes -conflicts $conf] error_check_bad lock_open $lp NULL # Close the region set ret [$lp close] error_check_good close $ret 0 # Finally, try unlinking the region without force and no live processes set ret [ lock_unlink $testdir 0 ] error_check_good lock_unlink $ret 0 # Now try creating the region in a different directory if { [file exists $testdir/MYLOCK] != 1 } { exec $MKDIR $testdir/MYLOCK } set lp [lock_open MYLOCK $DB_CREATE 0644 \ -maxlocks $maxl -nmodes $nmodes -conflicts $conf] error_check_bad lock_open $lp NULL error_check_good lock_close [$lp close] 0 error_check_good lock_unlink [lock_unlink $testdir/MYLOCK 0] 0 } # Make sure that the basic lock tests work. Do some simple gets and puts for # a single locker. proc lock002 {lp iter nmodes} { source ./include.tcl puts "Lock002: test basic lock operations" set locker 999 # Get and release each type of lock for {set i 0} { $i < $nmodes } {incr i} { set obj obj$i set lockp [$lp get $locker $obj $i 0] error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 set ret [ $lockp put ] error_check_good lock_put $ret 0 } # Get a bunch of locks for the same locker; these should work set obj OBJECT for {set i 0} { $i < $nmodes } {incr i} { set lockp [$lp get $locker $obj $i 0] lappend locklist $lockp error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 } release_list $locklist set locklist {} # Check that reference counted locks work for {set i 0} { $i < 10 } {incr i} { set lockp [$lp get $locker $obj $DB_LOCK_WRITE 1] error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 lappend locklist $lockp } release_list $locklist # Finally try some failing locks set locklist {} for {set i 0} { $i < $nmodes } {incr i} { set lockp [$lp get $locker $obj $i 0] lappend locklist $lockp error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 } # Change the locker set locker [incr locker] set blocklist {} # Skip NO_LOCK lock. for {set i 1} { $i < $nmodes } {incr i} { set lockp [$lp get $locker $obj $i $DB_LOCK_NOWAIT ] error_check_good lock_get [is_substr $lockp $lp] 0 error_check_good lock_get [is_blocked $lockp] 1 } # Now release original locks release_list $locklist # Now re-acquire blocking locks set locklist {} for {set i 1} { $i < $nmodes } {incr i} { set lockp [$lp get $locker $obj $i $DB_LOCK_NOWAIT ] error_check_good lock_get [is_substr $lockp $lp] 1 error_check_good lock_get [is_blocked $lockp] 0 lappend locklist $lockp } # Now release new locks release_list $locklist } proc lock003 { nmodes conflicts } { source ./include.tcl puts "Lock003: lock region grow test" set lp [lock_open "" $DB_CREATE 0644 \ -maxlocks 10 -nmodes $nmodes -conflicts $conflicts ] error_check_bad lock_open $lp NULL # First, cause to grow because of locks set locker 12345 set obj too_many_locks set locklist {} for {set i 0} { $i < 15 } { incr i } { set lockp [$lp get $locker $obj $DB_LOCK_READ 0] lappend locklist $lockp error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 } release_list $locklist # Next, cause to grow because of objects set locklist {} for {set i 0} { $i < 30 } { incr i } { set lockp [$lp get $locker $obj$i $DB_LOCK_WRITE 0] lappend locklist $lockp error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 } release_list $locklist # Finally, cause to grow because of string space; that means we need # to lock objects with very long names # # XXX # The loop end points, 50, and immediately below, 10, are for HPUX 9.05. # If we grow the region more than 4 times on those systems, they crash. set locker 12345 set longobj "" for {set i 0} { $i < 50} {incr i} { set longobj $longobj$obj } set locklist {} for {set i 0} { $i < 10 } { incr i } { set lockp [$lp get $locker $longobj$i $DB_LOCK_WRITE 0] lappend locklist $lockp error_check_good lock_get [is_blocked $lockp] 0 error_check_good lock_get [is_substr $lockp $lp] 1 } release_list $locklist error_check_good lock_close [$lp close] 0 } # Blocked locks appear as lockmgrN.lockM\nBLOCKED proc is_blocked { l } { if { [string compare $l BLOCKED ] == 0 } { return 1 } else { return 0 } }