aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dedo.go97
1 files changed, 54 insertions, 43 deletions
diff --git a/src/dedo.go b/src/dedo.go
index 8e37154..416d575 100644
--- a/src/dedo.go
+++ b/src/dedo.go
@@ -96,6 +96,10 @@ type elemRef struct {
index int
}
+type dbops struct {
+ writeAt func(b []byte, off int64) (n int, err error)
+}
+
// DB represents a collection of buckets persisted to a file on disk.
// All data access is performed through transactions which can be obtained through the DB.
// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
@@ -153,9 +157,7 @@ type DB struct {
mmaplock sync.RWMutex // Protects mmap access during remapping.
statlock sync.RWMutex // Protects stats access.
- ops struct {
- writeAt func(b []byte, off int64) (n int, err error)
- }
+ ops dbops
}
type call struct {
@@ -1726,6 +1728,19 @@ func (db *DB) String() string {
return fmt.Sprintf("DB<%q>", db.path)
}
+func newDB(path string, file *os.File) *DB {
+ db := &DB{
+ MaxBatchSize: DefaultMaxBatchSize,
+ MaxBatchDelay: DefaultMaxBatchDelay,
+ AllocSize: DefaultAllocSize,
+ opened: true,
+ path: path,
+ file: file,
+ ops: dbops{file.WriteAt},
+ }
+ return db
+}
+
func openFile(path string) (*os.File, error) {
const (
fileMode = 0o666
@@ -1749,23 +1764,18 @@ func openFile(path string) (*os.File, error) {
// If the file does not exist then it will be created automatically.
// Passing in nil options will cause Bolt to open the database with the default options.
func Open(path string) (*DB, error) {
- var db = &DB{
- opened: true,
- path: path,
+ file, err := openFile(path)
+ if err != nil {
+ return nil, err
}
- // Set default values for later DB operations.
- db.MaxBatchSize = DefaultMaxBatchSize
- db.MaxBatchDelay = DefaultMaxBatchDelay
- db.AllocSize = DefaultAllocSize
-
- file, err := openFile(path)
+ info, err := file.Stat()
if err != nil {
- _ = db.close()
+ file.Close()
return nil, err
}
- db.file = file
+ db := newDB(path, file)
// Lock file so that other processes using Bolt in read-write mode cannot
// use the database at the same time. This would cause corruption since
// the two processes would write meta pages and free pages separately.
@@ -1778,35 +1788,9 @@ func Open(path string) (*DB, error) {
return nil, err
}
- // Default values for test hooks
- db.ops.writeAt = db.file.WriteAt
-
- // Initialize the database if it doesn't exist.
- if info, err := db.file.Stat(); err != nil {
+ err = initDB(db, info.Size())
+ if err != nil {
return nil, err
- } else if info.Size() == 0 {
- // Initialize new files with meta pages.
- if err := db.init(); err != nil {
- return nil, err
- }
- } else {
- // Read the first meta page to determine the page size.
- var buf [0x1000]byte
- if _, err := db.file.ReadAt(buf[:], 0); err == nil {
- m := db.pageInBuffer(buf[:], 0).meta()
- if err := m.validate(); err != nil {
- // If we can't read the page size, we can assume it's the same
- // as the OS -- since that's how the page size was chosen in the
- // first place.
- //
- // If the first page is invalid and this OS uses a different
- // page size than what the database was created with then we
- // are out of luck and cannot access the database.
- db.pageSize = os.Getpagesize()
- } else {
- db.pageSize = int(m.pageSize)
- }
- }
}
// Initialize page pool.
@@ -1929,8 +1913,35 @@ func (db *DB) mmapSize(size int) (int, error) {
return int(sz), nil
}
+func readPageSize(db *DB) (int, error) {
+ // Read the first meta page to determine the page size.
+ var buf [0x1000]byte
+ _, err := db.file.ReadAt(buf[:], 0)
+ if err != nil {
+ return 0, err
+ }
+
+ m := db.pageInBuffer(buf[:], 0).meta()
+ err = m.validate()
+ if err != nil {
+ // return 0, err
+ return os.Getpagesize(), nil
+ }
+
+ return int(m.pageSize), nil
+}
+
// init creates a new database file and initializes its meta pages.
-func (db *DB) init() error {
+func initDB(db *DB, size int64) error {
+ if size != 0 {
+ pageSize, err := readPageSize(db)
+ if err != nil {
+ return err
+ }
+
+ db.pageSize = pageSize
+ return nil
+ }
// Set the page size to the OS page size.
db.pageSize = os.Getpagesize()