aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2016-03-10 12:42:47 -0700
committerBen Johnson <benbjohnson@yahoo.com>2016-03-10 12:42:47 -0700
commit871c8e43d807c18ca5775cccbbe6384b5d13d6a6 (patch)
tree833d3f129ba119f8e67307c6313cb6579b441823
parentMerge pull request #531 from michelmno/master (diff)
parentuse tx.meta during Tx.WriteTo() (diff)
downloaddedo-871c8e43d807c18ca5775cccbbe6384b5d13d6a6.tar.gz
dedo-871c8e43d807c18ca5775cccbbe6384b5d13d6a6.tar.xz
Merge pull request #515 from benbjohnson/meta-write-to
Use tx.meta during Tx.WriteTo()
-rw-r--r--tx.go32
-rw-r--r--tx_test.go2
2 files changed, 28 insertions, 6 deletions
diff --git a/tx.go b/tx.go
index e74d2ca..299c073 100644
--- a/tx.go
+++ b/tx.go
@@ -297,12 +297,34 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
}
defer func() { _ = f.Close() }()
- // Copy the meta pages.
- tx.db.metalock.Lock()
- n, err = io.CopyN(w, f, int64(tx.db.pageSize*2))
- tx.db.metalock.Unlock()
+ // Generate a meta page. We use the same page data for both meta pages.
+ buf := make([]byte, tx.db.pageSize)
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.flags = metaPageFlag
+ *page.meta() = *tx.meta
+
+ // Write meta 0.
+ page.id = 0
+ page.meta().checksum = page.meta().sum64()
+ nn, err := w.Write(buf)
+ n += int64(nn)
+ if err != nil {
+ return n, fmt.Errorf("meta 0 copy: %s", err)
+ }
+
+ // Write meta 1 with a lower transaction id.
+ page.id = 1
+ page.meta().txid -= 1
+ page.meta().checksum = page.meta().sum64()
+ nn, err = w.Write(buf)
+ n += int64(nn)
if err != nil {
- return n, fmt.Errorf("meta copy: %s", err)
+ return n, fmt.Errorf("meta 1 copy: %s", err)
+ }
+
+ // Move past the meta pages in the file.
+ if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil {
+ return n, fmt.Errorf("seek: %s", err)
}
// Copy data pages.
diff --git a/tx_test.go b/tx_test.go
index 18ff166..2201e79 100644
--- a/tx_test.go
+++ b/tx_test.go
@@ -570,7 +570,7 @@ func TestTx_CopyFile_Error_Meta(t *testing.T) {
if err := db.View(func(tx *bolt.Tx) error {
return tx.Copy(&failWriter{})
- }); err == nil || err.Error() != "meta copy: error injected for tests" {
+ }); err == nil || err.Error() != "meta 0 copy: error injected for tests" {
t.Fatalf("unexpected error: %v", err)
}
}