github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/rangefeed/resolved_timestamp_test.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package rangefeed 12 13 import ( 14 "testing" 15 16 "github.com/cockroachdb/cockroach/pkg/roachpb" 17 "github.com/cockroachdb/cockroach/pkg/util/hlc" 18 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 19 "github.com/cockroachdb/cockroach/pkg/util/uuid" 20 "github.com/stretchr/testify/require" 21 ) 22 23 func TestUnresolvedIntentQueue(t *testing.T) { 24 defer leaktest.AfterTest(t)() 25 uiq := makeUnresolvedIntentQueue() 26 27 // Test empty queue. 28 require.Equal(t, 0, uiq.Len()) 29 require.Nil(t, uiq.Oldest()) 30 require.Nil(t, uiq.Before(hlc.MinTimestamp)) 31 require.Nil(t, uiq.Before(hlc.MaxTimestamp)) 32 33 // Increment a non-existent txn. 34 txn1 := uuid.MakeV4() 35 txn1Key := roachpb.Key("key1") 36 txn1TS := hlc.Timestamp{WallTime: 1} 37 txn1MinTS := hlc.Timestamp{WallTime: 0, Logical: 4} 38 adv := uiq.IncRef(txn1, txn1Key, txn1MinTS, txn1TS) 39 require.False(t, adv) 40 require.Equal(t, 1, uiq.Len()) 41 require.Equal(t, txn1, uiq.Oldest().txnID) 42 require.Equal(t, txn1Key, uiq.Oldest().txnKey) 43 require.Equal(t, txn1MinTS, uiq.Oldest().txnMinTimestamp) 44 require.Equal(t, txn1TS, uiq.Oldest().timestamp) 45 require.Equal(t, 1, uiq.Oldest().refCount) 46 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 0}))) 47 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 1}))) 48 require.Equal(t, 1, len(uiq.Before(hlc.Timestamp{WallTime: 2}))) 49 require.NotPanics(t, func() { uiq.assertOnlyPositiveRefCounts() }) 50 51 // Decrement a non-existent txn. 52 txn2 := uuid.MakeV4() 53 txn2TS := hlc.Timestamp{WallTime: 3} 54 adv = uiq.DecrRef(txn2, txn2TS) 55 require.False(t, adv) 56 require.Equal(t, 2, uiq.Len()) 57 require.Equal(t, txn1, uiq.Oldest().txnID) 58 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 1}))) 59 require.Equal(t, 1, len(uiq.Before(hlc.Timestamp{WallTime: 3}))) 60 require.Equal(t, 2, len(uiq.Before(hlc.Timestamp{WallTime: 5}))) 61 require.Panics(t, func() { uiq.assertOnlyPositiveRefCounts() }) 62 63 // Update a non-existent txn. 64 txn3 := uuid.MakeV4() 65 adv = uiq.UpdateTS(txn3, hlc.Timestamp{WallTime: 5}) 66 require.False(t, adv) 67 require.Equal(t, 2, uiq.Len()) 68 69 // Delete a non-existent txn. 70 txn4 := uuid.MakeV4() 71 adv = uiq.Del(txn4) 72 require.False(t, adv) 73 require.Equal(t, 2, uiq.Len()) 74 75 // Update txn1 with a smaller timestamp. 76 adv = uiq.UpdateTS(txn1, hlc.Timestamp{WallTime: 0}) 77 require.False(t, adv) 78 require.Equal(t, 2, uiq.Len()) 79 require.Equal(t, txn1, uiq.Oldest().txnID) 80 require.Equal(t, txn1TS, uiq.Oldest().timestamp) 81 82 // Update txn1 with an equal timestamp. 83 adv = uiq.UpdateTS(txn1, hlc.Timestamp{WallTime: 1}) 84 require.False(t, adv) 85 require.Equal(t, 2, uiq.Len()) 86 require.Equal(t, txn1, uiq.Oldest().txnID) 87 require.Equal(t, txn1TS, uiq.Oldest().timestamp) 88 89 // Update txn1 with a larger timestamp. Should advance. 90 newTxn1TS := hlc.Timestamp{WallTime: 2} 91 adv = uiq.UpdateTS(txn1, newTxn1TS) 92 require.True(t, adv) 93 require.Equal(t, 2, uiq.Len()) 94 require.Equal(t, txn1, uiq.Oldest().txnID) 95 require.Equal(t, newTxn1TS, uiq.Oldest().timestamp) 96 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 2}))) 97 require.Equal(t, 1, len(uiq.Before(hlc.Timestamp{WallTime: 3}))) 98 require.Equal(t, 2, len(uiq.Before(hlc.Timestamp{WallTime: 4}))) 99 100 // Update txn1 with a much larger timestamp. txn2 new oldest. 101 newTxn1TS = hlc.Timestamp{WallTime: 4} 102 adv = uiq.UpdateTS(txn1, newTxn1TS) 103 require.True(t, adv) 104 require.Equal(t, 2, uiq.Len()) 105 require.Equal(t, txn2, uiq.Oldest().txnID) 106 require.Equal(t, txn2TS, uiq.Oldest().timestamp) 107 // Negative ref count ok. Indicates a re-ordering of events, which is 108 // expected during the catch up scan and supported by the queue. 109 require.Equal(t, -1, uiq.Oldest().refCount) 110 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 2}))) 111 require.Equal(t, 0, len(uiq.Before(hlc.Timestamp{WallTime: 3}))) 112 require.Equal(t, 1, len(uiq.Before(hlc.Timestamp{WallTime: 4}))) 113 require.Equal(t, 2, len(uiq.Before(hlc.Timestamp{WallTime: 5}))) 114 115 // Increase txn1's ref count while increasing timestamp. 116 newTxn1TS = hlc.Timestamp{WallTime: 5} 117 adv = uiq.IncRef(txn1, txn1Key, txn1MinTS, newTxn1TS) 118 require.False(t, adv) 119 require.Equal(t, 2, uiq.Len()) 120 require.Equal(t, 2, uiq.txns[txn1].refCount) 121 require.Equal(t, newTxn1TS, uiq.txns[txn1].timestamp) 122 123 // Decrease txn1's ref count while increasing timestamp. 124 newTxn1TS = hlc.Timestamp{WallTime: 6} 125 adv = uiq.DecrRef(txn1, newTxn1TS) 126 require.False(t, adv) 127 require.Equal(t, 2, uiq.Len()) 128 require.Equal(t, 1, uiq.txns[txn1].refCount) 129 require.Equal(t, newTxn1TS, uiq.txns[txn1].timestamp) 130 131 // Add new txn at much higher timestamp. Immediately delete. 132 txn5 := uuid.MakeV4() 133 txn5TS := hlc.Timestamp{WallTime: 10} 134 adv = uiq.IncRef(txn5, nil, txn5TS, txn5TS) 135 require.False(t, adv) 136 require.Equal(t, 3, uiq.Len()) 137 require.Equal(t, txn2, uiq.Oldest().txnID) 138 adv = uiq.Del(txn5) 139 require.False(t, adv) 140 require.Equal(t, 2, uiq.Len()) 141 142 // Increase txn2's ref count, which results in deletion. txn1 new oldest. 143 adv = uiq.IncRef(txn2, nil, txn2TS, txn2TS) 144 require.True(t, adv) 145 require.Equal(t, 1, uiq.Len()) 146 require.Equal(t, txn1, uiq.Oldest().txnID) 147 require.Equal(t, newTxn1TS, uiq.Oldest().timestamp) 148 require.NotPanics(t, func() { uiq.assertOnlyPositiveRefCounts() }) 149 150 // Decrease txn1's ref count. Should be empty again. 151 adv = uiq.DecrRef(txn1, hlc.Timestamp{}) 152 require.True(t, adv) 153 require.Equal(t, 0, uiq.Len()) 154 155 // Add new txn. Immediately decrement ref count. Should be empty again. 156 txn6 := uuid.MakeV4() 157 txn6TS := hlc.Timestamp{WallTime: 20} 158 adv = uiq.IncRef(txn6, nil, txn6TS, txn6TS) 159 require.False(t, adv) 160 require.Equal(t, 1, uiq.Len()) 161 require.Equal(t, txn6, uiq.Oldest().txnID) 162 adv = uiq.DecrRef(txn6, hlc.Timestamp{}) 163 require.True(t, adv) 164 require.Equal(t, 0, uiq.Len()) 165 166 // Instruct the queue to disallow negative ref counts. 167 uiq.AllowNegRefCount(false) 168 169 // Decrease txn1's ref count. Should ignore because ref count 170 // would go negative. 171 adv = uiq.DecrRef(txn1, hlc.Timestamp{}) 172 require.False(t, adv) 173 require.Equal(t, 0, uiq.Len()) 174 } 175 176 func TestResolvedTimestamp(t *testing.T) { 177 defer leaktest.AfterTest(t)() 178 rts := makeResolvedTimestamp() 179 rts.Init() 180 181 // Test empty resolved timestamp. 182 require.Equal(t, hlc.Timestamp{}, rts.Get()) 183 184 // Add an intent. No closed timestamp so no resolved timestamp. 185 txn1 := uuid.MakeV4() 186 fwd := rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 10})) 187 require.False(t, fwd) 188 require.Equal(t, hlc.Timestamp{}, rts.Get()) 189 190 // Add another intent. No closed timestamp so no resolved timestamp. 191 txn2 := uuid.MakeV4() 192 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn2, hlc.Timestamp{WallTime: 12})) 193 require.False(t, fwd) 194 require.Equal(t, hlc.Timestamp{}, rts.Get()) 195 196 // Set a closed timestamp. Resolved timestamp advances. 197 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 5}) 198 require.True(t, fwd) 199 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 200 201 // Write intent at earlier timestamp. Assertion failure. 202 require.Panics(t, func() { 203 rts.ConsumeLogicalOp(writeIntentOp(uuid.MakeV4(), hlc.Timestamp{WallTime: 3})) 204 }) 205 206 // Write value at earlier timestamp. Assertion failure. 207 require.Panics(t, func() { 208 rts.ConsumeLogicalOp(writeValueOp(hlc.Timestamp{WallTime: 4})) 209 }) 210 211 // Write value at later timestamp. No effect on resolved timestamp. 212 fwd = rts.ConsumeLogicalOp(writeValueOp(hlc.Timestamp{WallTime: 6})) 213 require.False(t, fwd) 214 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 215 216 // Forward closed timestamp. Resolved timestamp advances to the timestamp of 217 // the earliest intent. 218 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 15}) 219 require.True(t, fwd) 220 require.Equal(t, hlc.Timestamp{WallTime: 9}, rts.Get()) 221 222 // Update the timestamp of txn2. No effect on the resolved timestamp. 223 fwd = rts.ConsumeLogicalOp(updateIntentOp(txn2, hlc.Timestamp{WallTime: 18})) 224 require.False(t, fwd) 225 require.Equal(t, hlc.Timestamp{WallTime: 9}, rts.Get()) 226 227 // Update the timestamp of txn1. Resolved timestamp moves forward. 228 fwd = rts.ConsumeLogicalOp(updateIntentOp(txn1, hlc.Timestamp{WallTime: 20})) 229 require.True(t, fwd) 230 require.Equal(t, hlc.Timestamp{WallTime: 15}, rts.Get()) 231 232 // Forward closed timestamp to same time as earliest intent. 233 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 18}) 234 require.True(t, fwd) 235 require.Equal(t, hlc.Timestamp{WallTime: 17}, rts.Get()) 236 237 // Write intent for earliest txn at same timestamp. No change. 238 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn2, hlc.Timestamp{WallTime: 18})) 239 require.False(t, fwd) 240 require.Equal(t, hlc.Timestamp{WallTime: 17}, rts.Get()) 241 242 // Write intent for earliest txn at later timestamp. Resolved 243 // timestamp moves forward. 244 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn2, hlc.Timestamp{WallTime: 25})) 245 require.True(t, fwd) 246 require.Equal(t, hlc.Timestamp{WallTime: 18}, rts.Get()) 247 248 // Forward closed timestamp. Resolved timestamp moves to earliest intent. 249 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 30}) 250 require.True(t, fwd) 251 require.Equal(t, hlc.Timestamp{WallTime: 19}, rts.Get()) 252 253 // First transaction aborted. Resolved timestamp moves to next earliest 254 // intent. 255 fwd = rts.ConsumeLogicalOp(abortTxnOp(txn1)) 256 require.True(t, fwd) 257 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 258 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn1)) 259 require.False(t, fwd) 260 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 261 262 // Third transaction at higher timestamp. No effect. 263 txn3 := uuid.MakeV4() 264 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn3, hlc.Timestamp{WallTime: 30})) 265 require.False(t, fwd) 266 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 267 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn3, hlc.Timestamp{WallTime: 31})) 268 require.False(t, fwd) 269 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 270 271 // Third transaction aborted. No effect. 272 fwd = rts.ConsumeLogicalOp(abortTxnOp(txn3)) 273 require.False(t, fwd) 274 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 275 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn3)) 276 require.False(t, fwd) 277 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 278 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn3)) 279 require.False(t, fwd) 280 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 281 282 // Fourth transaction at higher timestamp. No effect. 283 txn4 := uuid.MakeV4() 284 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn4, hlc.Timestamp{WallTime: 45})) 285 require.False(t, fwd) 286 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 287 288 // Fourth transaction committed. No effect. 289 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn4, hlc.Timestamp{WallTime: 45})) 290 require.False(t, fwd) 291 require.Equal(t, hlc.Timestamp{WallTime: 24}, rts.Get()) 292 293 // Second transaction observes one intent being resolved at timestamp 294 // above closed time. Resolved timestamp moves to closed timestamp. 295 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn2, hlc.Timestamp{WallTime: 35})) 296 require.True(t, fwd) 297 require.Equal(t, hlc.Timestamp{WallTime: 30}, rts.Get()) 298 299 // Forward closed timestamp. Resolved timestamp moves to earliest intent. 300 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 40}) 301 require.True(t, fwd) 302 require.Equal(t, hlc.Timestamp{WallTime: 34}, rts.Get()) 303 304 // Second transaction observes another intent being resolved at timestamp 305 // below closed time. Still one intent left. 306 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn2, hlc.Timestamp{WallTime: 35})) 307 require.False(t, fwd) 308 require.Equal(t, hlc.Timestamp{WallTime: 34}, rts.Get()) 309 310 // Second transaction observes final intent being resolved at timestamp 311 // below closed time. Resolved timestamp moves to closed timestamp. 312 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn2, hlc.Timestamp{WallTime: 35})) 313 require.True(t, fwd) 314 require.Equal(t, hlc.Timestamp{WallTime: 40}, rts.Get()) 315 316 // Fifth transaction at higher timestamp. No effect. 317 txn5 := uuid.MakeV4() 318 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn5, hlc.Timestamp{WallTime: 45})) 319 require.False(t, fwd) 320 require.Equal(t, hlc.Timestamp{WallTime: 40}, rts.Get()) 321 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn5, hlc.Timestamp{WallTime: 46})) 322 require.False(t, fwd) 323 require.Equal(t, hlc.Timestamp{WallTime: 40}, rts.Get()) 324 325 // Forward closed timestamp. Resolved timestamp moves to earliest intent. 326 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 50}) 327 require.True(t, fwd) 328 require.Equal(t, hlc.Timestamp{WallTime: 45}, rts.Get()) 329 330 // Fifth transaction bumps epoch and re-writes one of its intents. Resolved 331 // timestamp moves to the new transaction timestamp. 332 fwd = rts.ConsumeLogicalOp(updateIntentOp(txn5, hlc.Timestamp{WallTime: 47})) 333 require.True(t, fwd) 334 require.Equal(t, hlc.Timestamp{WallTime: 46}, rts.Get()) 335 336 // Fifth transaction committed, but only one of its intents was written in 337 // its final epoch. Resolved timestamp moves forward after observing the 338 // first intent committing at a higher timestamp and moves to the closed 339 // timestamp after observing the second intent aborting. 340 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn5, hlc.Timestamp{WallTime: 49})) 341 require.True(t, fwd) 342 require.Equal(t, hlc.Timestamp{WallTime: 48}, rts.Get()) 343 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn5)) 344 require.True(t, fwd) 345 require.Equal(t, hlc.Timestamp{WallTime: 50}, rts.Get()) 346 } 347 348 func TestResolvedTimestampNoClosedTimestamp(t *testing.T) { 349 defer leaktest.AfterTest(t)() 350 rts := makeResolvedTimestamp() 351 rts.Init() 352 353 // Add a value. No closed timestamp so no resolved timestamp. 354 fwd := rts.ConsumeLogicalOp(writeValueOp(hlc.Timestamp{WallTime: 1})) 355 require.False(t, fwd) 356 require.Equal(t, hlc.Timestamp{}, rts.Get()) 357 358 // Add an intent. No closed timestamp so no resolved timestamp. 359 txn1 := uuid.MakeV4() 360 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 1})) 361 require.False(t, fwd) 362 require.Equal(t, hlc.Timestamp{}, rts.Get()) 363 364 // Update intent. No closed timestamp so no resolved timestamp. 365 fwd = rts.ConsumeLogicalOp(updateIntentOp(txn1, hlc.Timestamp{WallTime: 2})) 366 require.False(t, fwd) 367 require.Equal(t, hlc.Timestamp{}, rts.Get()) 368 369 // Add another intent. No closed timestamp so no resolved timestamp. 370 txn2 := uuid.MakeV4() 371 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn2, hlc.Timestamp{WallTime: 3})) 372 require.False(t, fwd) 373 require.Equal(t, hlc.Timestamp{}, rts.Get()) 374 375 // Abort the first intent. No closed timestamp so no resolved timestamp. 376 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn1)) 377 require.False(t, fwd) 378 require.Equal(t, hlc.Timestamp{}, rts.Get()) 379 380 // Commit the second intent. No closed timestamp so no resolved timestamp. 381 fwd = rts.ConsumeLogicalOp(commitIntentOp(txn2, hlc.Timestamp{WallTime: 3})) 382 require.False(t, fwd) 383 require.Equal(t, hlc.Timestamp{}, rts.Get()) 384 } 385 386 func TestResolvedTimestampNoIntents(t *testing.T) { 387 defer leaktest.AfterTest(t)() 388 rts := makeResolvedTimestamp() 389 rts.Init() 390 391 // Set a closed timestamp. Resolved timestamp advances. 392 fwd := rts.ForwardClosedTS(hlc.Timestamp{WallTime: 1}) 393 require.True(t, fwd) 394 require.Equal(t, hlc.Timestamp{WallTime: 1}, rts.Get()) 395 396 // Forward closed timestamp. Resolved timestamp advances. 397 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 3}) 398 require.True(t, fwd) 399 require.Equal(t, hlc.Timestamp{WallTime: 3}, rts.Get()) 400 401 // Smaller closed timestamp. Resolved timestamp does not advance. 402 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 2}) 403 require.False(t, fwd) 404 require.Equal(t, hlc.Timestamp{WallTime: 3}, rts.Get()) 405 406 // Equal closed timestamp. Resolved timestamp does not advance. 407 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 3}) 408 require.False(t, fwd) 409 require.Equal(t, hlc.Timestamp{WallTime: 3}, rts.Get()) 410 411 // Forward closed timestamp. Resolved timestamp advances. 412 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 4}) 413 require.True(t, fwd) 414 require.Equal(t, hlc.Timestamp{WallTime: 4}, rts.Get()) 415 } 416 417 func TestResolvedTimestampInit(t *testing.T) { 418 defer leaktest.AfterTest(t)() 419 420 t.Run("CT Before Init", func(t *testing.T) { 421 rts := makeResolvedTimestamp() 422 423 // Set a closed timestamp. Not initialized so no resolved timestamp. 424 fwd := rts.ForwardClosedTS(hlc.Timestamp{WallTime: 5}) 425 require.False(t, fwd) 426 require.Equal(t, hlc.Timestamp{}, rts.Get()) 427 428 // Init. Resolved timestamp moves to closed timestamp. 429 fwd = rts.Init() 430 require.True(t, fwd) 431 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 432 }) 433 t.Run("No CT Before Init", func(t *testing.T) { 434 rts := makeResolvedTimestamp() 435 436 // Add an intent. Not initialized so no resolved timestamp. 437 txn1 := uuid.MakeV4() 438 fwd := rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 3})) 439 require.False(t, fwd) 440 require.Equal(t, hlc.Timestamp{}, rts.Get()) 441 442 // Init. Resolved timestamp undefined. 443 fwd = rts.Init() 444 require.False(t, fwd) 445 require.Equal(t, hlc.Timestamp{}, rts.Get()) 446 }) 447 t.Run("Write Before Init", func(t *testing.T) { 448 rts := makeResolvedTimestamp() 449 450 // Add an intent. Not initialized so no resolved timestamp. 451 txn1 := uuid.MakeV4() 452 fwd := rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 3})) 453 require.False(t, fwd) 454 require.Equal(t, hlc.Timestamp{}, rts.Get()) 455 456 // Set a closed timestamp. Not initialized so no resolved timestamp. 457 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 5}) 458 require.False(t, fwd) 459 require.Equal(t, hlc.Timestamp{}, rts.Get()) 460 461 // Init. Resolved timestamp moves below first unresolved intent. 462 fwd = rts.Init() 463 require.True(t, fwd) 464 require.Equal(t, hlc.Timestamp{WallTime: 2}, rts.Get()) 465 }) 466 t.Run("Abort + Write Before Init", func(t *testing.T) { 467 rts := makeResolvedTimestamp() 468 469 // Abort an intent. Not initialized so no resolved timestamp. 470 txn1 := uuid.MakeV4() 471 fwd := rts.ConsumeLogicalOp(abortIntentOp(txn1)) 472 require.False(t, fwd) 473 require.Equal(t, hlc.Timestamp{}, rts.Get()) 474 475 // Abort that intent's transaction. Not initialized so no-op. 476 fwd = rts.ConsumeLogicalOp(abortTxnOp(txn1)) 477 require.False(t, fwd) 478 require.Equal(t, hlc.Timestamp{}, rts.Get()) 479 480 // Later, write an intent for the same transaction. This should cancel 481 // out with the out-of-order intent abort operation. If this abort hadn't 482 // allowed the unresolvedTxn's ref count to drop below 0, this would 483 // have created a reference that would never be cleaned up. 484 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 3})) 485 require.False(t, fwd) 486 require.Equal(t, hlc.Timestamp{}, rts.Get()) 487 488 // Set a closed timestamp. Not initialized so no resolved timestamp. 489 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 5}) 490 require.False(t, fwd) 491 require.Equal(t, hlc.Timestamp{}, rts.Get()) 492 493 // Init. Resolved timestamp moves to closed timestamp. 494 fwd = rts.Init() 495 require.True(t, fwd) 496 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 497 }) 498 t.Run("Abort Before Init, No Write", func(t *testing.T) { 499 rts := makeResolvedTimestamp() 500 501 // Abort an intent. Not initialized so no resolved timestamp. 502 txn1 := uuid.MakeV4() 503 fwd := rts.ConsumeLogicalOp(abortIntentOp(txn1)) 504 require.False(t, fwd) 505 require.Equal(t, hlc.Timestamp{}, rts.Get()) 506 507 // Init. Negative txn ref count causes panic. Init should not have 508 // been called because an intent must not have been accounted for. 509 require.Panics(t, func() { rts.Init() }) 510 }) 511 } 512 513 func TestResolvedTimestampTxnAborted(t *testing.T) { 514 defer leaktest.AfterTest(t)() 515 rts := makeResolvedTimestamp() 516 rts.Init() 517 518 // Set a closed timestamp. Resolved timestamp advances. 519 fwd := rts.ForwardClosedTS(hlc.Timestamp{WallTime: 5}) 520 require.True(t, fwd) 521 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 522 523 // Add an intent for a new transaction. 524 txn1 := uuid.MakeV4() 525 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 10})) 526 require.False(t, fwd) 527 require.Equal(t, hlc.Timestamp{WallTime: 5}, rts.Get()) 528 529 // Set a new closed timestamp. Resolved timestamp advances. 530 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 15}) 531 require.True(t, fwd) 532 require.Equal(t, hlc.Timestamp{WallTime: 9}, rts.Get()) 533 534 // Abort txn1 after a periodic txn push. Resolved timestamp advances. 535 fwd = rts.ConsumeLogicalOp(abortTxnOp(txn1)) 536 require.True(t, fwd) 537 require.Equal(t, hlc.Timestamp{WallTime: 15}, rts.Get()) 538 539 // Update one of txn1's intents. Should be ignored. 540 fwd = rts.ConsumeLogicalOp(updateIntentOp(txn1, hlc.Timestamp{WallTime: 20})) 541 require.False(t, fwd) 542 require.Equal(t, hlc.Timestamp{WallTime: 15}, rts.Get()) 543 544 // Abort one of txn1's intents. Should be ignored. 545 fwd = rts.ConsumeLogicalOp(abortIntentOp(txn1)) 546 require.False(t, fwd) 547 require.Equal(t, hlc.Timestamp{WallTime: 15}, rts.Get()) 548 549 // Write another intent as txn1. Should add txn1 back into queue. 550 // This will eventually require another txn push to evict. 551 fwd = rts.ConsumeLogicalOp(writeIntentOp(txn1, hlc.Timestamp{WallTime: 20})) 552 require.False(t, fwd) 553 require.Equal(t, hlc.Timestamp{WallTime: 15}, rts.Get()) 554 555 // Set a new closed timestamp. Resolved timestamp advances, but only up to 556 // the timestamp of txn1's intent, which we fail remember is uncommittable. 557 fwd = rts.ForwardClosedTS(hlc.Timestamp{WallTime: 25}) 558 require.True(t, fwd) 559 require.Equal(t, hlc.Timestamp{WallTime: 19}, rts.Get()) 560 561 // Abort txn1 again after another periodic push. Resolved timestamp advances. 562 fwd = rts.ConsumeLogicalOp(abortTxnOp(txn1)) 563 require.True(t, fwd) 564 require.Equal(t, hlc.Timestamp{WallTime: 25}, rts.Get()) 565 }