github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/keyspan/testdata/defragmenting_iter (about) 1 # Test a scenario that should NOT result in defragmentation. 2 3 define 4 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 5 c-d:{(#4,RANGEKEYSET,@3,bananas)} 6 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 7 ---- 8 9 iter 10 first 11 next 12 next 13 last 14 prev 15 prev 16 ---- 17 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 18 c-d:{(#4,RANGEKEYSET,@3,bananas)} 19 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 20 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 21 c-d:{(#4,RANGEKEYSET,@3,bananas)} 22 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 23 24 iter 25 first 26 next 27 next 28 next 29 last 30 prev 31 prev 32 prev 33 ---- 34 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 35 c-d:{(#4,RANGEKEYSET,@3,bananas)} 36 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 37 <nil> 38 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 39 c-d:{(#4,RANGEKEYSET,@3,bananas)} 40 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 41 <nil> 42 43 # Test a scenario that SHOULD result in internal defragmentation ([a,c) and 44 # [c,d) should be merged. 45 46 define 47 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 48 c-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 49 d-e:{(#1,RANGEKEYSET,@3,bananas)} 50 ---- 51 52 iter 53 first 54 next 55 next 56 ---- 57 a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 58 d-e:{(#1,RANGEKEYSET,@3,bananas)} 59 <nil> 60 61 # Test defragmenting in both directions at seek keys. 62 63 define 64 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 65 f-h:{(#3,RANGEKEYSET,@3,bananas)} 66 h-p:{(#3,RANGEKEYSET,@3,bananas)} 67 p-t:{(#3,RANGEKEYSET,@3,bananas)} 68 ---- 69 70 iter 71 seekge b 72 prev 73 seekge b 74 next 75 seeklt d 76 next 77 seeklt d 78 prev 79 ---- 80 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 81 <nil> 82 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 83 f-t:{(#3,RANGEKEYSET,@3,bananas)} 84 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 85 f-t:{(#3,RANGEKEYSET,@3,bananas)} 86 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 87 <nil> 88 89 iter 90 seeklt d 91 next 92 prev 93 ---- 94 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 95 f-t:{(#3,RANGEKEYSET,@3,bananas)} 96 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 97 98 # Test next-ing and prev-ing around seek keys. 99 100 define 101 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 102 f-h:{(#3,RANGEKEYSET,@3,bananas)} 103 h-p:{(#3,RANGEKEYSET,@3,bananas)} 104 p-t:{(#3,RANGEKEYSET,@3,bananas)} 105 t-z:{(#4,RANGEKEYSET,@2,oranges)} 106 ---- 107 108 iter 109 seekge r 110 prev 111 next 112 next 113 ---- 114 f-t:{(#3,RANGEKEYSET,@3,bananas)} 115 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 116 f-t:{(#3,RANGEKEYSET,@3,bananas)} 117 t-z:{(#4,RANGEKEYSET,@2,oranges)} 118 119 iter 120 seekge f 121 seekge h 122 seekge p 123 seekge t 124 seekge u 125 seekge v 126 seekge z 127 ---- 128 f-t:{(#3,RANGEKEYSET,@3,bananas)} 129 f-t:{(#3,RANGEKEYSET,@3,bananas)} 130 f-t:{(#3,RANGEKEYSET,@3,bananas)} 131 t-z:{(#4,RANGEKEYSET,@2,oranges)} 132 t-z:{(#4,RANGEKEYSET,@2,oranges)} 133 t-z:{(#4,RANGEKEYSET,@2,oranges)} 134 <nil> 135 136 iter 137 seeklt f 138 seeklt h 139 seeklt p 140 seeklt t 141 seeklt u 142 seeklt z 143 ---- 144 a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 145 f-t:{(#3,RANGEKEYSET,@3,bananas)} 146 f-t:{(#3,RANGEKEYSET,@3,bananas)} 147 f-t:{(#3,RANGEKEYSET,@3,bananas)} 148 t-z:{(#4,RANGEKEYSET,@2,oranges)} 149 t-z:{(#4,RANGEKEYSET,@2,oranges)} 150 151 # Test iteration with a reducer that collects keys across all spans that 152 # constitute a defragmented span. Abutting spans are always combined. 153 154 define 155 a-b:{(#3,RANGEDEL) (#2,RANGEDEL)} 156 b-c:{(#4,RANGEDEL) (#1,RANGEDEL)} 157 c-d:{(#5,RANGEDEL)} 158 e-f:{(#1,RANGEDEL)} 159 f-g:{(#2,RANGEDEL)} 160 ---- 161 162 iter equal=always reducer=collect 163 first 164 next 165 next 166 last 167 prev 168 prev 169 ---- 170 a-d:{(#5,RANGEDEL) (#4,RANGEDEL) (#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)} 171 e-g:{(#2,RANGEDEL) (#1,RANGEDEL)} 172 <nil> 173 e-g:{(#2,RANGEDEL) (#1,RANGEDEL)} 174 a-d:{(#5,RANGEDEL) (#4,RANGEDEL) (#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)} 175 <nil> 176 177 # Test defragmentation of non-empty (i.e. more than one value) fragments, while 178 # empty fragments are left untouched. 179 180 define 181 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 182 c-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 183 d-e:{} 184 e-f:{} 185 g-h:{(#1,RANGEKEYSET,@3,bananas)} 186 ---- 187 188 iter 189 first 190 next 191 next 192 next 193 next 194 ---- 195 a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 196 d-e:{} 197 e-f:{} 198 g-h:{(#1,RANGEKEYSET,@3,bananas)} 199 <nil> 200 201 iter 202 last 203 prev 204 prev 205 prev 206 prev 207 ---- 208 g-h:{(#1,RANGEKEYSET,@3,bananas)} 209 e-f:{} 210 d-e:{} 211 a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 212 <nil> 213 214 iter 215 seekge d 216 next 217 prev 218 seekge e 219 next 220 prev 221 prev 222 prev 223 ---- 224 d-e:{} 225 e-f:{} 226 d-e:{} 227 e-f:{} 228 g-h:{(#1,RANGEKEYSET,@3,bananas)} 229 e-f:{} 230 d-e:{} 231 a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 232 233 iter 234 seeklt e 235 next 236 prev 237 seeklt f 238 next 239 prev 240 prev 241 prev 242 ---- 243 d-e:{} 244 e-f:{} 245 d-e:{} 246 e-f:{} 247 g-h:{(#1,RANGEKEYSET,@3,bananas)} 248 e-f:{} 249 d-e:{} 250 a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 251 252 # Test that the defragmenting iterator does yield errors in cases that do not 253 # need to defragment. 254 255 define 256 a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 257 c-d:{(#4,RANGEKEYSET,@3,bananas)} 258 d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 259 ---- 260 261 iter probes=(ErrInjected) 262 seek-ge b 263 seek-lt d 264 first 265 last 266 ---- 267 <nil> err=<injected error> 268 <nil> err=<injected error> 269 <nil> err=<injected error> 270 <nil> err=<injected error> 271 272 # Next and Prev may only be called on positioned iterators, so to test 273 # propagation of errors on Next or Prev, we must use a probe that injects errors 274 # on Next or Prev but leaves seeks untouched. 275 # 276 # The situation is complicated by the fact that a seek on the defragmenting 277 # iterator will result in Next/Prevs on the embedded iterator (in order to peek 278 # ahead to see if anything needs to be defragmented). 279 # 280 # First we test the seeks too result in injected errors when they Next/Prev 281 # ahead to determine if there's anything to defragment. 282 283 iter probes=((If (Or OpNext OpPrev) ErrInjected noop), (Log "# inner.")) 284 seek-ge b 285 next 286 seek-lt cat 287 prev 288 ---- 289 # inner.SeekGE("b") = a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 290 # inner.Prev() = nil <err="injected error"> 291 <nil> err=<injected error> 292 # inner.Next() = nil <err="injected error"> 293 <nil> err=<injected error> 294 # inner.SeekLT("cat") = c-d:{(#4,RANGEKEYSET,@3,bananas)} 295 # inner.Next() = nil <err="injected error"> 296 <nil> err=<injected error> 297 # inner.Prev() = nil <err="injected error"> 298 <nil> err=<injected error> 299 300 # Use a probe that injects errors whenever we otherwise would've returned the 301 # c-d span. First and Last calls should both return errors because during 302 # defragmenting they'll step the internal iterator on to the error position. 303 304 iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner.")) 305 first 306 last 307 ---- 308 # inner.First() = a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)} 309 # inner.Next() = nil <err="injected error"> 310 <nil> err=<injected error> 311 # inner.Last() = d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 312 # inner.Prev() = nil <err="injected error"> 313 <nil> err=<injected error> 314 315 # In order to test that errors are injected when Next-ing the top-level 316 # iterator, define test data that includes 5 spans. 317 318 define 319 a-b:{(#3,RANGEKEYUNSET,@5)} 320 b-c:{(#4,RANGEKEYSET,@5,apples)} 321 c-d:{(#5,RANGEKEYSET,@3,bananas)} 322 d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 323 e-f:{(#4,RANGEKEYSET,@1,pineapple)} 324 ---- 325 326 # Use a probe that injects errors whenever we would've otherwise returned the 327 # c-d span. Our initial First/Last seeks should not step on to the error 328 # position and should not error. The subsequent Next/Prev however should. 329 330 iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner.")) 331 first 332 next 333 last 334 prev 335 ---- 336 # inner.First() = a-b:{(#3,RANGEKEYUNSET,@5)} 337 # inner.Next() = b-c:{(#4,RANGEKEYSET,@5,apples)} 338 a-b:{(#3,RANGEKEYUNSET,@5)} 339 # inner.Next() = nil <err="injected error"> 340 <nil> err=<injected error> 341 # inner.Last() = e-f:{(#4,RANGEKEYSET,@1,pineapple)} 342 # inner.Prev() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 343 e-f:{(#4,RANGEKEYSET,@1,pineapple)} 344 # inner.Prev() = nil <err="injected error"> 345 <nil> err=<injected error> 346 347 # When seeking, the defragmenting iterator needs to defragment in both 348 # directions. A forward seek first defragments in the reverse direction, and 349 # then in the forward direction. A backward seek does the inverse. If an error 350 # is encountered while performing the first defragment scan, it must be 351 # surfaced. 352 # 353 # To test this scenario we again inject errors instead of the c-d span. 354 # - The SeekGE('d') should land on d-e, try to defragment backward first and 355 # encounter the error. 356 # - The SeekLT('c') should land on b-c, try to defragment forward first and 357 # encounter the error. 358 iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner.")) 359 seek-ge d 360 seek-lt c 361 ---- 362 # inner.SeekGE("d") = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 363 # inner.Prev() = nil <err="injected error"> 364 <nil> err=<injected error> 365 # inner.SeekLT("c") = b-c:{(#4,RANGEKEYSET,@5,apples)} 366 # inner.Next() = nil <err="injected error"> 367 <nil> err=<injected error> 368 369 # When changing directions in some circumstances we step an iterator and then 370 # defragment twice; once to skip over the current span and once to construct the 371 # next defragmented span in the new iteration direction. If the first step of 372 # the iterator surfaces an error, ensure that it's still propagated. 373 iter probes=((If (And OpPrev (Equal StartKey (Bytes "c"))) ErrInjected noop), (Log "# inner.")) 374 seek-ge c 375 prev 376 ---- 377 # inner.SeekGE("c") = c-d:{(#5,RANGEKEYSET,@3,bananas)} 378 # inner.Prev() = b-c:{(#4,RANGEKEYSET,@5,apples)} 379 # inner.Next() = c-d:{(#5,RANGEKEYSET,@3,bananas)} 380 # inner.Next() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 381 c-d:{(#5,RANGEKEYSET,@3,bananas)} 382 # inner.Prev() = nil <err="injected error"> 383 <nil> err=<injected error> 384 385 iter probes=((If (And OpNext (Equal StartKey (Bytes "c"))) ErrInjected noop), (Log "# inner.")) 386 seek-lt d 387 next 388 ---- 389 # inner.SeekLT("d") = c-d:{(#5,RANGEKEYSET,@3,bananas)} 390 # inner.Next() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)} 391 # inner.Prev() = c-d:{(#5,RANGEKEYSET,@3,bananas)} 392 # inner.Prev() = b-c:{(#4,RANGEKEYSET,@5,apples)} 393 c-d:{(#5,RANGEKEYSET,@3,bananas)} 394 # inner.Next() = nil <err="injected error"> 395 <nil> err=<injected error>