allow only one shrink at a time.

This commit is contained in:
Josh Baker 2016-07-26 10:25:29 -07:00
parent 70dec49583
commit d6a4f5c635
1 changed files with 31 additions and 14 deletions

View File

@ -50,6 +50,9 @@ var (
// ErrInvalidSyncPolicy is returned for an invalid SyncPolicy value. // ErrInvalidSyncPolicy is returned for an invalid SyncPolicy value.
ErrInvalidSyncPolicy = errors.New("invalid sync policy") ErrInvalidSyncPolicy = errors.New("invalid sync policy")
// ErrShrinkInProcess is returned when a shrink operation is in-process.
ErrShrinkInProcess = errors.New("shrink is in-process")
) )
// Iterator allows callers of Ascend* or Descend* to iterate in-order // Iterator allows callers of Ascend* or Descend* to iterate in-order
@ -61,18 +64,19 @@ type Iterator func(key, val string) bool
// DB represents a collection of key-value pairs that persist on disk. // DB represents a collection of key-value pairs that persist on disk.
// Transactions are used for all forms of data access to the DB. // Transactions are used for all forms of data access to the DB.
type DB struct { type DB struct {
mu sync.RWMutex // the gatekeeper for all fields mu sync.RWMutex // the gatekeeper for all fields
file *os.File // the underlying file file *os.File // the underlying file
bufw *bufio.Writer // only write to this bufw *bufio.Writer // only write to this
keys *btree.BTree // a tree of all item ordered by key keys *btree.BTree // a tree of all item ordered by key
exps *btree.BTree // a tree of items ordered by expiration exps *btree.BTree // a tree of items ordered by expiration
idxs map[string]*index // the index trees. idxs map[string]*index // the index trees.
exmgr bool // indicates that expires manager is running. exmgr bool // indicates that expires manager is running.
flushes int // a count of the number of disk flushes flushes int // a count of the number of disk flushes
closed bool // set when the database has been closed closed bool // set when the database has been closed
aoflen int // the number of lines in the aof file aoflen int // the number of lines in the aof file
config Config // the database configuration config Config // the database configuration
persist bool // do we write to disk persist bool // do we write to disk
shrinking bool // when an aof shrink is in-process.
} }
// SyncPolicy represents how often data is synced to disk. // SyncPolicy represents how often data is synced to disk.
@ -107,10 +111,12 @@ type Config struct {
// disk may be up to 2x the number of items on disk. // disk may be up to 2x the number of items on disk.
// A zero value will disable auto shrinking. // A zero value will disable auto shrinking.
// A negative value or 1 are invalid. // A negative value or 1 are invalid.
// The default is value is 5. // The default is value is 50, but may change in the future.
AutoShrink int AutoShrink int
} }
const defaultAutoShrinkMultiplier = 50
// exctx is a simple b-tree context for ordering by expiration. // exctx is a simple b-tree context for ordering by expiration.
type exctx struct { type exctx struct {
db *DB db *DB
@ -125,7 +131,7 @@ func Open(path string) (*DB, error) {
db.idxs = make(map[string]*index) db.idxs = make(map[string]*index)
db.config = Config{ db.config = Config{
SyncPolicy: EverySecond, SyncPolicy: EverySecond,
AutoShrink: 5, AutoShrink: defaultAutoShrinkMultiplier,
} }
db.persist = path != ":memory:" db.persist = path != ":memory:"
if db.persist { if db.persist {
@ -501,6 +507,17 @@ func (db *DB) Shrink() error {
db.mu.Unlock() db.mu.Unlock()
return nil return nil
} }
if db.shrinking {
// The database is already in the process of shrinking.
db.mu.Unlock()
return ErrShrinkInProcess
}
db.shrinking = true
defer func() {
db.mu.Lock()
db.shrinking = false
db.mu.Unlock()
}()
fname := db.file.Name() fname := db.file.Name()
tmpname := fname + ".tmp" tmpname := fname + ".tmp"
// the endpos is used to return to the end of the file when we are // the endpos is used to return to the end of the file when we are