blob: 8906b3f169f8043cf616ca52d245c13724a066dd (
plain)
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
# See the file LICENSE for redistribution information.
#
# Copyright (c) 1996-2009 Oracle. All rights reserved.
#
# $Id$
#
# Random db tester.
# Usage: dbscript file numops min_del max_add key_avg data_avgdups
# method: method (we pass this in so that fixed-length records work)
# file: db file on which to operate
# numops: number of operations to do
# ncurs: number of cursors
# min_del: minimum number of keys before you disable deletes.
# max_add: maximum number of keys before you disable adds.
# key_avg: average key size
# data_avg: average data size
# dups: 1 indicates dups allowed, 0 indicates no dups
# errpct: What percent of operations should generate errors
# seed: Random number generator seed (-1 means use pid)
source ./include.tcl
source $test_path/test.tcl
source $test_path/testutils.tcl
set usage "dbscript file numops ncurs min_del max_add key_avg data_avg dups errpcnt args"
# Verify usage
if { $argc < 10 } {
puts stderr "FAIL:[timestamp] Usage: $usage"
exit
}
# Initialize arguments
set method [lindex $argv 0]
set file [lindex $argv 1]
set numops [ lindex $argv 2 ]
set ncurs [ lindex $argv 3 ]
set min_del [ lindex $argv 4 ]
set max_add [ lindex $argv 5 ]
set key_avg [ lindex $argv 6 ]
set data_avg [ lindex $argv 7 ]
set dups [ lindex $argv 8 ]
set errpct [ lindex $argv 9 ]
set args [ lindex $argv 10 ]
berkdb srand $rand_init
puts "Beginning execution for [pid]"
puts "$file database"
puts "$numops Operations"
puts "$ncurs cursors"
puts "$min_del keys before deletes allowed"
puts "$max_add or fewer keys to add"
puts "$key_avg average key length"
puts "$data_avg average data length"
puts "$method $args"
if { $dups != 1 } {
puts "No dups"
} else {
puts "Dups allowed"
}
puts "$errpct % Errors"
flush stdout
set db [eval {berkdb_open} $args $file]
set cerr [catch {error_check_good dbopen [is_substr $db db] 1} cret]
if {$cerr != 0} {
puts $cret
return
}
# set method [$db get_type]
set record_based [is_record_based $method]
# Initialize globals including data
global nkeys
global l_keys
global a_keys
set nkeys [db_init $db 1]
puts "Initial number of keys: $nkeys"
set pflags ""
set gflags ""
set txn ""
# Open the cursors
set curslist {}
for { set i 0 } { $i < $ncurs } { incr i } {
set dbc [$db cursor]
set cerr [catch {error_check_good dbcopen [is_substr $dbc $db.c] 1} cret]
if {$cerr != 0} {
puts $cret
return
}
set cerr [catch {error_check_bad cursor_create $dbc NULL} cret]
if {$cerr != 0} {
puts $cret
return
}
lappend curslist $dbc
}
# On each iteration we're going to generate random keys and
# data. We'll select either a get/put/delete operation unless
# we have fewer than min_del keys in which case, delete is not
# an option or more than max_add in which case, add is not
# an option. The tcl global arrays a_keys and l_keys keep track
# of key-data pairs indexed by key and a list of keys, accessed
# by integer.
set adds 0
set puts 0
set gets 0
set dels 0
set bad_adds 0
set bad_puts 0
set bad_gets 0
set bad_dels 0
for { set iter 0 } { $iter < $numops } { incr iter } {
set op [pick_op $min_del $max_add $nkeys]
set err [is_err $errpct]
# The op0's indicate that there aren't any duplicates, so we
# exercise regular operations. If dups is 1, then we'll use
# cursor ops.
switch $op$dups$err {
add00 {
incr adds
set k [random_data $key_avg 1 a_keys $record_based]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$db put} $txn $pflags \
{-nooverwrite $k $data}]
set cerr [catch {error_check_good put $ret 0} cret]
if {$cerr != 0} {
puts $cret
return
}
newpair $k [pad_data $method $data]
}
add01 {
incr bad_adds
set k [random_key]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$db put} $txn $pflags \
{-nooverwrite $k $data}]
set cerr [catch {error_check_good put $ret 0} cret]
if {$cerr != 0} {
puts $cret
return
}
# Error case so no change to data state
}
add10 {
incr adds
set dbcinfo [random_cursor $curslist]
set dbc [lindex $dbcinfo 0]
if { [berkdb random_int 1 2] == 1 } {
# Add a new key
set k [random_data $key_avg 1 a_keys \
$record_based]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$dbc put} $txn \
{-keyfirst $k $data}]
newpair $k [pad_data $method $data]
} else {
# Add a new duplicate
set dbc [lindex $dbcinfo 0]
set k [lindex $dbcinfo 1]
set data [random_data $data_avg 0 0]
set op [pick_cursput]
set data [chop_data $method $data]
set ret [eval {$dbc put} $txn {$op $k $data}]
adddup $k [lindex $dbcinfo 2] $data
}
}
add11 {
# TODO
incr bad_adds
set ret 1
}
put00 {
incr puts
set k [random_key]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$db put} $txn {$k $data}]
changepair $k [pad_data $method $data]
}
put01 {
incr bad_puts
set k [random_key]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$db put} $txn $pflags \
{-nooverwrite $k $data}]
set cerr [catch {error_check_good put $ret 0} cret]
if {$cerr != 0} {
puts $cret
return
}
# Error case so no change to data state
}
put10 {
incr puts
set dbcinfo [random_cursor $curslist]
set dbc [lindex $dbcinfo 0]
set k [lindex $dbcinfo 1]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set ret [eval {$dbc put} $txn {-current $data}]
changedup $k [lindex $dbcinfo 2] $data
}
put11 {
incr bad_puts
set k [random_key]
set data [random_data $data_avg 0 0]
set data [chop_data $method $data]
set dbc [$db cursor]
set ret [eval {$dbc put} $txn {-current $data}]
set cerr [catch {error_check_good curs_close \
[$dbc close] 0} cret]
if {$cerr != 0} {
puts $cret
return
}
# Error case so no change to data state
}
get00 {
incr gets
set k [random_key]
set val [eval {$db get} $txn {$k}]
set data [pad_data $method [lindex [lindex $val 0] 1]]
if { $data == $a_keys($k) } {
set ret 0
} else {
set ret "FAIL: Error got |$data| expected |$a_keys($k)|"
}
# Get command requires no state change
}
get01 {
incr bad_gets
set k [random_data $key_avg 1 a_keys $record_based]
set ret [eval {$db get} $txn {$k}]
# Error case so no change to data state
}
get10 {
incr gets
set dbcinfo [random_cursor $curslist]
if { [llength $dbcinfo] == 3 } {
set ret 0
else
set ret 0
}
# Get command requires no state change
}
get11 {
incr bad_gets
set k [random_key]
set dbc [$db cursor]
if { [berkdb random_int 1 2] == 1 } {
set dir -next
} else {
set dir -prev
}
set ret [eval {$dbc get} $txn {-next $k}]
set cerr [catch {error_check_good curs_close \
[$dbc close] 0} cret]
if {$cerr != 0} {
puts $cret
return
}
# Error and get case so no change to data state
}
del00 {
incr dels
set k [random_key]
set ret [eval {$db del} $txn {$k}]
rempair $k
}
del01 {
incr bad_dels
set k [random_data $key_avg 1 a_keys $record_based]
set ret [eval {$db del} $txn {$k}]
# Error case so no change to data state
}
del10 {
incr dels
set dbcinfo [random_cursor $curslist]
set dbc [lindex $dbcinfo 0]
set ret [eval {$dbc del} $txn]
remdup [lindex dbcinfo 1] [lindex dbcinfo 2]
}
del11 {
incr bad_dels
set c [$db cursor]
set ret [eval {$c del} $txn]
set cerr [catch {error_check_good curs_close \
[$c close] 0} cret]
if {$cerr != 0} {
puts $cret
return
}
# Error case so no change to data state
}
}
if { $err == 1 } {
# Verify failure.
set cerr [catch {error_check_good $op$dups$err:$k \
[is_substr Error $ret] 1} cret]
if {$cerr != 0} {
puts $cret
return
}
} else {
# Verify success
set cerr [catch {error_check_good $op$dups$err:$k $ret 0} cret]
if {$cerr != 0} {
puts $cret
return
}
}
flush stdout
}
# Close cursors and file
foreach i $curslist {
set r [$i close]
set cerr [catch {error_check_good cursor_close:$i $r 0} cret]
if {$cerr != 0} {
puts $cret
return
}
}
set r [$db close]
set cerr [catch {error_check_good db_close:$db $r 0} cret]
if {$cerr != 0} {
puts $cret
return
}
puts "[timestamp] [pid] Complete"
puts "Successful ops: $adds adds $gets gets $puts puts $dels dels"
puts "Error ops: $bad_adds adds $bad_gets gets $bad_puts puts $bad_dels dels"
flush stdout
eval filecheck $file {$txn} $args
exit
|