github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/transaction_test.go (about) 1 /* 2 * Copyright 2017 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package badger 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "math" 23 "math/rand" 24 "os" 25 "strconv" 26 "sync" 27 "sync/atomic" 28 "testing" 29 "time" 30 31 "github.com/coocood/badger/y" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func TestTxnSimple(t *testing.T) { 36 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 37 38 txn := db.NewTransaction(true) 39 40 for i := 0; i < 10; i++ { 41 k := []byte(fmt.Sprintf("key=%d", i)) 42 v := []byte(fmt.Sprintf("val=%d", i)) 43 txn.Set(k, v) 44 } 45 46 item, err := txn.Get([]byte("key=8")) 47 require.NoError(t, err) 48 49 val, err := item.Value() 50 require.NoError(t, err) 51 require.Equal(t, []byte("val=8"), val) 52 53 require.Equal(t, ErrManagedTxn, txn.CommitAt(100)) 54 require.NoError(t, txn.Commit()) 55 }) 56 } 57 58 func TestTxnReadAfterWrite(t *testing.T) { 59 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 60 var wg sync.WaitGroup 61 N := 100 62 wg.Add(N) 63 for i := 0; i < N; i++ { 64 go func(i int) { 65 defer wg.Done() 66 key := []byte(fmt.Sprintf("key%d", i)) 67 err := db.Update(func(tx *Txn) error { 68 return tx.Set(key, key) 69 }) 70 require.NoError(t, err) 71 err = db.View(func(tx *Txn) error { 72 item, err := tx.Get(key) 73 require.NoError(t, err) 74 val, err := item.Value() 75 require.NoError(t, err) 76 require.Equal(t, val, key) 77 return nil 78 }) 79 require.NoError(t, err) 80 }(i) 81 } 82 wg.Wait() 83 }) 84 } 85 86 func TestTxnCommitAsync(t *testing.T) { 87 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 88 89 txn := db.NewTransaction(true) 90 key := func(i int) []byte { 91 return []byte(fmt.Sprintf("key=%d", i)) 92 } 93 for i := 0; i < 40; i++ { 94 err := txn.Set(key(i), []byte(strconv.Itoa(100))) 95 require.NoError(t, err) 96 } 97 require.NoError(t, txn.Commit()) 98 txn.Discard() 99 100 var done uint64 101 go func() { 102 // Keep checking balance variant 103 for atomic.LoadUint64(&done) == 0 { 104 txn := db.NewTransaction(false) 105 totalBalance := 0 106 for i := 0; i < 40; i++ { 107 item, err := txn.Get(key(i)) 108 require.NoError(t, err) 109 val, err := item.Value() 110 require.NoError(t, err) 111 bal, err := strconv.Atoi(string(val)) 112 require.NoError(t, err) 113 totalBalance += bal 114 } 115 require.Equal(t, totalBalance, 4000) 116 txn.Discard() 117 } 118 }() 119 120 var wg sync.WaitGroup 121 wg.Add(100) 122 for i := 0; i < 100; i++ { 123 go func() { 124 txn := db.NewTransaction(true) 125 delta := rand.Intn(100) 126 for i := 0; i < 20; i++ { 127 err := txn.Set(key(i), []byte(strconv.Itoa(100-delta))) 128 require.NoError(t, err) 129 } 130 for i := 20; i < 40; i++ { 131 err := txn.Set(key(i), []byte(strconv.Itoa(100+delta))) 132 require.NoError(t, err) 133 } 134 // We are only doing writes, so there won't be any conflicts. 135 require.NoError(t, txn.Commit()) 136 txn.Discard() 137 wg.Done() 138 }() 139 } 140 wg.Wait() 141 atomic.StoreUint64(&done, 1) 142 time.Sleep(time.Millisecond * 10) // allow goroutine to complete. 143 }) 144 } 145 146 func TestTxnVersions(t *testing.T) { 147 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 148 k := []byte("key") 149 for i := 1; i < 10; i++ { 150 txn := db.NewTransaction(true) 151 152 txn.Set(k, []byte(fmt.Sprintf("valversion=%d", i))) 153 require.NoError(t, txn.Commit()) 154 require.Equal(t, uint64(i), db.orc.readTs()) 155 } 156 157 checkIterator := func(itr *Iterator, i int) { 158 defer itr.Close() 159 count := 0 160 for itr.Rewind(); itr.Valid(); itr.Next() { 161 item := itr.Item() 162 require.Equal(t, k, item.Key()) 163 164 val, err := item.Value() 165 require.NoError(t, err) 166 exp := fmt.Sprintf("valversion=%d", i) 167 require.Equal(t, exp, string(val), "i=%d", i) 168 count++ 169 } 170 require.Equal(t, 1, count, "i=%d", i) // Should only loop once. 171 } 172 173 checkAllVersions := func(itr *Iterator, i int) { 174 version := uint64(i) 175 176 count := 0 177 for itr.Rewind(); itr.Valid(); itr.Next() { 178 item := itr.Item() 179 require.Equal(t, k, item.Key()) 180 require.Equal(t, version, item.Version()) 181 182 val, err := item.Value() 183 require.NoError(t, err) 184 exp := fmt.Sprintf("valversion=%d", version) 185 require.Equal(t, exp, string(val), "v=%d", version) 186 count++ 187 version-- 188 } 189 require.Equal(t, i, count, "i=%d", i) // Should loop as many times as i. 190 } 191 192 for i := 1; i < 10; i++ { 193 txn := db.NewTransaction(true) 194 txn.readTs = uint64(i) // Read version at i. 195 196 item, err := txn.Get(k) 197 require.NoError(t, err) 198 199 val, err := item.Value() 200 require.NoError(t, err) 201 require.Equal(t, []byte(fmt.Sprintf("valversion=%d", i)), val, 202 "Expected versions to match up at i=%d", i) 203 204 // Try retrieving the latest version forward and reverse. 205 itr := txn.NewIterator(DefaultIteratorOptions) 206 checkIterator(itr, i) 207 208 opt := DefaultIteratorOptions 209 opt.Reverse = true 210 itr = txn.NewIterator(opt) 211 checkIterator(itr, i) 212 213 // Now try retrieving all versions forward and reverse. 214 opt = DefaultIteratorOptions 215 opt.AllVersions = true 216 itr = txn.NewIterator(opt) 217 checkAllVersions(itr, i) 218 itr.Close() 219 220 opt = DefaultIteratorOptions 221 opt.AllVersions = true 222 opt.Reverse = true 223 itr = txn.NewIterator(opt) 224 checkAllVersions(itr, i) 225 itr.Close() 226 227 txn.Discard() 228 } 229 txn := db.NewTransaction(true) 230 defer txn.Discard() 231 item, err := txn.Get(k) 232 require.NoError(t, err) 233 234 val, err := item.Value() 235 require.NoError(t, err) 236 require.Equal(t, []byte("valversion=9"), val) 237 }) 238 } 239 240 func TestTxnWriteSkew(t *testing.T) { 241 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 242 // Accounts 243 ax := []byte("x") 244 ay := []byte("y") 245 246 // Set balance to $100 in each account. 247 txn := db.NewTransaction(true) 248 defer txn.Discard() 249 val := []byte(strconv.Itoa(100)) 250 txn.Set(ax, val) 251 txn.Set(ay, val) 252 require.NoError(t, txn.Commit()) 253 require.Equal(t, uint64(1), db.orc.readTs()) 254 255 getBal := func(txn *Txn, key []byte) (bal int) { 256 item, err := txn.Get(key) 257 require.NoError(t, err) 258 259 val, err := item.Value() 260 require.NoError(t, err) 261 bal, err = strconv.Atoi(string(val)) 262 require.NoError(t, err) 263 return bal 264 } 265 266 // Start two transactions, each would read both accounts and deduct from one account. 267 txn1 := db.NewTransaction(true) 268 269 sum := getBal(txn1, ax) 270 sum += getBal(txn1, ay) 271 require.Equal(t, 200, sum) 272 txn1.Set(ax, []byte("0")) // Deduct 100 from ax. 273 274 // Let's read this back. 275 sum = getBal(txn1, ax) 276 require.Equal(t, 0, sum) 277 sum += getBal(txn1, ay) 278 require.Equal(t, 100, sum) 279 // Don't commit yet. 280 281 txn2 := db.NewTransaction(true) 282 283 sum = getBal(txn2, ax) 284 sum += getBal(txn2, ay) 285 require.Equal(t, 200, sum) 286 txn2.Set(ay, []byte("0")) // Deduct 100 from ay. 287 288 // Let's read this back. 289 sum = getBal(txn2, ax) 290 require.Equal(t, 100, sum) 291 sum += getBal(txn2, ay) 292 require.Equal(t, 100, sum) 293 294 // Commit both now. 295 require.NoError(t, txn1.Commit()) 296 require.Error(t, txn2.Commit()) // This should fail. 297 298 require.Equal(t, uint64(2), db.orc.readTs()) 299 }) 300 } 301 302 // a3, a2, b4 (del), b3, c2, c1 303 // Read at ts=4 -> a3, c2 304 // Read at ts=4(Uncomitted) -> a3, b4 305 // Read at ts=3 -> a3, b3, c2 306 // Read at ts=2 -> a2, c2 307 // Read at ts=1 -> c1 308 func TestTxnIterationEdgeCase(t *testing.T) { 309 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 310 ka := []byte("a") 311 kb := []byte("b") 312 kc := []byte("c") 313 314 // c1 315 txn := db.NewTransaction(true) 316 txn.Set(kc, []byte("c1")) 317 require.NoError(t, txn.Commit()) 318 require.Equal(t, uint64(1), db.orc.readTs()) 319 320 // a2, c2 321 txn = db.NewTransaction(true) 322 txn.Set(ka, []byte("a2")) 323 txn.Set(kc, []byte("c2")) 324 require.NoError(t, txn.Commit()) 325 require.Equal(t, uint64(2), db.orc.readTs()) 326 327 // b3 328 txn = db.NewTransaction(true) 329 txn.Set(ka, []byte("a3")) 330 txn.Set(kb, []byte("b3")) 331 require.NoError(t, txn.Commit()) 332 require.Equal(t, uint64(3), db.orc.readTs()) 333 334 // b4, c4(del) (Uncomitted) 335 txn4 := db.NewTransaction(true) 336 require.NoError(t, txn4.Set(kb, []byte("b4"))) 337 require.NoError(t, txn4.Delete(kc)) 338 require.Equal(t, uint64(3), db.orc.readTs()) 339 340 // b4 (del) 341 txn = db.NewTransaction(true) 342 txn.Delete(kb) 343 require.NoError(t, txn.Commit()) 344 require.Equal(t, uint64(4), db.orc.readTs()) 345 346 checkIterator := func(itr *Iterator, expected []string) { 347 defer itr.Close() 348 var i int 349 for itr.Rewind(); itr.Valid(); itr.Next() { 350 item := itr.Item() 351 val, err := item.Value() 352 require.NoError(t, err) 353 require.Equal(t, expected[i], string(val), "readts=%d", itr.readTs) 354 i++ 355 } 356 require.Equal(t, len(expected), i) 357 } 358 359 txn = db.NewTransaction(true) 360 defer txn.Discard() 361 itr := txn.NewIterator(DefaultIteratorOptions) 362 itr5 := txn4.NewIterator(DefaultIteratorOptions) 363 checkIterator(itr, []string{"a3", "c2"}) 364 checkIterator(itr5, []string{"a3", "b4"}) 365 366 rev := DefaultIteratorOptions 367 rev.Reverse = true 368 itr = txn.NewIterator(rev) 369 itr5 = txn4.NewIterator(rev) 370 checkIterator(itr, []string{"c2", "a3"}) 371 checkIterator(itr5, []string{"b4", "a3"}) 372 373 txn.readTs = 3 374 itr = txn.NewIterator(DefaultIteratorOptions) 375 checkIterator(itr, []string{"a3", "b3", "c2"}) 376 itr = txn.NewIterator(rev) 377 checkIterator(itr, []string{"c2", "b3", "a3"}) 378 379 txn.readTs = 2 380 itr = txn.NewIterator(DefaultIteratorOptions) 381 checkIterator(itr, []string{"a2", "c2"}) 382 itr = txn.NewIterator(rev) 383 checkIterator(itr, []string{"c2", "a2"}) 384 385 txn.readTs = 1 386 itr = txn.NewIterator(DefaultIteratorOptions) 387 checkIterator(itr, []string{"c1"}) 388 itr = txn.NewIterator(rev) 389 checkIterator(itr, []string{"c1"}) 390 }) 391 } 392 393 // a2, a3, b4 (del), b3, c2, c1 394 // Read at ts=4 -> a3, c2 395 // Read at ts=3 -> a3, b3, c2 396 // Read at ts=2 -> a2, c2 397 // Read at ts=1 -> c1 398 func TestTxnIterationEdgeCase2(t *testing.T) { 399 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 400 ka := []byte("a") 401 kb := []byte("aa") 402 kc := []byte("aaa") 403 404 // c1 405 txn := db.NewTransaction(true) 406 txn.Set(kc, []byte("c1")) 407 require.NoError(t, txn.Commit()) 408 require.Equal(t, uint64(1), db.orc.readTs()) 409 410 // a2, c2 411 txn = db.NewTransaction(true) 412 txn.Set(ka, []byte("a2")) 413 txn.Set(kc, []byte("c2")) 414 require.NoError(t, txn.Commit()) 415 require.Equal(t, uint64(2), db.orc.readTs()) 416 417 // b3 418 txn = db.NewTransaction(true) 419 txn.Set(ka, []byte("a3")) 420 txn.Set(kb, []byte("b3")) 421 require.NoError(t, txn.Commit()) 422 require.Equal(t, uint64(3), db.orc.readTs()) 423 424 // b4 (del) 425 txn = db.NewTransaction(true) 426 txn.Delete(kb) 427 require.NoError(t, txn.Commit()) 428 require.Equal(t, uint64(4), db.orc.readTs()) 429 430 checkIterator := func(itr *Iterator, expected []string) { 431 defer itr.Close() 432 var i int 433 for itr.Rewind(); itr.Valid(); itr.Next() { 434 item := itr.Item() 435 val, err := item.Value() 436 require.NoError(t, err) 437 require.Equal(t, expected[i], string(val), "readts=%d", itr.readTs) 438 i++ 439 } 440 require.Equal(t, len(expected), i) 441 } 442 txn = db.NewTransaction(true) 443 defer txn.Discard() 444 rev := DefaultIteratorOptions 445 rev.Reverse = true 446 447 itr := txn.NewIterator(DefaultIteratorOptions) 448 checkIterator(itr, []string{"a3", "c2"}) 449 itr = txn.NewIterator(rev) 450 checkIterator(itr, []string{"c2", "a3"}) 451 452 txn.readTs = 5 453 itr = txn.NewIterator(DefaultIteratorOptions) 454 itr.Seek(ka) 455 require.True(t, itr.Valid()) 456 require.Equal(t, itr.item.Key(), ka) 457 itr.Seek(kc) 458 require.True(t, itr.Valid()) 459 require.Equal(t, itr.item.Key(), kc) 460 itr.Close() 461 462 itr = txn.NewIterator(rev) 463 itr.Seek(ka) 464 require.True(t, itr.Valid()) 465 require.Equal(t, itr.item.Key(), ka) 466 itr.Seek(kc) 467 require.True(t, itr.Valid()) 468 require.Equal(t, itr.item.Key(), kc) 469 itr.Close() 470 471 txn.readTs = 3 472 itr = txn.NewIterator(DefaultIteratorOptions) 473 checkIterator(itr, []string{"a3", "b3", "c2"}) 474 itr = txn.NewIterator(rev) 475 checkIterator(itr, []string{"c2", "b3", "a3"}) 476 477 txn.readTs = 2 478 itr = txn.NewIterator(DefaultIteratorOptions) 479 checkIterator(itr, []string{"a2", "c2"}) 480 itr = txn.NewIterator(rev) 481 checkIterator(itr, []string{"c2", "a2"}) 482 483 txn.readTs = 1 484 itr = txn.NewIterator(DefaultIteratorOptions) 485 checkIterator(itr, []string{"c1"}) 486 itr = txn.NewIterator(rev) 487 checkIterator(itr, []string{"c1"}) 488 }) 489 } 490 491 func TestTxnIterationEdgeCase3(t *testing.T) { 492 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 493 kb := []byte("abc") 494 kc := []byte("acd") 495 kd := []byte("ade") 496 497 // c1 498 txn := db.NewTransaction(true) 499 txn.Set(kc, []byte("c1")) 500 require.NoError(t, txn.Commit()) 501 require.Equal(t, uint64(1), db.orc.readTs()) 502 503 // b2 504 txn = db.NewTransaction(true) 505 txn.Set(kb, []byte("b2")) 506 require.NoError(t, txn.Commit()) 507 require.Equal(t, uint64(2), db.orc.readTs()) 508 509 txn2 := db.NewTransaction(true) 510 require.NoError(t, txn2.Set(kd, []byte("d2"))) 511 require.NoError(t, txn2.Delete(kc)) 512 513 txn = db.NewTransaction(true) 514 defer txn.Discard() 515 rev := DefaultIteratorOptions 516 rev.Reverse = true 517 518 itr := txn.NewIterator(DefaultIteratorOptions) 519 itr.Seek([]byte("ab")) 520 require.True(t, itr.Valid()) 521 require.Equal(t, itr.item.Key(), kb) 522 itr.Seek([]byte("ac")) 523 require.True(t, itr.Valid()) 524 require.Equal(t, itr.item.Key(), kc) 525 itr.Seek(nil) 526 require.True(t, itr.Valid()) 527 require.Equal(t, itr.item.Key(), kb) 528 itr.Seek([]byte("ac")) 529 itr.Rewind() 530 itr.Seek(nil) 531 require.True(t, itr.Valid()) 532 require.Equal(t, itr.item.Key(), kb) 533 itr.Seek([]byte("ac")) 534 require.True(t, itr.Valid()) 535 require.Equal(t, itr.item.Key(), kc) 536 itr.Close() 537 538 // Keys: "abc", "ade" 539 // Read pending writes. 540 itr = txn2.NewIterator(DefaultIteratorOptions) 541 itr.Seek([]byte("ab")) 542 require.True(t, itr.Valid()) 543 require.Equal(t, itr.item.Key(), kb) 544 itr.Seek([]byte("ac")) 545 require.True(t, itr.Valid()) 546 require.Equal(t, itr.item.Key(), kd) 547 itr.Seek(nil) 548 require.True(t, itr.Valid()) 549 require.Equal(t, itr.item.Key(), kb) 550 itr.Seek([]byte("ac")) 551 itr.Rewind() 552 itr.Seek(nil) 553 require.True(t, itr.Valid()) 554 require.Equal(t, itr.item.Key(), kb) 555 itr.Seek([]byte("ad")) 556 require.True(t, itr.Valid()) 557 require.Equal(t, itr.item.Key(), kd) 558 itr.Close() 559 560 itr = txn.NewIterator(rev) 561 itr.Seek([]byte("ac")) 562 require.True(t, itr.Valid()) 563 require.Equal(t, itr.item.Key(), kb) 564 itr.Seek([]byte("ad")) 565 require.True(t, itr.Valid()) 566 require.Equal(t, itr.item.Key(), kc) 567 itr.Seek(nil) 568 require.True(t, itr.Valid()) 569 require.Equal(t, itr.item.Key(), kc) 570 itr.Seek([]byte("ac")) 571 itr.Rewind() 572 require.True(t, itr.Valid()) 573 require.Equal(t, itr.item.Key(), kc) 574 itr.Seek([]byte("ad")) 575 require.True(t, itr.Valid()) 576 require.Equal(t, itr.item.Key(), kc) 577 itr.Close() 578 579 // Keys: "abc", "ade" 580 itr = txn2.NewIterator(rev) 581 itr.Seek([]byte("ad")) 582 require.True(t, itr.Valid()) 583 require.Equal(t, itr.item.Key(), kb) 584 itr.Seek([]byte("ae")) 585 require.True(t, itr.Valid()) 586 require.Equal(t, itr.item.Key(), kd) 587 itr.Seek(nil) 588 require.True(t, itr.Valid()) 589 require.Equal(t, itr.item.Key(), kd) 590 itr.Seek([]byte("ab")) 591 itr.Rewind() 592 require.True(t, itr.Valid()) 593 require.Equal(t, itr.item.Key(), kd) 594 itr.Seek([]byte("ac")) 595 require.True(t, itr.Valid()) 596 require.Equal(t, itr.item.Key(), kb) 597 itr.Close() 598 }) 599 } 600 601 func TestIteratorAllVersionsWithDeleted(t *testing.T) { 602 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 603 // Write two keys 604 err := db.Update(func(txn *Txn) error { 605 txn.Set([]byte("answer1"), []byte("42")) 606 txn.Set([]byte("answer2"), []byte("43")) 607 return nil 608 }) 609 require.NoError(t, err) 610 611 // Delete the specific key version from underlying db directly 612 err = db.Update(func(txn *Txn) error { 613 item, err := txn.Get([]byte("answer1")) 614 require.NoError(t, err) 615 err = txn.Delete(item.KeyCopy(nil)) 616 require.NoError(t, err) 617 return err 618 }) 619 require.NoError(t, err) 620 621 opts := DefaultIteratorOptions 622 opts.AllVersions = true 623 624 // Verify that deleted shows up when AllVersions is set. 625 err = db.View(func(txn *Txn) error { 626 it := txn.NewIterator(opts) 627 defer it.Close() 628 var count int 629 for it.Rewind(); it.Valid(); it.Next() { 630 count++ 631 item := it.Item() 632 if count == 1 { 633 require.Equal(t, []byte("answer1"), item.Key()) 634 require.True(t, item.meta&bitDelete > 0) 635 } else if count == 3 { 636 require.Equal(t, []byte("answer2"), item.Key()) 637 } 638 } 639 require.Equal(t, 3, count) 640 return nil 641 }) 642 require.NoError(t, err) 643 }) 644 } 645 646 func TestIteratorAllVersionsWithDeleted2(t *testing.T) { 647 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 648 // Set and delete alternatively 649 for i := 0; i < 4; i++ { 650 err := db.Update(func(txn *Txn) error { 651 if i%2 == 0 { 652 txn.Set([]byte("key"), []byte("value")) 653 return nil 654 } 655 txn.Delete([]byte("key")) 656 return nil 657 }) 658 require.NoError(t, err) 659 } 660 661 opts := DefaultIteratorOptions 662 opts.AllVersions = true 663 664 // Verify that deleted shows up when AllVersions is set. 665 err := db.View(func(txn *Txn) error { 666 it := txn.NewIterator(opts) 667 defer it.Close() 668 var count int 669 for it.Rewind(); it.Valid(); it.Next() { 670 item := it.Item() 671 require.Equal(t, []byte("key"), item.Key()) 672 if count%2 != 0 { 673 val, err := item.Value() 674 require.NoError(t, err) 675 require.Equal(t, val, []byte("value")) 676 } else { 677 require.True(t, item.meta&bitDelete > 0) 678 } 679 count++ 680 } 681 require.Equal(t, 4, count) 682 return nil 683 }) 684 require.NoError(t, err) 685 }) 686 } 687 688 func TestManagedDB(t *testing.T) { 689 dir, err := ioutil.TempDir("", "badger") 690 require.NoError(t, err) 691 defer os.RemoveAll(dir) 692 693 opt := getTestOptions(dir) 694 kv, err := OpenManaged(opt) 695 require.NoError(t, err) 696 defer kv.Close() 697 698 key := func(i int) []byte { 699 return []byte(fmt.Sprintf("key-%02d", i)) 700 } 701 702 val := func(i int) []byte { 703 return []byte(fmt.Sprintf("val-%d", i)) 704 } 705 706 // Don't allow these APIs in ManagedDB 707 require.Panics(t, func() { kv.NewTransaction(false) }) 708 709 // Write data at t=3. 710 txn := kv.NewTransactionAt(3, true) 711 for i := 0; i <= 3; i++ { 712 require.NoError(t, txn.SetEntry(&Entry{Key: y.KeyWithTs(key(i), 3), Value: val(i)})) 713 } 714 require.NoError(t, txn.Commit()) 715 716 // Read data at t=2. 717 txn = kv.NewTransactionAt(2, false) 718 for i := 0; i <= 3; i++ { 719 _, err := txn.Get(key(i)) 720 require.Equal(t, ErrKeyNotFound, err) 721 } 722 txn.Discard() 723 724 // Read data at t=3. 725 txn = kv.NewTransactionAt(3, false) 726 for i := 0; i <= 3; i++ { 727 item, err := txn.Get(key(i)) 728 require.NoError(t, err) 729 require.Equal(t, uint64(3), item.Version()) 730 v, err := item.Value() 731 require.NoError(t, err) 732 require.Equal(t, val(i), v) 733 } 734 txn.Discard() 735 736 // Write data at t=7. 737 txn = kv.NewTransactionAt(6, true) 738 for i := 0; i <= 7; i++ { 739 _, err := txn.Get(key(i)) 740 if err == nil { 741 continue // Don't overwrite existing keys. 742 } 743 require.NoError(t, txn.SetEntry(&Entry{Key: y.KeyWithTs(key(i), 7), Value: val(i)})) 744 } 745 require.NoError(t, txn.Commit()) 746 747 // Read data at t=9. 748 txn = kv.NewTransactionAt(9, false) 749 for i := 0; i <= 9; i++ { 750 item, err := txn.Get(key(i)) 751 if i <= 7 { 752 require.NoError(t, err) 753 } else { 754 require.Equal(t, ErrKeyNotFound, err) 755 } 756 757 if i <= 3 { 758 require.Equal(t, uint64(3), item.Version()) 759 } else if i <= 7 { 760 require.Equal(t, uint64(7), item.Version()) 761 } 762 if i <= 7 { 763 v, err := item.Value() 764 require.NoError(t, err) 765 require.Equal(t, val(i), v) 766 } 767 } 768 txn.Discard() 769 } 770 771 func TestArmV7Issue311Fix(t *testing.T) { 772 dir, err := ioutil.TempDir("", "") 773 if err != nil { 774 t.Fatal(err) 775 } 776 defer os.RemoveAll(dir) 777 778 config := DefaultOptions 779 config.ValueLogFileSize = 16 << 20 780 config.LevelOneSize = 8 << 20 781 config.MaxTableSize = 2 << 20 782 config.MaxMemTableSize = 2 << 20 783 config.Dir = dir 784 config.ValueDir = dir 785 config.SyncWrites = false 786 787 db, err := Open(config) 788 if err != nil { 789 t.Fatalf("cannot open db at location %s: %v", dir, err) 790 } 791 792 err = db.View(func(txn *Txn) error { return nil }) 793 if err != nil { 794 t.Fatal(err) 795 } 796 797 err = db.Update(func(txn *Txn) error { 798 return txn.Set([]byte{0x11}, []byte{0x22}) 799 }) 800 if err != nil { 801 t.Fatal(err) 802 } 803 804 err = db.Update(func(txn *Txn) error { 805 return txn.Set([]byte{0x11}, []byte{0x22}) 806 }) 807 808 if err != nil { 809 t.Fatal(err) 810 } 811 812 if err = db.Close(); err != nil { 813 t.Fatal(err) 814 } 815 } 816 817 func TestTxnMultiGet(t *testing.T) { 818 runBadgerTest(t, nil, func(t *testing.T, db *DB) { 819 txn := db.NewTransaction(true) 820 keys := make([][]byte, 10) 821 vals := make([][]byte, 10) 822 for i := 0; i < 10; i++ { 823 k := []byte(fmt.Sprintf("key=%d", i)) 824 keys[i] = k 825 v := []byte(fmt.Sprintf("val=%d", i)) 826 vals[i] = v 827 require.NoError(t, txn.Set(k, v)) 828 } 829 require.NoError(t, txn.Commit()) 830 831 txn = db.NewTransaction(false) 832 items, err := txn.MultiGet(keys) 833 require.NoError(t, err) 834 for i, item := range items { 835 val, err := item.Value() 836 require.NoError(t, err) 837 require.Equal(t, vals[i], val) 838 } 839 txn.Discard() 840 841 txn = db.NewTransaction(true) 842 for _, k := range keys[:5] { 843 require.NoError(t, txn.Delete(k)) 844 } 845 require.NoError(t, txn.Commit()) 846 847 txn = db.NewTransaction(false) 848 items, err = txn.MultiGet(keys) 849 require.NoError(t, err) 850 for i, item := range items { 851 if i < 5 { 852 require.Nil(t, item) 853 } else { 854 val, err := item.Value() 855 require.NoError(t, err) 856 require.Equal(t, vals[i], val) 857 } 858 } 859 txn.Discard() 860 }) 861 } 862 863 func TestMangedDB(t *testing.T) { 864 dir, err := ioutil.TempDir("", "badger") 865 require.NoError(t, err) 866 defer os.RemoveAll(dir) 867 opts := getTestOptions(dir) 868 opts.ManagedTxns = true 869 db, err := Open(opts) 870 require.NoError(t, err) 871 defer db.Close() 872 k := []byte("k") 873 k2 := []byte("k2") 874 err = db.Update(func(txn *Txn) error { 875 err1 := txn.Set([]byte("l"), []byte("b")) 876 // A managed DB cannot set key with zero version. 877 require.NotNil(t, err1) 878 e := &Entry{ 879 Key: y.KeyWithTs(k, 100), 880 Value: []byte("v1"), 881 } 882 return txn.SetEntry(e) 883 }) 884 require.Nil(t, err) 885 err = db.Update(func(txn *Txn) error { 886 require.Nil(t, txn.SetEntry(&Entry{ 887 Key: y.KeyWithTs(k, 101), 888 Value: []byte("v2"), 889 })) 890 return txn.SetEntry(&Entry{ 891 Key: y.KeyWithTs(k2, 100), 892 Value: []byte("v2"), 893 }) 894 }) 895 require.Nil(t, err) 896 err = db.Update(func(txn *Txn) error { 897 e := &Entry{ 898 Key: y.KeyWithTs(k, 103), 899 } 900 e.SetDelete() 901 return txn.SetEntry(e) 902 }) 903 require.Nil(t, err) 904 905 err = db.View(func(txn *Txn) error { 906 require.Equal(t, txn.readTs, uint64(math.MaxUint64)) 907 item, _ := txn.Get(k) 908 require.Nil(t, item) 909 txn.SetReadTS(102) 910 item, _ = txn.Get(k) 911 require.NotNil(t, item) 912 require.Equal(t, item.Version(), uint64(101)) 913 txn.SetReadTS(100) 914 item, _ = txn.Get(k) 915 require.NotNil(t, item) 916 require.Equal(t, item.Version(), uint64(100)) 917 txn.SetReadTS(99) 918 item, _ = txn.Get(k) 919 require.Nil(t, item) 920 921 txn.SetReadTS(102) 922 items, _ := txn.MultiGet([][]byte{k, k2}) 923 require.Len(t, items, 2) 924 require.Equal(t, items[0].Version(), uint64(101)) 925 require.Equal(t, items[1].Version(), uint64(100)) 926 return nil 927 }) 928 require.Nil(t, err) 929 }