recd012.tcl
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. # See the file LICENSE for redistribution information.
  2. #
  3. # Copyright (c) 2000
  4. # Sleepycat Software.  All rights reserved.
  5. #
  6. # $Id: recd012.tcl,v 11.14 2000/12/11 17:24:55 sue Exp $
  7. #
  8. # Recovery Test 12.
  9. # Test recovery handling of file opens and closes.
  10. proc recd012 { method {start 0} 
  11.     {niter 49} {noutiter 25} {niniter 100} {ndbs 5} args } {
  12. source ./include.tcl
  13. set tnum 12
  14. set pagesize 512
  15. if { $is_qnx_test } {
  16. set niter 40
  17. }
  18. puts "Recd0$tnum $method ($args): Test recovery file management."
  19. set pgindex [lsearch -exact $args "-pagesize"]
  20. if { $pgindex != -1 } {
  21. puts "Recd012: skipping for specific pagesizes"
  22. return
  23. }
  24. for { set i $start } { $i <= $niter } { incr i } {
  25. env_cleanup $testdir
  26. # For repeatability, we pass in the iteration number
  27. # as a parameter and use that in recd012_body to seed
  28. # the random number generator to randomize our operations.
  29. # This lets us re-run a potentially failing iteration
  30. # without having to start from the beginning and work
  31. # our way to it.
  32. # The number of databases ranges from 4 to 8 and is
  33. # a function of $niter
  34. # set ndbs [expr ($i % 5) + 4]
  35. recd012_body 
  36.     $method $ndbs $i $noutiter $niniter $pagesize $tnum $args 
  37. }
  38. }
  39. proc recd012_body { method {ndbs 5} iter noutiter niniter psz tnum {largs ""} } {
  40. global alphabet rand_init fixed_len recd012_ofkey recd012_ofckptkey
  41. source ./include.tcl
  42. set largs [convert_args $method $largs]
  43. set omethod [convert_method $method]
  44. puts "tRecd0$tnum $method ($largs): Iteration $iter"
  45. puts "ttRecd0$tnum.a: Create environment and $ndbs databases."
  46. set flags "-create -txn -home $testdir"
  47. set env_cmd "berkdb env $flags"
  48. error_check_good env_remove [berkdb envremove -home $testdir] 0
  49. set dbenv [eval $env_cmd]
  50. error_check_good dbenv [is_valid_env $dbenv] TRUE
  51. # Initialize random number generator based on $iter.
  52. berkdb srand [expr $iter + $rand_init]
  53. # Initialize database that keeps track of number of open files (so
  54. # we don't run out of descriptors).
  55. set ofname of.db
  56. set ofdb [berkdb_open -env $dbenv
  57.     -create -dup -mode 0644 -btree -pagesize 512 $ofname]
  58. error_check_good of_open [is_valid_db $ofdb] TRUE
  59. set oftxn [$dbenv txn]
  60. error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
  61. error_check_good of_put [$ofdb put -txn $oftxn $recd012_ofkey 1] 0
  62. error_check_good of_put2 [$ofdb put -txn $oftxn $recd012_ofckptkey 0] 0
  63. error_check_good of_put3 [$ofdb put -txn $oftxn $recd012_ofckptkey 0] 0
  64. error_check_good of_txn_commit [$oftxn commit] 0
  65. error_check_good of_close [$ofdb close] 0
  66. # Create ndbs databases to work in, and a file listing db names to
  67. # pick from.
  68. set f [open TESTDIR/dblist w]
  69. set oflags 
  70.     "-env $dbenv -create -mode 0644 -pagesize $psz $largs $omethod"
  71. for { set i 0 } { $i < $ndbs } { incr i } {
  72. # 50-50 chance of being a subdb, unless we're a queue.
  73. if { [berkdb random_int 0 1] || [is_queue $method] } {
  74. # not a subdb
  75. set dbname recd0$tnum-$i.db
  76. } else {
  77. # subdb
  78. set dbname "recd0$tnum-subdb.db s$i"
  79. }
  80. puts $f $dbname
  81. set db [eval berkdb_open $oflags $dbname]
  82. error_check_good db($i) [is_valid_db $db] TRUE
  83. error_check_good db($i)_close [$db close] 0
  84. }
  85. close $f
  86. error_check_good env_close [$dbenv close] 0
  87. # Now we get to the meat of things.  Our goal is to do some number
  88. # of opens, closes, updates, and shutdowns (simulated here by a
  89. # close of all open handles and a close/reopen of the environment,
  90. # with or without an envremove), matching the regular expression
  91. #
  92. # ((O[OUC]+S)+R+V)
  93. # We'll repeat the inner + a random number up to $niniter times,
  94. # and the outer + a random number up to $noutiter times.
  95. #
  96. # In order to simulate shutdowns, we'll perform the opens, closes,
  97. # and updates in a separate process, which we'll exit without closing
  98. # all handles properly.  The environment will be left lying around
  99. # before we run recovery 50% of the time.
  100. set out [berkdb random_int 1 $noutiter]
  101. puts "ttRecd0$tnum.b: Performing $out recoveries of up to $niniter
  102.     ops."
  103. for { set i 0 } { $i < $out } { incr i } {
  104. set child [open "|$tclsh_path" w]
  105. # For performance, don't source everything, 
  106. # just what we'll need.
  107. puts $child "load $tcllib"
  108. puts $child "set fixed_len $fixed_len"
  109. puts $child "source ../test/testutils.tcl"
  110. puts $child "source ../test/recd0$tnum.tcl"
  111. set rnd [expr $iter * 10000 + $i * 100 + $rand_init]
  112. # Go.
  113. # puts "recd012_dochild {$env_cmd} $rnd $i $niniter
  114. #    $ndbs $tnum $method $ofname $largs"
  115. puts $child "recd012_dochild {$env_cmd} $rnd $i $niniter
  116.     $ndbs $tnum $method $ofname $largs"
  117. close $child
  118. # Run recovery 0-3 times.
  119. set nrecs [berkdb random_int 0 3]
  120. for { set j 0 } { $j < $nrecs } { incr j } {
  121. set ret [catch {exec $util_path/db_recover 
  122.     -h $testdir} res]
  123. if { $ret != 0 } { 
  124. puts "FAIL: db_recover returned with nonzero
  125.     exit status, output as follows:"
  126. file mkdir /tmp/12out
  127. set fd [open /tmp/12out/[pid] w]
  128. puts $fd $res 
  129. close $fd
  130. }
  131. error_check_good recover($j) $ret 0
  132. }
  133. }
  134. # Run recovery one final time;  it doesn't make sense to 
  135. # check integrity if we do not.
  136. set ret [catch {exec $util_path/db_recover -h $testdir} res]
  137. if { $ret != 0 } { 
  138. puts "FAIL: db_recover returned with nonzero
  139.     exit status, output as follows:"
  140. puts $res 
  141. }
  142. # Make sure each datum is the correct filename.
  143. puts "ttRecd0$tnum.c: Checking data integrity."
  144. set dbenv [berkdb env -create -private -home $testdir]
  145. error_check_good env_open_integrity [is_valid_env $dbenv] TRUE
  146. set f [open TESTDIR/dblist r]
  147. set i 0
  148. while { [gets $f dbinfo] > 0 } {
  149. set db [eval berkdb_open -env $dbenv $dbinfo]
  150. error_check_good dbopen($dbinfo) [is_valid_db $db] TRUE
  151. set dbc [$db cursor]
  152. error_check_good cursor [is_valid_cursor $dbc $db] TRUE
  153. for { set dbt [$dbc get -first] } { [llength $dbt] > 0 } 
  154.     { set dbt [$dbc get -next] } {
  155. error_check_good integrity [lindex [lindex $dbt 0] 1] 
  156.     [pad_data $method $dbinfo]
  157. }
  158. error_check_good dbc_close [$dbc close] 0
  159. error_check_good db_close [$db close] 0
  160. }
  161. close $f
  162. error_check_good env_close_integrity [$dbenv close] 0
  163. # Verify
  164. error_check_good verify [verify_dir $testdir "ttRecd0$tnum.d: "] 0
  165. }
  166. proc recd012_dochild { env_cmd rnd outiter niniter ndbs tnum method
  167.     ofname args } {
  168. global recd012_ofkey
  169. if { [is_record_based $method] } {
  170. set keybase ""
  171. } else {
  172. set keybase .[repeat abcdefghijklmnopqrstuvwxyz 4]
  173. }
  174. # Initialize our random number generator, repeatably based on an arg.
  175. berkdb srand $rnd
  176. # Open our env.
  177. set dbenv [eval $env_cmd]
  178. error_check_good env_open [is_valid_env $dbenv] TRUE
  179. # Find out how many databases appear to be open in the log--we
  180. # don't want recovery to run out of filehandles.
  181. set ofdb [berkdb_open -env $dbenv $ofname]
  182. set oftxn [$dbenv txn]
  183. error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
  184. set dbt [$ofdb get -txn $oftxn $recd012_ofkey]
  185. error_check_good of_get [lindex [lindex $dbt 0] 0] $recd012_ofkey
  186. set nopenfiles [lindex [lindex $dbt 0] 1]
  187. error_check_good of_commit [$oftxn commit] 0
  188. # Read our dbnames
  189. set f [open TESTDIR/dblist r]
  190. set i 0
  191. while { [gets $f dbname($i)] > 0 } {
  192. incr i
  193. }
  194. close $f
  195. # We now have $ndbs extant databases.  
  196. # Open one of them, just to get us started.
  197. set opendbs {}
  198. set oflags "-env $dbenv $args"
  199. # Start a transaction, just to get us started.
  200. set curtxn [$dbenv txn]
  201. error_check_good txn [is_valid_txn $curtxn $dbenv] TRUE
  202. # Inner loop.  Do $in iterations of a random open, close, or
  203. # update, where $in is between 1 and $niniter.
  204. set in [berkdb random_int 1 $niniter]
  205. for { set j 0 } { $j < $in } { incr j } {
  206. set op [berkdb random_int 0 2]
  207. switch $op {
  208. 0 {
  209. # Open.
  210. recd012_open
  211. }
  212. 1 {
  213. # Update.  Put random-number$keybase as key,
  214. # filename as data, into random database.
  215. set num_open [llength $opendbs]
  216. if { $num_open == 0 } {
  217. # If none are open, do an open first.
  218. recd012_open
  219. }
  220. set n [berkdb random_int 0 [expr $num_open - 1]]
  221. set pair [lindex $opendbs $n]
  222. set udb [lindex $pair 0]
  223. set uname [lindex $pair 1]
  224. set key [berkdb random_int 1000 1999]$keybase
  225. set data [chop_data $method $uname]
  226. error_check_good put($uname,$udb,$key,$data) 
  227.     [$udb put -txn $curtxn $key $data] 0
  228. # One time in four, commit the transaction.
  229. if { [berkdb random_int 0 3] == 0 && 0 } {
  230. error_check_good txn_recommit 
  231.     [$curtxn commit] 0
  232. set curtxn [$dbenv txn]
  233. error_check_good txn_reopen 
  234.          [is_valid_txn $curtxn $dbenv] TRUE
  235. }
  236. }
  237. 2 {
  238. # Close.
  239. if { [llength $opendbs] == 0 } {
  240. # If none are open, open instead of closing.
  241. recd012_open
  242. continue
  243. }
  244. # Commit curtxn first, lest we self-deadlock.
  245. error_check_good txn_recommit 
  246.     [$curtxn commit] 0
  247. # Do it.
  248. set which [berkdb random_int 0 
  249.     [expr [llength $opendbs] - 1]]
  250. set db [lindex [lindex $opendbs $which] 0]
  251. error_check_good db_choice [is_valid_db $db] TRUE
  252. global errorCode errorInfo
  253. error_check_good db_close 
  254.     [[lindex [lindex $opendbs $which] 0] close] 0
  255. set opendbs [lreplace $opendbs $which $which]
  256. incr nopenfiles -1
  257. # Reopen txn.
  258. set curtxn [$dbenv txn]
  259. error_check_good txn_reopen 
  260.     [is_valid_txn $curtxn $dbenv] TRUE
  261. }
  262. }
  263. # One time in two hundred, checkpoint.
  264. if { [berkdb random_int 0 199] == 0 } {
  265. puts "tttRecd0$tnum:
  266.     Random checkpoint after operation $outiter.$j."
  267. error_check_good txn_ckpt 
  268.     [$dbenv txn_checkpoint] 0
  269. set nopenfiles 
  270.     [recd012_nopenfiles_ckpt $dbenv $ofdb $nopenfiles]
  271. }
  272. }
  273. # We have to commit curtxn.  It'd be kind of nice not to, but
  274. # if we start in again without running recovery, we may block
  275. # ourselves.
  276. error_check_good curtxn_commit [$curtxn commit] 0
  277. # Put back the new number of open files.
  278. set oftxn [$dbenv txn]
  279. error_check_good of_txn [is_valid_txn $oftxn $dbenv] TRUE
  280. error_check_good of_del [$ofdb del -txn $oftxn $recd012_ofkey] 0
  281. error_check_good of_put 
  282.     [$ofdb put -txn $oftxn $recd012_ofkey $nopenfiles] 0
  283. error_check_good of_commit [$oftxn commit] 0
  284. error_check_good ofdb_close [$ofdb close] 0
  285. }
  286. proc recd012_open { } {
  287. # This is basically an inline and has to modify curtxn, 
  288. # so use upvars.
  289. upvar curtxn curtxn 
  290. upvar ndbs ndbs
  291. upvar dbname dbname
  292. upvar dbenv dbenv
  293. upvar oflags oflags
  294. upvar opendbs opendbs
  295. upvar nopenfiles nopenfiles
  296. # Return without an open if we've already opened too many files--
  297. # we don't want to make recovery run out of filehandles.
  298. if { $nopenfiles > 30 } {
  299. #puts "skipping--too many open files"
  300. return -code break
  301. }
  302. # Commit curtxn first, lest we self-deadlock.
  303. error_check_good txn_recommit 
  304.     [$curtxn commit] 0
  305. # Do it.
  306. set which [berkdb random_int 0 [expr $ndbs - 1]]
  307. set db [eval berkdb_open 
  308.     $oflags $dbname($which)]
  309. lappend opendbs [list $db $dbname($which)]
  310. # Reopen txn.
  311. set curtxn [$dbenv txn]
  312. error_check_good txn_reopen 
  313.     [is_valid_txn $curtxn $dbenv] TRUE
  314. incr nopenfiles
  315. }
  316. # Update the database containing the number of files that db_recover has
  317. # to contend with--we want to avoid letting it run out of file descriptors.
  318. # We do this by keeping track of the number of unclosed opens since the 
  319. # checkpoint before last.
  320. # $recd012_ofkey stores this current value;  the two dups available
  321. # at $recd012_ofckptkey store the number of opens since the last checkpoint
  322. # previous.
  323. # Thus, if the current value is 17 when we do a checkpoint, and the
  324. # stored values are 3 and 8, the new current value (which we return)
  325. # is 14, and the new stored values are 8 and 6.
  326. proc recd012_nopenfiles_ckpt { env db nopenfiles } {
  327. global recd012_ofckptkey
  328. set txn [$env txn]
  329. error_check_good nopenfiles_ckpt_txn [is_valid_txn $txn $env] TRUE
  330. set dbc [$db cursor -txn $txn]
  331. error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
  332. # Get the first ckpt value and delete it.
  333. set dbt [$dbc get -set $recd012_ofckptkey]
  334. error_check_good set [llength $dbt] 1
  335. set discard [lindex [lindex $dbt 0] 1]
  336. error_check_good del [$dbc del] 0
  337. set nopenfiles [expr $nopenfiles - $discard]
  338. # Get the next ckpt value
  339. set dbt [$dbc get -nextdup]
  340. error_check_good set2 [llength $dbt] 1
  341. # Calculate how many opens we've had since this checkpoint before last.
  342. set onlast [lindex [lindex $dbt 0] 1]
  343. set sincelast [expr $nopenfiles - $onlast]
  344. # Put this new number at the end of the dup set.
  345. error_check_good put [$dbc put -keylast $recd012_ofckptkey $sincelast] 0
  346. # We should never deadlock since we're the only one in this db.
  347. error_check_good dbc_close [$dbc close] 0
  348. error_check_good txn_commit [$txn commit] 0
  349. return $nopenfiles
  350. }
  351. # globals -- it's not worth passing these around, as they're constants
  352. set recd012_ofkey OPENFILES
  353. set recd012_ofckptkey CKPTS