# --------------------------------------------------------------- #
# -- Copyright (c) 1994, 1995 Computer Sciences Department,    -- #
# -- University of Wisconsin-Madison, subject to the terms     -- #
# -- and conditions given in the file COPYRIGHT.  All Rights   -- #
# -- Reserved.                                                 -- #
# --------------------------------------------------------------- #

#
#  This script tests 2x2 (SH and EX) lock compatibility on record. 
#
#  The operations to set a SH lock on a record are
#	sm read_rec
#	sm read_rec_body
#	sm print_rec
#
#  The operations to set an EX lock on a record are
#	sm append_rec
#	sm truncate_rec
#	sm update_rec
#	sm update_rec_hdr
#

proc req_lock { id type op } {
    sm begin_xct

    if { "$type" == "SH" } {
	case $op in {
	    read 	{ verbose [sm read_rec $id 0 0] }
	    read_body 	{ verbose [sm read_rec_body $id 0 0] }
	    print 	{ verbose [sm print_rec $id 0 0] }
	}
    }

    if { "$type" == "EX" } {
	case $op in {
	    update 	{ sm update_rec $id 1 bbb }
	    update_hdr 	{ sm update_rec_hdr $id 1 hhh }
	    append 	{ sm append_rec $id zzz }
	    truncate 	{ sm truncate_rec $id 3 }
	}
    }
}

proc rel_lock { args } {
    sm commit_xct
}

proc holder { id type op me } {
    sync

    echo "$me: $type ($op) requesting lock on $id"
    req_lock $id $type $op
    echo "$me: $type ($op) lock on $id granted"

    sync
    sync

    echo "$me: $type ($op) releasing lock on $id"
    rel_lock
}

proc requester { id type op me } {
    sync
    sync

    echo "$me: $type ($op) requesting lock on $id"
    req_lock $id $type $op
    echo "$me: $type ($op) lock on $id granted"

    sync

    echo "$me: $type ($op) releasing lock on $id"
    rel_lock
}

proc sh_sh { id } {
    global sh_ops

    foreach i $sh_ops {
    	foreach j $sh_ops {

	    set x [ fork_thread holder $id SH $i 1 ]
	    set y [ fork_thread requester $id SH $j 2 ]

	    sync_thread $x $y
	    sync_thread $x $y
	    sync_thread $x $y
	    join_thread $x $y
	    echo "----------------"
	}
    }
}

proc sh_ex { id } {
    global sh_ops
    global ex_ops

    foreach i $sh_ops {
	foreach j $ex_ops {

	    set x [ fork_thread holder $id SH $i 1 ]
	    set y [ fork_thread requester $id EX $j 2 ]

	    sync_thread $x $y
	    sync_thread $x $y
	    sync_thread $x $y
	    join_thread $x $y
	    echo "----------------"
	}
    }
}

proc ex_sh { id } {
    global sh_ops
    global ex_ops

    foreach i $ex_ops {
    	foreach j $sh_ops {

	    set x [ fork_thread holder $id EX $i 1 ]
	    set y [ fork_thread requester $id SH $j 2 ]

	    sync_thread $x $y
	    sync_thread $x $y
	    sync_thread $x $y
	    join_thread $x $y
	    echo "----------------"
    	}
    }
}

proc ex_ex {id} {
    global ex_ops

    foreach i $ex_ops {
    	foreach j $ex_ops {

	    set x [ fork_thread holder $id EX $i 1 ]
	    set y [ fork_thread requester $id EX $j 2 ]

	    sync_thread $x $y
	    sync_thread $x $y
	    sync_thread $x $y
	    join_thread $x $y
	    echo "----------------"
	}
    }
}

####  global variables ####
set sh_ops { read read_body print }
set ex_ops { append truncate update update_hdr }

##########  main  ########## 

source $script_dir/vol.init

sm begin_xct
set fid [sm create_file $volid]
set rid [sm create_rec $fid hdr12345 11 hellodata]
sm commit_xct

#echo volid = $volid
#echo fid = $fid
echo rid = $rid

echo "TEST:\tRecord Locking with SM Record Operations  *******\n"

echo "==================   SH  SH  ====================="
sh_sh $rid

echo "==================   SH  EX  ====================="
sh_ex $rid

echo "==================   EX  SH  ====================="
ex_sh $rid

echo "==================   EX  EX  ====================="
ex_ex $rid

unset sh_ops
unset ex_ops
unset rid
unset fid
