write writes any dirty pages to disk.
()
| 518 | |
| 519 | // write writes any dirty pages to disk. |
| 520 | func (tx *Tx) write() error { |
| 521 | // Sort pages by id. |
| 522 | lg := tx.db.Logger() |
| 523 | pages := make(common.Pages, 0, len(tx.pages)) |
| 524 | for _, p := range tx.pages { |
| 525 | pages = append(pages, p) |
| 526 | } |
| 527 | // Clear out page cache early. |
| 528 | tx.pages = make(map[common.Pgid]*common.Page) |
| 529 | sort.Sort(pages) |
| 530 | |
| 531 | // Write pages to disk in order. |
| 532 | for _, p := range pages { |
| 533 | rem := (uint64(p.Overflow()) + 1) * uint64(tx.db.pageSize) |
| 534 | offset := int64(p.Id()) * int64(tx.db.pageSize) |
| 535 | var written uintptr |
| 536 | |
| 537 | // Write out page in "max allocation" sized chunks. |
| 538 | for { |
| 539 | sz := rem |
| 540 | if sz > common.MaxAllocSize-1 { |
| 541 | sz = common.MaxAllocSize - 1 |
| 542 | } |
| 543 | buf := common.UnsafeByteSlice(unsafe.Pointer(p), written, 0, int(sz)) |
| 544 | |
| 545 | if _, err := tx.db.ops.writeAt(buf, offset); err != nil { |
| 546 | lg.Errorf("writeAt failed, offset: %d: %w", offset, err) |
| 547 | return err |
| 548 | } |
| 549 | |
| 550 | // Update statistics. |
| 551 | tx.stats.IncWrite(1) |
| 552 | |
| 553 | // Exit inner for loop if we've written all the chunks. |
| 554 | rem -= sz |
| 555 | if rem == 0 { |
| 556 | break |
| 557 | } |
| 558 | |
| 559 | // Otherwise move offset forward and move pointer to next chunk. |
| 560 | offset += int64(sz) |
| 561 | written += uintptr(sz) |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | // Ignore file sync if flag is set on DB. |
| 566 | if !tx.db.NoSync || common.IgnoreNoSync { |
| 567 | // gofail: var beforeSyncDataPages struct{} |
| 568 | if err := fdatasync(tx.db); err != nil { |
| 569 | lg.Errorf("[GOOS: %s, GOARCH: %s] fdatasync failed: %w", runtime.GOOS, runtime.GOARCH, err) |
| 570 | return err |
| 571 | } |
| 572 | } |
| 573 | |
| 574 | // Put small pages back to page pool. |
| 575 | for _, p := range pages { |
| 576 | // Ignore page sizes over 1 page. |
| 577 | // These are allocated using make() instead of the page pool. |