aboutsummaryrefslogtreecommitdiff
path: root/db.go
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-05-05 07:56:54 -0600
committerBen Johnson <benbjohnson@yahoo.com>2014-05-05 07:56:54 -0600
commitc3903d38a10fda3c9a366d62705e06ddc558eb2d (patch)
tree504e0dcfc35536f7f9023aca59895c653bf68bee /db.go
parentMerge pull request #152 from benbjohnson/remove-bolt-set (diff)
downloaddedo-c3903d38a10fda3c9a366d62705e06ddc558eb2d.tar.gz
dedo-c3903d38a10fda3c9a366d62705e06ddc558eb2d.tar.xz
Consolidate code for clarity.
This commit consolidates some of the smaller files into some of the larger files. The smaller files cluttered the file tree and made it harder to see the logical groupings of structs.
Diffstat (limited to 'db.go')
-rw-r--r--db.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/db.go b/db.go
index 7e8dd7f..9754f21 100644
--- a/db.go
+++ b/db.go
@@ -3,6 +3,7 @@ package bolt
import (
"errors"
"fmt"
+ "hash/fnv"
"io"
"os"
"sync"
@@ -16,6 +17,12 @@ const minMmapSize = 1 << 22 // 4MB
// The largest step that can be taken when remapping the mmap.
const maxMmapStep = 1 << 30 // 1GB
+// The data file format version.
+const version = 2
+
+// Represents a marker value to indicate that a file is a Bolt DB.
+const magic uint32 = 0xED0CDAED
+
var (
// ErrDatabaseNotOpen is returned when a DB instance is accessed before it
// is opened or after it is closed.
@@ -24,6 +31,16 @@ var (
// ErrDatabaseOpen is returned when opening a database that is
// already open.
ErrDatabaseOpen = errors.New("database already open")
+
+ // ErrInvalid is returned when a data file is not a Bolt-formatted database.
+ ErrInvalid = errors.New("invalid database")
+
+ // ErrVersionMismatch is returned when the data file was created with a
+ // different version of Bolt.
+ ErrVersionMismatch = errors.New("version mismatch")
+
+ // ErrChecksum is returned when either meta page checksum does not match.
+ ErrChecksum = errors.New("checksum error")
)
// DB represents a collection of buckets persisted to a file on disk.
@@ -652,3 +669,74 @@ type Info struct {
Data []byte
PageSize int
}
+
+type meta struct {
+ magic uint32
+ version uint32
+ pageSize uint32
+ flags uint32
+ root bucket
+ freelist pgid
+ pgid pgid
+ txid txid
+ checksum uint64
+}
+
+// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
+func (m *meta) validate() error {
+ if m.checksum != 0 && m.checksum != m.sum64() {
+ return ErrChecksum
+ } else if m.magic != magic {
+ return ErrInvalid
+ } else if m.version != version {
+ return ErrVersionMismatch
+ }
+ return nil
+}
+
+// copy copies one meta object to another.
+func (m *meta) copy(dest *meta) {
+ *dest = *m
+}
+
+// write writes the meta onto a page.
+func (m *meta) write(p *page) {
+ // Page id is either going to be 0 or 1 which we can determine by the transaction ID.
+ p.id = pgid(m.txid % 2)
+ p.flags |= metaPageFlag
+
+ // Calculate the checksum.
+ m.checksum = m.sum64()
+
+ m.copy(p.meta())
+}
+
+// generates the checksum for the meta.
+func (m *meta) sum64() uint64 {
+ var h = fnv.New64a()
+ _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
+ return h.Sum64()
+}
+
+// ErrorList represents a slice of errors.
+type ErrorList []error
+
+// Error returns a readable count of the errors in the list.
+func (l ErrorList) Error() string {
+ return fmt.Sprintf("%d errors occurred", len(l))
+}
+
+// _assert will panic with a given formatted message if the given condition is false.
+func _assert(condition bool, msg string, v ...interface{}) {
+ if !condition {
+ panic(fmt.Sprintf("assertion failed: "+msg, v...))
+ }
+}
+
+func warn(v ...interface{}) {
+ fmt.Fprintln(os.Stderr, v...)
+}
+
+func warnf(msg string, v ...interface{}) {
+ fmt.Fprintf(os.Stderr, msg+"\n", v...)
+}