diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dedo.go | 172 |
1 files changed, 83 insertions, 89 deletions
diff --git a/src/dedo.go b/src/dedo.go index 416d575..a7bc629 100644 --- a/src/dedo.go +++ b/src/dedo.go @@ -1729,16 +1729,15 @@ func (db *DB) String() string { } func newDB(path string, file *os.File) *DB { - db := &DB{ + return &DB{ MaxBatchSize: DefaultMaxBatchSize, MaxBatchDelay: DefaultMaxBatchDelay, AllocSize: DefaultAllocSize, opened: true, path: path, file: file, - ops: dbops{file.WriteAt}, + ops: dbops{writeAt: file.WriteAt}, } - return db } func openFile(path string) (*os.File, error) { @@ -1760,9 +1759,82 @@ func openFile(path string) (*os.File, error) { return os.OpenFile(path, flagsRO, fileMode) } +func readPageSize(db *DB) (int, error) { + // Read the first meta page to determine the page size. + const size4KiB = 0x1000 + buf := [0x1000]byte{} + _, err := db.file.ReadAt(buf[:], 0) + if err != nil { + return 0, err + } + + m := pageInBuffer(db, buf[:], 0).meta() + err = m.validate() + if err != nil { + return 0, err + } + + return int(m.pageSize), nil +} + +// init creates a new database file and initializes its meta pages. +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() + + // Create two meta pages on a buffer. + buf := make([]byte, db.pageSize*4) + for i := 0; i < 2; i++ { + p := pageInBuffer(db, buf[:], pgid(i)) + p.id = pgid(i) + p.flags = metaPageFlag + + // Initialize the meta page. + m := p.meta() + m.magic = magic + m.version = version + m.pageSize = uint32(db.pageSize) + m.freelist = 2 + m.root = bucket{root: 3} + m.pgid = 4 + m.txid = txid(i) + m.checksum = m.sum64() + } + + // Write an empty freelist at page 3. + p := pageInBuffer(db, buf[:], pgid(2)) + p.id = pgid(2) + p.flags = freelistPageFlag + p.count = 0 + + // Write an empty leaf page at page 4. + p = pageInBuffer(db, buf[:], pgid(3)) + p.id = pgid(3) + p.flags = leafPageFlag + p.count = 0 + + // Write the buffer to our data file. + if _, err := db.ops.writeAt(buf, 0); err != nil { + return err + } + if err := fdatasync(db); err != nil { + return err + } + + return nil +} + // Open creates and opens a database at the given path. // 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) { file, err := openFile(path) if err != nil { @@ -1776,14 +1848,9 @@ func Open(path string) (*DB, error) { } 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. - // The database file is locked exclusively (only one process can grab the lock) - // if !options.ReadOnly. - // The database file is locked using the shared lock (more than one process may - // hold a lock at the same time) otherwise (options.ReadOnly is set). - if err := flock(db); err != nil { + + err = flock(db) + if err != nil { _ = db.close() return nil, err } @@ -1801,7 +1868,8 @@ func Open(path string) (*DB, error) { } // Memory map the data file. - if err := db.mmap(0); err != nil { + err = db.mmap(0) + if err != nil { _ = db.close() return nil, err } @@ -1913,80 +1981,6 @@ 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 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() - - // Create two meta pages on a buffer. - buf := make([]byte, db.pageSize*4) - for i := 0; i < 2; i++ { - p := db.pageInBuffer(buf[:], pgid(i)) - p.id = pgid(i) - p.flags = metaPageFlag - - // Initialize the meta page. - m := p.meta() - m.magic = magic - m.version = version - m.pageSize = uint32(db.pageSize) - m.freelist = 2 - m.root = bucket{root: 3} - m.pgid = 4 - m.txid = txid(i) - m.checksum = m.sum64() - } - - // Write an empty freelist at page 3. - p := db.pageInBuffer(buf[:], pgid(2)) - p.id = pgid(2) - p.flags = freelistPageFlag - p.count = 0 - - // Write an empty leaf page at page 4. - p = db.pageInBuffer(buf[:], pgid(3)) - p.id = pgid(3) - p.flags = leafPageFlag - p.count = 0 - - // Write the buffer to our data file. - if _, err := db.ops.writeAt(buf, 0); err != nil { - return err - } - if err := fdatasync(db); err != nil { - return err - } - - return nil -} - // Close releases all database resources. // All transactions must be closed before closing the database. func (db *DB) Close() error { @@ -2356,7 +2350,7 @@ func (db *DB) page(id pgid) *page { } // pageInBuffer retrieves a page reference from a given byte array based on the current page size. -func (db *DB) pageInBuffer(b []byte, id pgid) *page { +func pageInBuffer(db *DB, b []byte, id pgid) *page { return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)])) } @@ -4003,7 +3997,7 @@ func (tx *Tx) write() error { func (tx *Tx) writeMeta() error { // Create a temporary buffer for the meta page. buf := make([]byte, tx.db.pageSize) - p := tx.db.pageInBuffer(buf, 0) + p := pageInBuffer(tx.db, buf, 0) tx.meta.write(p) // Write the meta page to file. |