File: lazyfree.tcl

package info (click to toggle)
redis 5%3A8.0.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 22,304 kB
  • sloc: ansic: 216,903; tcl: 51,562; sh: 4,625; perl: 4,214; cpp: 3,568; python: 2,954; makefile: 2,055; ruby: 639; javascript: 30; csh: 7
file content (200 lines) | stat: -rw-r--r-- 5,994 bytes parent folder | download
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
start_server {tags {"lazyfree"}} {
    test "UNLINK can reclaim memory in background" {
        set orig_mem [s used_memory]
        set args {}
        for {set i 0} {$i < 100000} {incr i} {
            lappend args $i
        }
        r sadd myset {*}$args
        assert {[r scard myset] == 100000}
        set peak_mem [s used_memory]
        assert {[r unlink myset] == 1}
        assert {$peak_mem > $orig_mem+1000000}
        wait_for_condition 50 100 {
            [s used_memory] < $peak_mem &&
            [s used_memory] < $orig_mem*2
        } else {
            fail "Memory is not reclaimed by UNLINK"
        }
    }

    test "FLUSHDB ASYNC can reclaim memory in background" {
        # make the previous test is really done before sampling used_memory
        wait_lazyfree_done r

        set orig_mem [s used_memory]
        set args {}
        for {set i 0} {$i < 100000} {incr i} {
            lappend args $i
        }
        r sadd myset {*}$args
        assert {[r scard myset] == 100000}
        set peak_mem [s used_memory]
        r flushdb async
        assert {$peak_mem > $orig_mem+1000000}
        wait_for_condition 50 100 {
            [s used_memory] < $peak_mem &&
            [s used_memory] < $orig_mem*2
        } else {
            fail "Memory is not reclaimed by FLUSHDB ASYNC"
        }
    }

    test "lazy free a stream with all types of metadata" {
        # make the previous test is really done before doing RESETSTAT
        wait_for_condition 50 100 {
            [s lazyfree_pending_objects] == 0
        } else {
            fail "lazyfree isn't done"
        }

        r config resetstat
        r config set stream-node-max-entries 5
        for {set j 0} {$j < 1000} {incr j} {
            if {rand() < 0.9} {
                r xadd stream * foo $j
            } else {
                r xadd stream * bar $j
            }
        }
        r xgroup create stream mygroup 0
        set records [r xreadgroup GROUP mygroup Alice COUNT 2 STREAMS stream >]
        r xdel stream [lindex [lindex [lindex [lindex $records 0] 1] 1] 0]
        r xack stream mygroup [lindex [lindex [lindex [lindex $records 0] 1] 0] 0]
        r unlink stream

        # make sure it was lazy freed
        wait_for_condition 50 100 {
            [s lazyfree_pending_objects] == 0
        } else {
            fail "lazyfree isn't done"
        }
        assert_equal [s lazyfreed_objects] 1
    } {} {needs:config-resetstat}

    test "lazy free a stream with deleted cgroup" {
        r config resetstat
        r xadd s * a b
        r xgroup create s bla $
        r xgroup destroy s bla
        r unlink s

        # make sure it was not lazy freed
        wait_for_condition 50 100 {
            [s lazyfree_pending_objects] == 0
        } else {
            fail "lazyfree isn't done"
        }
        assert_equal [s lazyfreed_objects] 0
    } {} {needs:config-resetstat}

    test "FLUSHALL SYNC optimized to run in bg as blocking FLUSHALL ASYNC" {
        set num_keys 1000
        r config resetstat

        # Verify at start there are no lazyfree pending objects
        assert_equal [s lazyfree_pending_objects] 0

        # Fillup DB with items
        populate $num_keys

        # Run FLUSHALL SYNC command, optimized as blocking ASYNC
        r flushall

        # Verify all keys counted as lazyfreed
        assert_equal [s lazyfreed_objects] $num_keys
    }

    test "Run consecutive blocking FLUSHALL ASYNC successfully" {
        r config resetstat
        set rd [redis_deferring_client]

        # Fillup DB with items
        r set x 1
        r set y 2

        $rd write "FLUSHALL\r\nFLUSHALL\r\nFLUSHDB\r\n"
        $rd flush
        assert_equal [$rd read] {OK}
        assert_equal [$rd read] {OK}
        assert_equal [$rd read] {OK}
        assert_equal [s lazyfreed_objects] 2
        $rd close
    }

    test "FLUSHALL SYNC in MULTI not optimized to run as blocking FLUSHALL ASYNC" {
        r config resetstat

        # Fillup DB with items
        r set x 11
        r set y 22

        # FLUSHALL SYNC in multi
        r multi
        r flushall
        r exec

        # Verify flushall not run as lazyfree
        assert_equal [s lazyfree_pending_objects] 0
        assert_equal [s lazyfreed_objects] 0
    }

    test "Client closed in the middle of blocking FLUSHALL ASYNC" {
        set num_keys 100000
        r config resetstat

        # Fillup DB with items
        populate $num_keys

        # close client in the middle of ongoing Blocking FLUSHALL ASYNC
        set rd [redis_deferring_client]
        $rd flushall
        $rd close

        # Wait to verify all keys counted as lazyfreed
        wait_for_condition 50 100 {
            [s lazyfreed_objects] == $num_keys
        } else {
            fail "Unexpected number of lazyfreed_objects: [s lazyfreed_objects]"
        }
    }

    test "Pending commands in querybuf processed once unblocking FLUSHALL ASYNC" {
        r config resetstat
        set rd [redis_deferring_client]

        # Fillup DB with items
        r set x 1
        r set y 2

        $rd write "FLUSHALL\r\nPING\r\n"
        $rd flush
        assert_equal [$rd read] {OK}
        assert_equal [$rd read] {PONG}
        assert_equal [s lazyfreed_objects] 2
        $rd close
    }

    test "Unblocks client blocked on lazyfree via REPLICAOF command" {
        r config resetstat
        set rd [redis_deferring_client]

        populate 50000 ;# Just to make flushdb async slower
        $rd flushdb

        # Verify flushdb run as lazyfree
        wait_for_condition 50 100 {
            [s lazyfree_pending_objects] > 0 ||
            [s lazyfreed_objects] > 0
        } else {
            fail "FLUSHDB didn't run as lazyfree"
        }

        # Test that slaveof command unblocks clients without assertion failure
        r slaveof 127.0.0.1 0
        assert_equal [$rd read] {OK}
        $rd close
        r ping
        r slaveof no one
    } {OK} {external:skip}
}