diff options
Diffstat (limited to 'tx.go')
-rw-r--r-- | tx.go | 56 |
1 files changed, 56 insertions, 0 deletions
@@ -3,6 +3,8 @@ package bolt import ( "errors" "fmt" + "io" + "os" "sort" "time" "unsafe" @@ -71,6 +73,11 @@ func (tx *Tx) DB() *DB { return tx.db } +// Size returns current database size in bytes as seen by this transaction. +func (tx *Tx) Size() int64 { + return int64(tx.meta.pgid) * int64(tx.db.pageSize) +} + // Writable returns whether the transaction can perform write operations. func (tx *Tx) Writable() bool { return tx.writable @@ -227,6 +234,55 @@ func (tx *Tx) close() { tx.db = nil } +// Copy writes the entire database to a writer. +// A reader transaction is maintained during the copy so it is safe to continue +// using the database while a copy is in progress. +// Copy will write exactly tx.Size() bytes into the writer. +func (tx *Tx) Copy(w io.Writer) error { + // Open reader on the database. + f, err := os.Open(tx.db.path) + if err != nil { + _ = tx.Rollback() + return err + } + + // Copy the meta pages. + tx.db.metalock.Lock() + _, err = io.CopyN(w, f, int64(tx.db.pageSize*2)) + tx.db.metalock.Unlock() + if err != nil { + _ = tx.Rollback() + _ = f.Close() + return fmt.Errorf("meta copy: %s", err) + } + + // Copy data pages. + if _, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2)); err != nil { + _ = tx.Rollback() + _ = f.Close() + return err + } + + return f.Close() +} + +// CopyFile copies the entire database to file at the given path. +// A reader transaction is maintained during the copy so it is safe to continue +// using the database while a copy is in progress. +func (tx *Tx) CopyFile(path string, mode os.FileMode) error { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + + err = tx.Copy(f) + if err != nil { + _ = f.Close() + return err + } + return f.Close() +} + // Check performs several consistency checks on the database for this transaction. // An error is returned if any inconsistency is found or if executed on a read-only transaction. func (tx *Tx) Check() error { |