ledisdb/ledis/ledis.go

163 lines
2.5 KiB
Go
Raw Normal View History

2014-05-20 04:41:24 +04:00
package ledis
import (
"fmt"
"github.com/siddontang/go-log/log"
"github.com/siddontang/ledisdb/config"
2014-07-25 13:58:00 +04:00
"github.com/siddontang/ledisdb/store"
2014-05-29 11:07:14 +04:00
"sync"
"time"
2014-05-20 04:41:24 +04:00
)
type DB struct {
2014-06-05 11:59:10 +04:00
l *Ledis
2014-07-25 13:58:00 +04:00
db *store.DB
2014-05-20 04:41:24 +04:00
index uint8
kvTx *tx
listTx *tx
hashTx *tx
zsetTx *tx
2014-06-23 16:09:05 +04:00
binTx *tx
2014-08-13 17:54:27 +04:00
setTx *tx
2014-05-20 04:41:24 +04:00
}
type Ledis struct {
2014-05-29 11:07:14 +04:00
sync.Mutex
cfg *config.Config
2014-05-20 04:41:24 +04:00
2014-07-25 13:58:00 +04:00
ldb *store.DB
2014-05-20 04:41:24 +04:00
dbs [MaxDBNumber]*DB
2014-05-27 12:05:24 +04:00
binlog *BinLog
2014-06-05 11:59:10 +04:00
quit chan struct{}
jobs *sync.WaitGroup
2014-05-20 04:41:24 +04:00
}
func Open(cfg *config.Config) (*Ledis, error) {
if len(cfg.DataDir) == 0 {
fmt.Printf("no datadir set, use default %s\n", config.DefaultDataDir)
cfg.DataDir = config.DefaultDataDir
}
ldb, err := store.Open(cfg)
2014-05-20 04:41:24 +04:00
if err != nil {
return nil, err
}
l := new(Ledis)
2014-06-05 11:59:10 +04:00
l.quit = make(chan struct{})
l.jobs = new(sync.WaitGroup)
2014-06-05 11:59:10 +04:00
2014-05-20 04:41:24 +04:00
l.ldb = ldb
if cfg.BinLog.MaxFileNum > 0 && cfg.BinLog.MaxFileSize > 0 {
2014-07-23 13:08:55 +04:00
println("binlog will be refactored later, use your own risk!!!")
l.binlog, err = NewBinLog(cfg)
2014-05-27 12:05:24 +04:00
if err != nil {
return nil, err
}
} else {
l.binlog = nil
}
2014-05-20 04:41:24 +04:00
for i := uint8(0); i < MaxDBNumber; i++ {
l.dbs[i] = newDB(l, i)
}
l.activeExpireCycle()
2014-05-20 04:41:24 +04:00
return l, nil
}
func newDB(l *Ledis, index uint8) *DB {
d := new(DB)
2014-06-05 11:59:10 +04:00
d.l = l
2014-05-20 04:41:24 +04:00
d.db = l.ldb
d.index = index
2014-05-27 12:05:24 +04:00
d.kvTx = newTx(l)
d.listTx = newTx(l)
d.hashTx = newTx(l)
d.zsetTx = newTx(l)
2014-06-23 16:09:05 +04:00
d.binTx = newTx(l)
2014-08-13 17:54:27 +04:00
d.setTx = newTx(l)
2014-05-20 04:41:24 +04:00
return d
}
func (l *Ledis) Close() {
2014-06-05 11:59:10 +04:00
close(l.quit)
l.jobs.Wait()
2014-06-05 11:59:10 +04:00
2014-05-20 04:41:24 +04:00
l.ldb.Close()
2014-06-05 11:59:10 +04:00
if l.binlog != nil {
l.binlog.Close()
l.binlog = nil
}
2014-05-20 04:41:24 +04:00
}
func (l *Ledis) Select(index int) (*DB, error) {
if index < 0 || index >= int(MaxDBNumber) {
return nil, fmt.Errorf("invalid db index %d", index)
}
return l.dbs[index], nil
}
2014-06-08 12:43:59 +04:00
func (l *Ledis) FlushAll() error {
for index, db := range l.dbs {
if _, err := db.FlushAll(); err != nil {
log.Error("flush db %d error %s", index, err.Error())
}
}
return nil
}
2014-06-10 06:41:50 +04:00
2014-07-09 05:33:44 +04:00
// very dangerous to use
2014-07-25 13:58:00 +04:00
func (l *Ledis) DataDB() *store.DB {
2014-06-10 06:41:50 +04:00
return l.ldb
}
func (l *Ledis) activeExpireCycle() {
var executors []*elimination = make([]*elimination, len(l.dbs))
for i, db := range l.dbs {
executors[i] = db.newEliminator()
}
l.jobs.Add(1)
go func() {
tick := time.NewTicker(1 * time.Second)
end := false
done := make(chan struct{})
for !end {
select {
case <-tick.C:
go func() {
for _, eli := range executors {
eli.active()
}
done <- struct{}{}
}()
<-done
case <-l.quit:
end = true
break
}
}
tick.Stop()
l.jobs.Done()
}()
}