+proc waitForBgsave r {
+ while 1 {
+ set i [$r info]
+ if {[string match {*bgsave_in_progress:1*} $i]} {
+ puts -nonewline "\nWaiting for background save to finish... "
+ flush stdout
+ after 1000
+ } else {
+ break
+ }
+ }
+}
+
+proc waitForBgrewriteaof r {
+ while 1 {
+ set i [$r info]
+ if {[string match {*bgrewriteaof_in_progress:1*} $i]} {
+ puts -nonewline "\nWaiting for background AOF rewrite to finish... "
+ flush stdout
+ after 1000
+ } else {
+ break
+ }
+ }
+}
+
+proc randomInt {max} {
+ expr {int(rand()*$max)}
+}
+
+proc randpath args {
+ set path [expr {int(rand()*[llength $args])}]
+ uplevel 1 [lindex $args $path]
+}
+
+proc randomValue {} {
+ randpath {
+ # Small enough to likely collide
+ randomInt 1000
+ } {
+ # 32 bit compressible signed/unsigned
+ randpath {randomInt 2000000000} {randomInt 4000000000}
+ } {
+ # 64 bit
+ randpath {randomInt 1000000000000}
+ } {
+ # Random string
+ randpath {randstring 0 256 alpha} \
+ {randstring 0 256 compr} \
+ {randstring 0 256 binary}
+ }
+}
+
+proc randomKey {} {
+ randpath {
+ # Small enough to likely collide
+ randomInt 1000
+ } {
+ # 32 bit compressible signed/unsigned
+ randpath {randomInt 2000000000} {randomInt 4000000000}
+ } {
+ # 64 bit
+ randpath {randomInt 1000000000000}
+ } {
+ # Random string
+ randpath {randstring 1 256 alpha} \
+ {randstring 1 256 compr}
+ }
+}
+
+proc createComplexDataset {r ops} {
+ for {set j 0} {$j < $ops} {incr j} {
+ set k [randomKey]
+ set v [randomValue]
+ set d [expr {rand()}]
+ set t [$r type $k]
+
+ if {$t eq {none}} {
+ randpath {
+ $r set $k $v
+ } {
+ $r lpush $k $v
+ } {
+ $r sadd $k $v
+ } {
+ $r zadd $k $d $v
+ }
+ set t [$r type $k]
+ }
+
+ switch $t {
+ {string} {
+ # Nothing to do
+ }
+ {list} {
+ randpath {$r lpush $k $v} \
+ {$r rpush $k $v} \
+ {$r lrem $k 0 $v} \
+ {$r rpop $k} \
+ {$r lpop $k}
+ }
+ {set} {
+ randpath {$r sadd $k $v} \
+ {$r srem $k $v}
+ }
+ {zset} {
+ randpath {$r zadd $k $d $v} \
+ {$r zrem $k $v}
+ }
+ }
+ }
+}
+
+proc datasetDigest r {
+ set keys [lsort [split [$r keys *] " "]]
+ set digest {}
+ foreach k $keys {
+ set t [$r type $k]
+ switch $t {
+ {string} {
+ set aux [::sha1::sha1 -hex [$r get $k]]
+ } {list} {
+ if {[$r llen $k] == 0} {
+ set aux {}
+ } else {
+ set aux [::sha1::sha1 -hex [$r lrange $k 0 -1]]
+ }
+ } {set} {
+ if {[$r scard $k] == 0} {
+ set aux {}
+ } else {
+ set aux [::sha1::sha1 -hex [lsort [$r smembers $k]]]
+ }
+ } {zset} {
+ if {[$r zcard $k] == 0} {
+ set aux {}
+ } else {
+ set aux [::sha1::sha1 -hex [$r zrange $k 0 -1]]
+ }
+ } default {
+ error "Type not supported"
+ }
+ }
+ if {$aux eq {}} continue
+ set digest [::sha1::sha1 -hex [join [list $aux $digest $k] "\n"]]
+ }
+ return $digest
+}
+