diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dedo.go | 97 |
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() |