Annotation of embedaddon/sqlite3/test/lock_common.tcl, revision 1.1.1.1

1.1       misho       1: # 2010 April 14
                      2: #
                      3: # The author disclaims copyright to this source code.  In place of
                      4: # a legal notice, here is a blessing:
                      5: #
                      6: #    May you do good and not evil.
                      7: #    May you find forgiveness for yourself and forgive others.
                      8: #    May you share freely, never taking more than you give.
                      9: #
                     10: #***********************************************************************
                     11: # This file contains code used by several different test scripts. The
                     12: # code in this file allows testfixture to control another process (or
                     13: # processes) to test locking.
                     14: #
                     15: 
                     16: proc do_multiclient_test {varname script} {
                     17: 
                     18:   foreach code [list {
                     19:     if {[info exists ::G(valgrind)]} { db close ; continue }
                     20:     set ::code2_chan [launch_testfixture]
                     21:     set ::code3_chan [launch_testfixture]
                     22:     proc code2 {tcl} { testfixture $::code2_chan $tcl }
                     23:     proc code3 {tcl} { testfixture $::code3_chan $tcl }
                     24:     set tn 1
                     25:   } {
                     26:     proc code2 {tcl} { uplevel #0 $tcl }
                     27:     proc code3 {tcl} { uplevel #0 $tcl }
                     28:     set tn 2
                     29:   }] {
                     30:     faultsim_delete_and_reopen
                     31: 
                     32:     proc code1 {tcl} { uplevel #0 $tcl }
                     33:   
                     34:     # Open connections [db2] and [db3]. Depending on which iteration this
                     35:     # is, the connections may be created in this interpreter, or in 
                     36:     # interpreters running in other OS processes. As such, the [db2] and [db3]
                     37:     # commands should only be accessed within [code2] and [code3] blocks,
                     38:     # respectively.
                     39:     #
                     40:     eval $code
                     41:     code2 { sqlite3 db2 test.db }
                     42:     code3 { sqlite3 db3 test.db }
                     43:     
                     44:     # Shorthand commands. Execute SQL using database connection [db2] or 
                     45:     # [db3]. Return the results.
                     46:     #
                     47:     proc sql1 {sql} { db eval $sql }
                     48:     proc sql2 {sql} { code2 [list db2 eval $sql] }
                     49:     proc sql3 {sql} { code3 [list db3 eval $sql] }
                     50:   
                     51:     proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg }
                     52:     proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg }
                     53:     proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg }
                     54: 
                     55:     uplevel set $varname $tn
                     56:     uplevel $script
                     57: 
                     58:     catch { code2 { db2 close } }
                     59:     catch { code3 { db3 close } }
                     60:     catch { close $::code2_chan }
                     61:     catch { close $::code3_chan }
                     62:     catch { db close }
                     63:   }
                     64: }
                     65: 
                     66: # Launch another testfixture process to be controlled by this one. A
                     67: # channel name is returned that may be passed as the first argument to proc
                     68: # 'testfixture' to execute a command. The child testfixture process is shut
                     69: # down by closing the channel.
                     70: proc launch_testfixture {{prg ""}} {
                     71:   write_main_loop
                     72:   if {$prg eq ""} { set prg [info nameofexec] }
                     73:   if {$prg eq ""} { set prg testfixture }
                     74:   if {[file tail $prg]==$prg} { set prg [file join . $prg] }
                     75:   set chan [open "|$prg tf_main.tcl" r+]
                     76:   fconfigure $chan -buffering line
                     77:   set rc [catch { 
                     78:     testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
                     79:   }]
                     80:   if {$rc} {
                     81:     testfixture $chan "set ::sqlite_pending_byte $::sqlite_pending_byte"
                     82:   }
                     83:   return $chan
                     84: }
                     85: 
                     86: # Execute a command in a child testfixture process, connected by two-way
                     87: # channel $chan. Return the result of the command, or an error message.
                     88: #
                     89: proc testfixture {chan cmd} {
                     90:   puts $chan $cmd
                     91:   puts $chan OVER
                     92:   set r ""
                     93:   while { 1 } {
                     94:     set line [gets $chan]
                     95:     if { $line == "OVER" } { 
                     96:       set res [lindex $r 1]
                     97:       if { [lindex $r 0] } { error $res }
                     98:       return $res
                     99:     }
                    100:     if {[eof $chan]} {
                    101:       return "ERROR: Child process hung up"
                    102:     }
                    103:     append r $line
                    104:   }
                    105: }
                    106: 
                    107: proc testfixture_nb_cb {varname chan} {
                    108:   if {[eof $chan]} {
                    109:     append ::tfnb($chan) "ERROR: Child process hung up"
                    110:     set line "OVER"
                    111:   } else {
                    112:     set line [gets $chan]
                    113:   }
                    114: 
                    115:   if { $line == "OVER" } {
                    116:     set $varname [lindex $::tfnb($chan) 1]
                    117:     unset ::tfnb($chan)
                    118:     close $chan
                    119:   } else {
                    120:     append ::tfnb($chan) $line
                    121:   }
                    122: }
                    123: 
                    124: proc testfixture_nb {varname cmd} {
                    125:   set chan [launch_testfixture]
                    126:   set ::tfnb($chan) ""
                    127:   fconfigure $chan -blocking 0 -buffering none
                    128:   puts $chan $cmd
                    129:   puts $chan OVER
                    130:   fileevent $chan readable [list testfixture_nb_cb $varname $chan]
                    131:   return ""
                    132: }
                    133: 
                    134: # Write the main loop for the child testfixture processes into file
                    135: # tf_main.tcl. The parent (this script) interacts with the child processes
                    136: # via a two way pipe. The parent writes a script to the stdin of the child
                    137: # process, followed by the word "OVER" on a line of its own. The child
                    138: # process evaluates the script and writes the results to stdout, followed
                    139: # by an "OVER" of its own.
                    140: #
                    141: set main_loop_written 0
                    142: proc write_main_loop {} {
                    143:   if {$::main_loop_written} return
                    144:   set wrapper ""
                    145:   if {[sqlite3 -has-codec] && [info exists ::do_not_use_codec]==0} {
                    146:     set wrapper "
                    147:       rename sqlite3 sqlite_orig
                    148:       proc sqlite3 {args} {[info body sqlite3]}
                    149:     "
                    150:   }
                    151: 
                    152:   set fd [open tf_main.tcl w]
                    153:   puts $fd [string map [list %WRAPPER% $wrapper] {
                    154:     %WRAPPER%
                    155:     set script ""
                    156:     while {![eof stdin]} {
                    157:       flush stdout
                    158:       set line [gets stdin]
                    159:       if { $line == "OVER" } {
                    160:         set rc [catch {eval $script} result]
                    161:         puts [list $rc $result]
                    162:         puts OVER
                    163:         flush stdout
                    164:         set script ""
                    165:       } else {
                    166:         append script $line
                    167:         append script "\n"
                    168:       }
                    169:     }
                    170:   }]
                    171:   close $fd
                    172:   set main_loop_written 1
                    173: }
                    174: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>