| // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> |
| // All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Package opt provides sets of options used by LevelDB. |
| package opt |
| |
| import ( |
| "github.com/syndtr/goleveldb/leveldb/cache" |
| "github.com/syndtr/goleveldb/leveldb/comparer" |
| "github.com/syndtr/goleveldb/leveldb/filter" |
| "math" |
| ) |
| |
| const ( |
| KiB = 1024 |
| MiB = KiB * 1024 |
| GiB = MiB * 1024 |
| ) |
| |
| var ( |
| DefaultBlockCacher = LRUCacher |
| DefaultBlockCacheCapacity = 8 * MiB |
| DefaultBlockRestartInterval = 16 |
| DefaultBlockSize = 4 * KiB |
| DefaultCompactionExpandLimitFactor = 25 |
| DefaultCompactionGPOverlapsFactor = 10 |
| DefaultCompactionL0Trigger = 4 |
| DefaultCompactionSourceLimitFactor = 1 |
| DefaultCompactionTableSize = 2 * MiB |
| DefaultCompactionTableSizeMultiplier = 1.0 |
| DefaultCompactionTotalSize = 10 * MiB |
| DefaultCompactionTotalSizeMultiplier = 10.0 |
| DefaultCompressionType = SnappyCompression |
| DefaultIteratorSamplingRate = 1 * MiB |
| DefaultMaxMemCompationLevel = 2 |
| DefaultNumLevel = 7 |
| DefaultOpenFilesCacher = LRUCacher |
| DefaultOpenFilesCacheCapacity = 500 |
| DefaultWriteBuffer = 4 * MiB |
| DefaultWriteL0PauseTrigger = 12 |
| DefaultWriteL0SlowdownTrigger = 8 |
| ) |
| |
| // Cacher is a caching algorithm. |
| type Cacher interface { |
| New(capacity int) cache.Cacher |
| } |
| |
| type CacherFunc struct { |
| NewFunc func(capacity int) cache.Cacher |
| } |
| |
| func (f *CacherFunc) New(capacity int) cache.Cacher { |
| if f.NewFunc != nil { |
| return f.NewFunc(capacity) |
| } |
| return nil |
| } |
| |
| func noCacher(int) cache.Cacher { return nil } |
| |
| var ( |
| // LRUCacher is the LRU-cache algorithm. |
| LRUCacher = &CacherFunc{cache.NewLRU} |
| |
| // NoCacher is the value to disable caching algorithm. |
| NoCacher = &CacherFunc{} |
| ) |
| |
| // Compression is the 'sorted table' block compression algorithm to use. |
| type Compression uint |
| |
| func (c Compression) String() string { |
| switch c { |
| case DefaultCompression: |
| return "default" |
| case NoCompression: |
| return "none" |
| case SnappyCompression: |
| return "snappy" |
| } |
| return "invalid" |
| } |
| |
| const ( |
| DefaultCompression Compression = iota |
| NoCompression |
| SnappyCompression |
| nCompression |
| ) |
| |
| // Strict is the DB 'strict level'. |
| type Strict uint |
| |
| const ( |
| // If present then a corrupted or invalid chunk or block in manifest |
| // journal will cause an error instead of being dropped. |
| // This will prevent database with corrupted manifest to be opened. |
| StrictManifest Strict = 1 << iota |
| |
| // If present then journal chunk checksum will be verified. |
| StrictJournalChecksum |
| |
| // If present then a corrupted or invalid chunk or block in journal |
| // will cause an error instead of being dropped. |
| // This will prevent database with corrupted journal to be opened. |
| StrictJournal |
| |
| // If present then 'sorted table' block checksum will be verified. |
| // This has effect on both 'read operation' and compaction. |
| StrictBlockChecksum |
| |
| // If present then a corrupted 'sorted table' will fails compaction. |
| // The database will enter read-only mode. |
| StrictCompaction |
| |
| // If present then a corrupted 'sorted table' will halts 'read operation'. |
| StrictReader |
| |
| // If present then leveldb.Recover will drop corrupted 'sorted table'. |
| StrictRecovery |
| |
| // This only applicable for ReadOptions, if present then this ReadOptions |
| // 'strict level' will override global ones. |
| StrictOverride |
| |
| // StrictAll enables all strict flags. |
| StrictAll = StrictManifest | StrictJournalChecksum | StrictJournal | StrictBlockChecksum | StrictCompaction | StrictReader | StrictRecovery |
| |
| // DefaultStrict is the default strict flags. Specify any strict flags |
| // will override default strict flags as whole (i.e. not OR'ed). |
| DefaultStrict = StrictJournalChecksum | StrictBlockChecksum | StrictCompaction | StrictReader |
| |
| // NoStrict disables all strict flags. Override default strict flags. |
| NoStrict = ^StrictAll |
| ) |
| |
| // Options holds the optional parameters for the DB at large. |
| type Options struct { |
| // AltFilters defines one or more 'alternative filters'. |
| // 'alternative filters' will be used during reads if a filter block |
| // does not match with the 'effective filter'. |
| // |
| // The default value is nil |
| AltFilters []filter.Filter |
| |
| // BlockCacher provides cache algorithm for LevelDB 'sorted table' block caching. |
| // Specify NoCacher to disable caching algorithm. |
| // |
| // The default value is LRUCacher. |
| BlockCacher Cacher |
| |
| // BlockCacheCapacity defines the capacity of the 'sorted table' block caching. |
| // Use -1 for zero, this has same effect as specifying NoCacher to BlockCacher. |
| // |
| // The default value is 8MiB. |
| BlockCacheCapacity int |
| |
| // BlockRestartInterval is the number of keys between restart points for |
| // delta encoding of keys. |
| // |
| // The default value is 16. |
| BlockRestartInterval int |
| |
| // BlockSize is the minimum uncompressed size in bytes of each 'sorted table' |
| // block. |
| // |
| // The default value is 4KiB. |
| BlockSize int |
| |
| // CompactionExpandLimitFactor limits compaction size after expanded. |
| // This will be multiplied by table size limit at compaction target level. |
| // |
| // The default value is 25. |
| CompactionExpandLimitFactor int |
| |
| // CompactionGPOverlapsFactor limits overlaps in grandparent (Level + 2) that a |
| // single 'sorted table' generates. |
| // This will be multiplied by table size limit at grandparent level. |
| // |
| // The default value is 10. |
| CompactionGPOverlapsFactor int |
| |
| // CompactionL0Trigger defines number of 'sorted table' at level-0 that will |
| // trigger compaction. |
| // |
| // The default value is 4. |
| CompactionL0Trigger int |
| |
| // CompactionSourceLimitFactor limits compaction source size. This doesn't apply to |
| // level-0. |
| // This will be multiplied by table size limit at compaction target level. |
| // |
| // The default value is 1. |
| CompactionSourceLimitFactor int |
| |
| // CompactionTableSize limits size of 'sorted table' that compaction generates. |
| // The limits for each level will be calculated as: |
| // CompactionTableSize * (CompactionTableSizeMultiplier ^ Level) |
| // The multiplier for each level can also fine-tuned using CompactionTableSizeMultiplierPerLevel. |
| // |
| // The default value is 2MiB. |
| CompactionTableSize int |
| |
| // CompactionTableSizeMultiplier defines multiplier for CompactionTableSize. |
| // |
| // The default value is 1. |
| CompactionTableSizeMultiplier float64 |
| |
| // CompactionTableSizeMultiplierPerLevel defines per-level multiplier for |
| // CompactionTableSize. |
| // Use zero to skip a level. |
| // |
| // The default value is nil. |
| CompactionTableSizeMultiplierPerLevel []float64 |
| |
| // CompactionTotalSize limits total size of 'sorted table' for each level. |
| // The limits for each level will be calculated as: |
| // CompactionTotalSize * (CompactionTotalSizeMultiplier ^ Level) |
| // The multiplier for each level can also fine-tuned using |
| // CompactionTotalSizeMultiplierPerLevel. |
| // |
| // The default value is 10MiB. |
| CompactionTotalSize int |
| |
| // CompactionTotalSizeMultiplier defines multiplier for CompactionTotalSize. |
| // |
| // The default value is 10. |
| CompactionTotalSizeMultiplier float64 |
| |
| // CompactionTotalSizeMultiplierPerLevel defines per-level multiplier for |
| // CompactionTotalSize. |
| // Use zero to skip a level. |
| // |
| // The default value is nil. |
| CompactionTotalSizeMultiplierPerLevel []float64 |
| |
| // Comparer defines a total ordering over the space of []byte keys: a 'less |
| // than' relationship. The same comparison algorithm must be used for reads |
| // and writes over the lifetime of the DB. |
| // |
| // The default value uses the same ordering as bytes.Compare. |
| Comparer comparer.Comparer |
| |
| // Compression defines the 'sorted table' block compression to use. |
| // |
| // The default value (DefaultCompression) uses snappy compression. |
| Compression Compression |
| |
| // DisableBufferPool allows disable use of util.BufferPool functionality. |
| // |
| // The default value is false. |
| DisableBufferPool bool |
| |
| // DisableBlockCache allows disable use of cache.Cache functionality on |
| // 'sorted table' block. |
| // |
| // The default value is false. |
| DisableBlockCache bool |
| |
| // DisableCompactionBackoff allows disable compaction retry backoff. |
| // |
| // The default value is false. |
| DisableCompactionBackoff bool |
| |
| // ErrorIfExist defines whether an error should returned if the DB already |
| // exist. |
| // |
| // The default value is false. |
| ErrorIfExist bool |
| |
| // ErrorIfMissing defines whether an error should returned if the DB is |
| // missing. If false then the database will be created if missing, otherwise |
| // an error will be returned. |
| // |
| // The default value is false. |
| ErrorIfMissing bool |
| |
| // Filter defines an 'effective filter' to use. An 'effective filter' |
| // if defined will be used to generate per-table filter block. |
| // The filter name will be stored on disk. |
| // During reads LevelDB will try to find matching filter from |
| // 'effective filter' and 'alternative filters'. |
| // |
| // Filter can be changed after a DB has been created. It is recommended |
| // to put old filter to the 'alternative filters' to mitigate lack of |
| // filter during transition period. |
| // |
| // A filter is used to reduce disk reads when looking for a specific key. |
| // |
| // The default value is nil. |
| Filter filter.Filter |
| |
| // IteratorSamplingRate defines approximate gap (in bytes) between read |
| // sampling of an iterator. The samples will be used to determine when |
| // compaction should be triggered. |
| // |
| // The default is 1MiB. |
| IteratorSamplingRate int |
| |
| // MaxMemCompationLevel defines maximum level a newly compacted 'memdb' |
| // will be pushed into if doesn't creates overlap. This should less than |
| // NumLevel. Use -1 for level-0. |
| // |
| // The default is 2. |
| MaxMemCompationLevel int |
| |
| // NumLevel defines number of database level. The level shouldn't changed |
| // between opens, or the database will panic. |
| // |
| // The default is 7. |
| NumLevel int |
| |
| // OpenFilesCacher provides cache algorithm for open files caching. |
| // Specify NoCacher to disable caching algorithm. |
| // |
| // The default value is LRUCacher. |
| OpenFilesCacher Cacher |
| |
| // OpenFilesCacheCapacity defines the capacity of the open files caching. |
| // Use -1 for zero, this has same effect as specifying NoCacher to OpenFilesCacher. |
| // |
| // The default value is 500. |
| OpenFilesCacheCapacity int |
| |
| // If true then opens DB in read-only mode. |
| // |
| // The default value is false. |
| ReadOnly bool |
| |
| // Strict defines the DB strict level. |
| Strict Strict |
| |
| // WriteBuffer defines maximum size of a 'memdb' before flushed to |
| // 'sorted table'. 'memdb' is an in-memory DB backed by an on-disk |
| // unsorted journal. |
| // |
| // LevelDB may held up to two 'memdb' at the same time. |
| // |
| // The default value is 4MiB. |
| WriteBuffer int |
| |
| // WriteL0StopTrigger defines number of 'sorted table' at level-0 that will |
| // pause write. |
| // |
| // The default value is 12. |
| WriteL0PauseTrigger int |
| |
| // WriteL0SlowdownTrigger defines number of 'sorted table' at level-0 that |
| // will trigger write slowdown. |
| // |
| // The default value is 8. |
| WriteL0SlowdownTrigger int |
| } |
| |
| func (o *Options) GetAltFilters() []filter.Filter { |
| if o == nil { |
| return nil |
| } |
| return o.AltFilters |
| } |
| |
| func (o *Options) GetBlockCacher() Cacher { |
| if o == nil || o.BlockCacher == nil { |
| return DefaultBlockCacher |
| } else if o.BlockCacher == NoCacher { |
| return nil |
| } |
| return o.BlockCacher |
| } |
| |
| func (o *Options) GetBlockCacheCapacity() int { |
| if o == nil || o.BlockCacheCapacity == 0 { |
| return DefaultBlockCacheCapacity |
| } else if o.BlockCacheCapacity < 0 { |
| return 0 |
| } |
| return o.BlockCacheCapacity |
| } |
| |
| func (o *Options) GetBlockRestartInterval() int { |
| if o == nil || o.BlockRestartInterval <= 0 { |
| return DefaultBlockRestartInterval |
| } |
| return o.BlockRestartInterval |
| } |
| |
| func (o *Options) GetBlockSize() int { |
| if o == nil || o.BlockSize <= 0 { |
| return DefaultBlockSize |
| } |
| return o.BlockSize |
| } |
| |
| func (o *Options) GetCompactionExpandLimit(level int) int { |
| factor := DefaultCompactionExpandLimitFactor |
| if o != nil && o.CompactionExpandLimitFactor > 0 { |
| factor = o.CompactionExpandLimitFactor |
| } |
| return o.GetCompactionTableSize(level+1) * factor |
| } |
| |
| func (o *Options) GetCompactionGPOverlaps(level int) int { |
| factor := DefaultCompactionGPOverlapsFactor |
| if o != nil && o.CompactionGPOverlapsFactor > 0 { |
| factor = o.CompactionGPOverlapsFactor |
| } |
| return o.GetCompactionTableSize(level+2) * factor |
| } |
| |
| func (o *Options) GetCompactionL0Trigger() int { |
| if o == nil || o.CompactionL0Trigger == 0 { |
| return DefaultCompactionL0Trigger |
| } |
| return o.CompactionL0Trigger |
| } |
| |
| func (o *Options) GetCompactionSourceLimit(level int) int { |
| factor := DefaultCompactionSourceLimitFactor |
| if o != nil && o.CompactionSourceLimitFactor > 0 { |
| factor = o.CompactionSourceLimitFactor |
| } |
| return o.GetCompactionTableSize(level+1) * factor |
| } |
| |
| func (o *Options) GetCompactionTableSize(level int) int { |
| var ( |
| base = DefaultCompactionTableSize |
| mult float64 |
| ) |
| if o != nil { |
| if o.CompactionTableSize > 0 { |
| base = o.CompactionTableSize |
| } |
| if len(o.CompactionTableSizeMultiplierPerLevel) > level && o.CompactionTableSizeMultiplierPerLevel[level] > 0 { |
| mult = o.CompactionTableSizeMultiplierPerLevel[level] |
| } else if o.CompactionTableSizeMultiplier > 0 { |
| mult = math.Pow(o.CompactionTableSizeMultiplier, float64(level)) |
| } |
| } |
| if mult == 0 { |
| mult = math.Pow(DefaultCompactionTableSizeMultiplier, float64(level)) |
| } |
| return int(float64(base) * mult) |
| } |
| |
| func (o *Options) GetCompactionTotalSize(level int) int64 { |
| var ( |
| base = DefaultCompactionTotalSize |
| mult float64 |
| ) |
| if o != nil { |
| if o.CompactionTotalSize > 0 { |
| base = o.CompactionTotalSize |
| } |
| if len(o.CompactionTotalSizeMultiplierPerLevel) > level && o.CompactionTotalSizeMultiplierPerLevel[level] > 0 { |
| mult = o.CompactionTotalSizeMultiplierPerLevel[level] |
| } else if o.CompactionTotalSizeMultiplier > 0 { |
| mult = math.Pow(o.CompactionTotalSizeMultiplier, float64(level)) |
| } |
| } |
| if mult == 0 { |
| mult = math.Pow(DefaultCompactionTotalSizeMultiplier, float64(level)) |
| } |
| return int64(float64(base) * mult) |
| } |
| |
| func (o *Options) GetComparer() comparer.Comparer { |
| if o == nil || o.Comparer == nil { |
| return comparer.DefaultComparer |
| } |
| return o.Comparer |
| } |
| |
| func (o *Options) GetCompression() Compression { |
| if o == nil || o.Compression <= DefaultCompression || o.Compression >= nCompression { |
| return DefaultCompressionType |
| } |
| return o.Compression |
| } |
| |
| func (o *Options) GetDisableBufferPool() bool { |
| if o == nil { |
| return false |
| } |
| return o.DisableBufferPool |
| } |
| |
| func (o *Options) GetDisableBlockCache() bool { |
| if o == nil { |
| return false |
| } |
| return o.DisableBlockCache |
| } |
| |
| func (o *Options) GetDisableCompactionBackoff() bool { |
| if o == nil { |
| return false |
| } |
| return o.DisableCompactionBackoff |
| } |
| |
| func (o *Options) GetErrorIfExist() bool { |
| if o == nil { |
| return false |
| } |
| return o.ErrorIfExist |
| } |
| |
| func (o *Options) GetErrorIfMissing() bool { |
| if o == nil { |
| return false |
| } |
| return o.ErrorIfMissing |
| } |
| |
| func (o *Options) GetFilter() filter.Filter { |
| if o == nil { |
| return nil |
| } |
| return o.Filter |
| } |
| |
| func (o *Options) GetIteratorSamplingRate() int { |
| if o == nil || o.IteratorSamplingRate <= 0 { |
| return DefaultIteratorSamplingRate |
| } |
| return o.IteratorSamplingRate |
| } |
| |
| func (o *Options) GetMaxMemCompationLevel() int { |
| level := DefaultMaxMemCompationLevel |
| if o != nil { |
| if o.MaxMemCompationLevel > 0 { |
| level = o.MaxMemCompationLevel |
| } else if o.MaxMemCompationLevel < 0 { |
| level = 0 |
| } |
| } |
| if level >= o.GetNumLevel() { |
| return o.GetNumLevel() - 1 |
| } |
| return level |
| } |
| |
| func (o *Options) GetNumLevel() int { |
| if o == nil || o.NumLevel <= 0 { |
| return DefaultNumLevel |
| } |
| return o.NumLevel |
| } |
| |
| func (o *Options) GetOpenFilesCacher() Cacher { |
| if o == nil || o.OpenFilesCacher == nil { |
| return DefaultOpenFilesCacher |
| } |
| if o.OpenFilesCacher == NoCacher { |
| return nil |
| } |
| return o.OpenFilesCacher |
| } |
| |
| func (o *Options) GetOpenFilesCacheCapacity() int { |
| if o == nil || o.OpenFilesCacheCapacity == 0 { |
| return DefaultOpenFilesCacheCapacity |
| } else if o.OpenFilesCacheCapacity < 0 { |
| return 0 |
| } |
| return o.OpenFilesCacheCapacity |
| } |
| |
| func (o *Options) GetReadOnly() bool { |
| if o == nil { |
| return false |
| } |
| return o.ReadOnly |
| } |
| |
| func (o *Options) GetStrict(strict Strict) bool { |
| if o == nil || o.Strict == 0 { |
| return DefaultStrict&strict != 0 |
| } |
| return o.Strict&strict != 0 |
| } |
| |
| func (o *Options) GetWriteBuffer() int { |
| if o == nil || o.WriteBuffer <= 0 { |
| return DefaultWriteBuffer |
| } |
| return o.WriteBuffer |
| } |
| |
| func (o *Options) GetWriteL0PauseTrigger() int { |
| if o == nil || o.WriteL0PauseTrigger == 0 { |
| return DefaultWriteL0PauseTrigger |
| } |
| return o.WriteL0PauseTrigger |
| } |
| |
| func (o *Options) GetWriteL0SlowdownTrigger() int { |
| if o == nil || o.WriteL0SlowdownTrigger == 0 { |
| return DefaultWriteL0SlowdownTrigger |
| } |
| return o.WriteL0SlowdownTrigger |
| } |
| |
| // ReadOptions holds the optional parameters for 'read operation'. The |
| // 'read operation' includes Get, Find and NewIterator. |
| type ReadOptions struct { |
| // DontFillCache defines whether block reads for this 'read operation' |
| // should be cached. If false then the block will be cached. This does |
| // not affects already cached block. |
| // |
| // The default value is false. |
| DontFillCache bool |
| |
| // Strict will be OR'ed with global DB 'strict level' unless StrictOverride |
| // is present. Currently only StrictReader that has effect here. |
| Strict Strict |
| } |
| |
| func (ro *ReadOptions) GetDontFillCache() bool { |
| if ro == nil { |
| return false |
| } |
| return ro.DontFillCache |
| } |
| |
| func (ro *ReadOptions) GetStrict(strict Strict) bool { |
| if ro == nil { |
| return false |
| } |
| return ro.Strict&strict != 0 |
| } |
| |
| // WriteOptions holds the optional parameters for 'write operation'. The |
| // 'write operation' includes Write, Put and Delete. |
| type WriteOptions struct { |
| // Sync is whether to sync underlying writes from the OS buffer cache |
| // through to actual disk, if applicable. Setting Sync can result in |
| // slower writes. |
| // |
| // If false, and the machine crashes, then some recent writes may be lost. |
| // Note that if it is just the process that crashes (and the machine does |
| // not) then no writes will be lost. |
| // |
| // In other words, Sync being false has the same semantics as a write |
| // system call. Sync being true means write followed by fsync. |
| // |
| // The default value is false. |
| Sync bool |
| } |
| |
| func (wo *WriteOptions) GetSync() bool { |
| if wo == nil { |
| return false |
| } |
| return wo.Sync |
| } |
| |
| func GetStrict(o *Options, ro *ReadOptions, strict Strict) bool { |
| if ro.GetStrict(StrictOverride) { |
| return ro.GetStrict(strict) |
| } else { |
| return o.GetStrict(strict) || ro.GetStrict(strict) |
| } |
| } |