File: test011.tcl

package info (click to toggle)
db 2%3A2.4.14-2.7.7.1.c
  • links: PTS
  • area: main
  • in suites: potato
  • size: 12,716 kB
  • ctags: 9,382
  • sloc: ansic: 35,556; tcl: 8,564; cpp: 4,890; sh: 2,075; makefile: 1,723; java: 1,632; sed: 419; awk: 153; asm: 41
file content (300 lines) | stat: -rw-r--r-- 8,630 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# See the file LICENSE for redistribution information.
#
# Copyright (c) 1996, 1997, 1998
#	Sleepycat Software.  All rights reserved.
#
#	@(#)test011.tcl	10.8 (Sleepycat) 12/5/98
#
# DB Test 11 {access method}
# Use the first 10,000 entries from the dictionary.
# Insert each with self as key and data; add duplicate
# records for each.
# Then do some key_first/key_last add_before, add_after operations.
# This does not work for recno
# To test if dups work when they fall off the main page, run this with
# a very tiny page size.
proc test011 { method {nentries 10000} {ndups 5} {tnum 11} args } {
global dlist
	set dlist ""
	set omethod $method
	set do_renumber [is_rrecno $method]
	set args [convert_args $method $args]
	set method [convert_method $method]
	if { [is_rbtree $omethod] == 1 } {
		puts "Test011 skipping for method $omethod"
		return
	}
	if { [string compare $method DB_RECNO] == 0 } {
		test011_recno $do_renumber $nentries $tnum $args
		return
	} else {
		puts -nonewline "Test0$tnum: $method $nentries small dup "
		puts "key/data pairs, cursor ops"
	}
	if {$ndups < 5} {
		set ndups 5
	}

	# Get global declarations since tcl doesn't support
	# any useful equivalent to #defines!
	source ./include.tcl

	# Create the database and open the dictionary
	set testfile test0$tnum.db
	set t1 $testdir/t1
	set t2 $testdir/t2
	set t3 $testdir/t3
	cleanup $testdir
	set args [add_to_args $DB_DUP $args]
	set db [eval [concat dbopen $testfile \
	    [expr $DB_CREATE | $DB_TRUNCATE] 0644 $method $args]]
	error_check_good dbopen [is_valid_db $db] TRUE
	set did [open $dict]

	set flags 0
	set txn 0
	set count 0

	# Here is the loop where we put and get each key/data pair
	# We will add dups with values 1, 3, ... $ndups.  Then we'll add
	# 0 and $ndups+1 using keyfirst/keylast.  We'll add 2 and 4 using
	# add before and add after.
	puts "\tTest0$tnum.a: put and get duplicate keys."
	set dbc [$db cursor $txn]
	set i ""
	for { set i 1 } { $i <= $ndups } { incr i 2 } {
		lappend dlist $i
	}
	set maxodd $i
	while { [gets $did str] != -1 && $count < $nentries } {
		for { set i 1 } { $i <= $ndups } { incr i 2 } {
			set datastr $i:$str
			set ret [$db put $txn $str $datastr $flags]
			error_check_good put $ret 0
		}

		# Now retrieve all the keys matching this key
		set x 1
		for {set ret [$dbc get $str $DB_SET]} \
		    {[string length $ret] != 0} \
		    {set ret [$dbc get 0 $DB_NEXT] } {
			set k [lindex $ret 0]
			if { [string compare $k $str] != 0 } {
				break
			}
			set datastr [lindex $ret 1]
			set d [data_of $datastr]

			if {[string length $d] == 0} {
				break
			}
			error_check_good Test0$tnum:put $d $str
			set id [ id_of $datastr ]
			error_check_good Test0$tnum:dup# $id $x
			incr x 2
		}
		error_check_good Test011:numdups $x $maxodd
		incr count
	}
	error_check_good curs_close [$dbc close] 0
	close $did

	# Now we will get each key from the DB and compare the results
	# to the original.
	puts "\tTest0$tnum.b: traverse entire file checking duplicates before close."
	dup_check $db $txn $t1 $dlist

	# Now compare the keys to see if they match the dictionary entries
	set q q
	exec $SED $nentries$q $dict > $t2
	exec $SORT $t1 > $t3

	error_check_good Test0$tnum:diff($t3,$t2) \
	    [catch { exec $DIFF $t3 $t2 } res] 0

	error_check_good db_close [$db close] 0
	set db [dbopen $testfile 0 0 $method]
	error_check_good dbopen [is_valid_db $db] TRUE

	puts "\tTest0$tnum.c: traverse entire file checking duplicates after close."
	dup_check $db $txn $t1 $dlist

	# Now compare the keys to see if they match the dictionary entries
	exec $SORT $t1 > $t3
	error_check_good Test0$tnum:diff($t3,$t2) \
	    [catch { exec $DIFF $t3 $t2 } res] 0

	puts "\tTest0$tnum.d: Testing key_first functionality"
	add_dup $db $txn $nentries $DB_KEYFIRST 0 0
	set dlist [linsert $dlist 0 0]
	dup_check $db $txn $t1 $dlist

	puts "\tTest0$tnum.e: Testing key_last functionality"
	add_dup $db $txn $nentries $DB_KEYLAST [expr $maxodd - 1] 0
	lappend dlist [expr $maxodd - 1]
	dup_check $db $txn $t1 $dlist

	puts "\tTest0$tnum.f: Testing add_before functionality"
	add_dup $db $txn $nentries $DB_BEFORE 2 3
	set dlist [linsert $dlist 2 2]
	dup_check $db $txn $t1 $dlist

	puts "\tTest0$tnum.g: Testing add_after functionality"
	add_dup $db $txn $nentries $DB_AFTER 4 4
	set dlist [linsert $dlist 4 4]
	dup_check $db $txn $t1 $dlist

	error_check_good db_close [$db close] 0
}

proc add_dup {db txn nentries flag dataval iter} {
source ./include.tcl

	set dbc [$db cursor $txn]
	set did [open $dict]
	set count 0
	while { [gets $did str] != -1 && $count < $nentries } {
		set datastr $dataval:$str
		set ret [$dbc get $str $DB_SET]
		error_check_bad "cget(SET)" [is_substr $ret Error] 1
		for { set i 1 } { $i < $iter } { incr i } {
			set ret [ $dbc get $str $DB_NEXT ]
			error_check_bad "cget(NEXT)" [is_substr $ret Error] 1
		}

		$dbc put $str $datastr $flag
		incr count
	}
	close $did
	$dbc close
}

proc test011_recno { {renum 0} {nentries 10000} {tnum 11} largs } {
global dlist
	puts "Test0$tnum: RECNO ($largs) $nentries test cursor insert functionality"

	# Get global declarations since tcl doesn't support
	# any useful equivalent to #defines!
	source ./include.tcl

	# Create the database and open the dictionary
	set testfile test0$tnum.db
	set t1 $testdir/t1
	set t2 $testdir/t2
	set t3 $testdir/t3
	cleanup $testdir
	set db [eval [concat dbopen $testfile [expr $DB_CREATE | $DB_TRUNCATE] \
	    0644 DB_RECNO $largs]]
	error_check_good dbopen [is_valid_db $db] TRUE
	set did [open $dict]

	set flags 0
	set txn 0
	set count 0

	# The basic structure of the test is that we pick a random key
	# in the database and then add items before, after, ?? it.  The
	# trickiness is that with RECNO, these are not duplicates, they
	# are creating new keys.  Therefore, every time we do this, the
	# keys assigned to other values change.  For this reason, we'll
	# keep the database in tcl as a list and insert properly into
	# it to verify that the right thing is happening.  If we do not
	# have renumber set, then the BEFORE and AFTER calls should fail.

	# Seed the database with an initial record
	gets $did str
	set ret [$db put $txn 1 $str 0]
	error_check_good put $ret 0
	set count 1

	set dlist "NULL $str"

	# Open a cursor
	set dbc [$db cursor $txn]
	puts "\tTest0$tnum.a: put and get entries"
	while { [gets $did str] != -1 && $count < $nentries } {
		# Pick a random key
		set key [random_int 1 $count]
		set ret [$dbc get $key $DB_SET]
		set k [lindex $ret 0]
		set d [lindex $ret 1]
		error_check_good cget:SET:key $k $key
		error_check_good cget:SET $d [lindex $dlist $key]

		# Current
		set ret [$dbc put $key $str $DB_CURRENT]
		error_check_good cput:$key $ret 0
		set dlist [lreplace $dlist $key $key $str]

		# Before
		if { [gets $did str] == -1 } {
			continue;
		}

		if { $renum == 1 } {
			set ret [$dbc put $key $str $DB_BEFORE]
			error_check_good cput:$key:BEFORE $ret 0
			set dlist [linsert $dlist $key $str]
			incr count

			# After
			if { [gets $did str] == -1 } {
				continue;
			}
			set ret [$dbc put $key $str $DB_AFTER]
			error_check_good cput:$key:AFTER $ret 0
			set dlist [linsert $dlist [expr $key + 1] $str]
			incr count
		}

		# Now verify that the keys are in the right place
		set i 0
		for {set ret [$dbc get $key $DB_SET]} \
		    {[string length $ret] != 0 && $i < 3} \
		    {set ret [$dbc get 0 $DB_NEXT] } {
			set check_key [expr $key + $i]

			set k [lindex $ret 0]
			error_check_good cget:$key:loop $k $check_key

			set d [lindex $ret 1]
			error_check_good cget:data $d [lindex $dlist $check_key]
			incr i
		}
	}
	close $did
	error_check_good cclose [$dbc close] 0

	# Create  check key file.
	set oid [open $t2 w]
	for {set i 1} {$i <= $count} {incr i} {
		puts $oid $i
	}
	close $oid

	puts "\tTest0$tnum.b: dump file"
	dump_file $db $txn $t1 test011_check
	error_check_good Test0$tnum:diff($t2,$t1) \
	    [catch { exec $DIFF $t2 $t1 } res] 0

	error_check_good db_close [$db close] 0

	puts "\tTest0$tnum.c: close, open, and dump file"
	open_and_dump_file $testfile NULL $txn $t1 test011_check \
	    dump_file_direction $DB_FIRST $DB_NEXT
	error_check_good Test0$tnum:diff($t2,$t1) \
	    [catch { exec $DIFF $t2 $t1 } res] 0

	puts "\tTest0$tnum.d: close, open, and dump file in reverse direction"
	open_and_dump_file $testfile NULL $txn $t1 test011_check \
	    dump_file_direction $DB_LAST $DB_PREV

	exec $SORT -n $t1 > $t3
	error_check_good Test0$tnum:diff($t2,$t3) \
	    [catch { exec $DIFF $t2 $t3 } res] 0
}

proc test011_check { key data } {
global dlist
	error_check_good "get key $key" $data [lindex $dlist $key]
}