Add DB.NoGrowSync flag.

This commit adds the DB.NoGrowSync flag to optionally revert mmap()
calls to how they were implemented before the ext3/ext4 fix. When
NoGrowSync is true, remapping the data file will not force the file
system to resize it immediately. This works for non-ext3/4 file
systems.

The default value of NoGrowSync is false so it is still safe for
ext3/ext4 file systems by default.

See also: https://github.com/boltdb/bolt/issues/284
master
Ben Johnson 2015-05-04 14:10:25 -06:00
parent 550b8c7cb6
commit b107b35f19
2 changed files with 21 additions and 6 deletions

View File

@ -44,11 +44,13 @@ func funlock(f *os.File) error {
func mmap(db *DB, sz int) error { func mmap(db *DB, sz int) error {
// Truncate and fsync to ensure file size metadata is flushed. // Truncate and fsync to ensure file size metadata is flushed.
// https://github.com/boltdb/bolt/issues/284 // https://github.com/boltdb/bolt/issues/284
if err := db.file.Truncate(int64(sz)); err != nil { if !db.NoGrowSync {
return fmt.Errorf("file resize error: %s", err) if err := db.file.Truncate(int64(sz)); err != nil {
} return fmt.Errorf("file resize error: %s", err)
if err := db.file.Sync(); err != nil { }
return fmt.Errorf("file sync error: %s", err) if err := db.file.Sync(); err != nil {
return fmt.Errorf("file sync error: %s", err)
}
} }
// Map the data file to memory. // Map the data file to memory.

15
db.go
View File

@ -55,6 +55,14 @@ type DB struct {
// THIS IS UNSAFE. PLEASE USE WITH CAUTION. // THIS IS UNSAFE. PLEASE USE WITH CAUTION.
NoSync bool NoSync bool
// When true, skips the truncate call when growing the database.
// Setting this to true is only safe on non-ext3/ext4 systems.
// Skipping truncation avoids preallocation of hard drive space and
// bypasses a truncate() and fsync() syscall on remapping.
//
// https://github.com/boltdb/bolt/issues/284
NoGrowSync bool
// MaxBatchSize is the maximum size of a batch. Default value is // MaxBatchSize is the maximum size of a batch. Default value is
// copied from DefaultMaxBatchSize in Open. // copied from DefaultMaxBatchSize in Open.
// //
@ -123,6 +131,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
if options == nil { if options == nil {
options = DefaultOptions options = DefaultOptions
} }
db.NoGrowSync = options.NoGrowSync
// Set default values for later DB operations. // Set default values for later DB operations.
db.MaxBatchSize = DefaultMaxBatchSize db.MaxBatchSize = DefaultMaxBatchSize
@ -613,12 +622,16 @@ type Options struct {
// When set to zero it will wait indefinitely. This option is only // When set to zero it will wait indefinitely. This option is only
// available on Darwin and Linux. // available on Darwin and Linux.
Timeout time.Duration Timeout time.Duration
// Sets the DB.NoGrowSync flag before memory mapping the file.
NoGrowSync bool
} }
// DefaultOptions represent the options used if nil options are passed into Open(). // DefaultOptions represent the options used if nil options are passed into Open().
// No timeout is used which will cause Bolt to wait indefinitely for a lock. // No timeout is used which will cause Bolt to wait indefinitely for a lock.
var DefaultOptions = &Options{ var DefaultOptions = &Options{
Timeout: 0, Timeout: 0,
NoGrowSync: false,
} }
// Stats represents statistics about the database. // Stats represents statistics about the database.