mirror of https://github.com/ledisdb/ledisdb.git
add global lock to handle replication
This commit is contained in:
parent
93491791d5
commit
2b106981ba
|
@ -11,7 +11,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +27,8 @@ timestamp(bigendian uint32, seconds)|PayloadLen(bigendian uint32)|PayloadData|Lo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type BinLogConfig struct {
|
type BinLogConfig struct {
|
||||||
|
BaseName string `json:"base_name"`
|
||||||
|
IndexName string `json:"index_name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
MaxFileSize int `json:"max_file_size"`
|
MaxFileSize int `json:"max_file_size"`
|
||||||
MaxFileNum int `json:"max_file_num"`
|
MaxFileNum int `json:"max_file_num"`
|
||||||
|
@ -45,11 +46,16 @@ func (cfg *BinLogConfig) adjust() {
|
||||||
} else if cfg.MaxFileNum > MaxBinLogFileNum {
|
} else if cfg.MaxFileNum > MaxBinLogFileNum {
|
||||||
cfg.MaxFileNum = MaxBinLogFileNum
|
cfg.MaxFileNum = MaxBinLogFileNum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(cfg.BaseName) == 0 {
|
||||||
|
cfg.BaseName = "ledis"
|
||||||
|
}
|
||||||
|
if len(cfg.IndexName) == 0 {
|
||||||
|
cfg.IndexName = "ledis"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type BinLog struct {
|
type BinLog struct {
|
||||||
sync.Mutex
|
|
||||||
|
|
||||||
cfg *BinLogConfig
|
cfg *BinLogConfig
|
||||||
|
|
||||||
logFile *os.File
|
logFile *os.File
|
||||||
|
@ -132,7 +138,7 @@ func (b *BinLog) flushIndex() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BinLog) loadIndex() error {
|
func (b *BinLog) loadIndex() error {
|
||||||
b.indexName = path.Join(b.cfg.Path, BinLogIndexFile)
|
b.indexName = path.Join(b.cfg.Path, fmt.Sprintf("%s-bin.index", b.cfg.IndexName))
|
||||||
fd, err := os.OpenFile(b.indexName, os.O_CREATE|os.O_RDWR, 0666)
|
fd, err := os.OpenFile(b.indexName, os.O_CREATE|os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -187,7 +193,7 @@ func (b *BinLog) loadIndex() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BinLog) getLogName() string {
|
func (b *BinLog) getLogName() string {
|
||||||
return fmt.Sprintf("%s.%05d", BinLogBaseName, b.lastLogIndex)
|
return fmt.Sprintf("%s-bin.%05d", b.cfg.BaseName, b.lastLogIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BinLog) openNewLogFile() error {
|
func (b *BinLog) openNewLogFile() error {
|
||||||
|
@ -241,14 +247,14 @@ func (b *BinLog) openLogFile() error {
|
||||||
func (b *BinLog) Log(args ...[]byte) error {
|
func (b *BinLog) Log(args ...[]byte) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for _, data := range args {
|
|
||||||
createTime := uint32(time.Now().Unix())
|
|
||||||
payLoadLen := len(data)
|
|
||||||
|
|
||||||
if err = b.openLogFile(); err != nil {
|
if err = b.openLogFile(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, data := range args {
|
||||||
|
createTime := uint32(time.Now().Unix())
|
||||||
|
payLoadLen := len(data)
|
||||||
|
|
||||||
binary.Write(b.logWb, binary.BigEndian, createTime)
|
binary.Write(b.logWb, binary.BigEndian, createTime)
|
||||||
binary.Write(b.logWb, binary.BigEndian, payLoadLen)
|
binary.Write(b.logWb, binary.BigEndian, payLoadLen)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ledis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
func encodeBinLogDelete(key []byte) []byte {
|
||||||
|
buf := make([]byte, 3+len(key))
|
||||||
|
buf[0] = BinLogTypeDeletion
|
||||||
|
pos := 1
|
||||||
|
binary.BigEndian.PutUint16(buf[pos:], uint16(len(key)))
|
||||||
|
pos += 2
|
||||||
|
copy(buf[pos:], key)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBinLogPut(key []byte, value []byte) []byte {
|
||||||
|
buf := make([]byte, 7+len(key)+len(value))
|
||||||
|
buf[0] = BinLogTypePut
|
||||||
|
pos := 1
|
||||||
|
binary.BigEndian.PutUint16(buf[pos:], uint16(len(key)))
|
||||||
|
pos += 2
|
||||||
|
copy(buf[pos:], key)
|
||||||
|
pos += len(key)
|
||||||
|
binary.BigEndian.PutUint32(buf[pos:], uint32(len(value)))
|
||||||
|
pos += 4
|
||||||
|
copy(buf[pos:], value)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeBinLogCommand(commandType uint8, args []byte) []byte {
|
||||||
|
//to do
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -43,9 +43,6 @@ var (
|
||||||
ErrZSetMemberSize = errors.New("invalid zset member size")
|
ErrZSetMemberSize = errors.New("invalid zset member size")
|
||||||
)
|
)
|
||||||
|
|
||||||
const BinLogBaseName = "ledis-bin"
|
|
||||||
const BinLogIndexFile = "ledis-bin.index"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxBinLogFileSize int = 1024 * 1024 * 1024
|
MaxBinLogFileSize int = 1024 * 1024 * 1024
|
||||||
MaxBinLogFileNum int = 10000
|
MaxBinLogFileNum int = 10000
|
||||||
|
@ -54,8 +51,8 @@ const (
|
||||||
DefaultBinLogFileNum int = 10
|
DefaultBinLogFileNum int = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
//like leveldb
|
|
||||||
const (
|
const (
|
||||||
BinLogTypeDeletion uint8 = 0x0
|
BinLogTypeDeletion uint8 = 0x0
|
||||||
BinLogTypeValue uint8 = 0x1
|
BinLogTypePut uint8 = 0x1
|
||||||
|
BinLogTypeCommand uint8 = 0x2
|
||||||
)
|
)
|
||||||
|
|
|
@ -36,11 +36,11 @@ func (l *Ledis) Dump(w io.Writer) error {
|
||||||
if l.binlog == nil {
|
if l.binlog == nil {
|
||||||
sp = l.ldb.NewSnapshot()
|
sp = l.ldb.NewSnapshot()
|
||||||
} else {
|
} else {
|
||||||
l.binlog.Lock()
|
l.Lock()
|
||||||
sp = l.ldb.NewSnapshot()
|
sp = l.ldb.NewSnapshot()
|
||||||
logFileName = l.binlog.LogFileName()
|
logFileName = l.binlog.LogFileName()
|
||||||
logPos = l.binlog.LogFilePos()
|
logPos = l.binlog.LogFilePos()
|
||||||
l.binlog.Unlock()
|
l.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
var head = DumpHead{
|
var head = DumpHead{
|
||||||
|
@ -104,6 +104,9 @@ func (l *Ledis) LoadDumpFile(path string) (*DumpHead, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Ledis) LoadDump(r io.Reader) (*DumpHead, error) {
|
func (l *Ledis) LoadDump(r io.Reader) (*DumpHead, error) {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
rb := bufio.NewReaderSize(r, 4096)
|
rb := bufio.NewReaderSize(r, 4096)
|
||||||
|
|
||||||
var headLen uint32
|
var headLen uint32
|
||||||
|
@ -150,6 +153,10 @@ func (l *Ledis) LoadDump(r io.Reader) (*DumpHead, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if l.binlog != nil {
|
||||||
|
err = l.binlog.Log(encodeBinLogPut(keyBuf.Bytes(), valueBuf.Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
keyBuf.Reset()
|
keyBuf.Reset()
|
||||||
valueBuf.Reset()
|
valueBuf.Reset()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/siddontang/go-leveldb/leveldb"
|
"github.com/siddontang/go-leveldb/leveldb"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -24,6 +25,8 @@ type DB struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ledis struct {
|
type Ledis struct {
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
cfg *Config
|
cfg *Config
|
||||||
|
|
||||||
ldb *leveldb.DB
|
ldb *leveldb.DB
|
||||||
|
|
31
ledis/tx.go
31
ledis/tx.go
|
@ -1,7 +1,6 @@
|
||||||
package ledis
|
package ledis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"github.com/siddontang/go-leveldb/leveldb"
|
"github.com/siddontang/go-leveldb/leveldb"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -9,6 +8,7 @@ import (
|
||||||
type tx struct {
|
type tx struct {
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
|
|
||||||
|
l *Ledis
|
||||||
wb *leveldb.WriteBatch
|
wb *leveldb.WriteBatch
|
||||||
|
|
||||||
binlog *BinLog
|
binlog *BinLog
|
||||||
|
@ -18,6 +18,7 @@ type tx struct {
|
||||||
func newTx(l *Ledis) *tx {
|
func newTx(l *Ledis) *tx {
|
||||||
t := new(tx)
|
t := new(tx)
|
||||||
|
|
||||||
|
t.l = l
|
||||||
t.wb = l.ldb.NewWriteBatch()
|
t.wb = l.ldb.NewWriteBatch()
|
||||||
|
|
||||||
t.batch = make([][]byte, 0, 4)
|
t.batch = make([][]byte, 0, 4)
|
||||||
|
@ -33,17 +34,7 @@ func (t *tx) Put(key []byte, value []byte) {
|
||||||
t.wb.Put(key, value)
|
t.wb.Put(key, value)
|
||||||
|
|
||||||
if t.binlog != nil {
|
if t.binlog != nil {
|
||||||
buf := make([]byte, 7+len(key)+len(value))
|
buf := encodeBinLogPut(key, value)
|
||||||
buf[0] = BinLogTypeValue
|
|
||||||
pos := 1
|
|
||||||
binary.BigEndian.PutUint16(buf[pos:], uint16(len(key)))
|
|
||||||
pos += 2
|
|
||||||
copy(buf[pos:], key)
|
|
||||||
pos += len(key)
|
|
||||||
binary.BigEndian.PutUint32(buf[pos:], uint32(len(value)))
|
|
||||||
pos += 4
|
|
||||||
copy(buf[pos:], value)
|
|
||||||
|
|
||||||
t.batch = append(t.batch, buf)
|
t.batch = append(t.batch, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,13 +43,7 @@ func (t *tx) Delete(key []byte) {
|
||||||
t.wb.Delete(key)
|
t.wb.Delete(key)
|
||||||
|
|
||||||
if t.binlog != nil {
|
if t.binlog != nil {
|
||||||
buf := make([]byte, 3+len(key))
|
buf := encodeBinLogDelete(key)
|
||||||
buf[0] = BinLogTypeDeletion
|
|
||||||
pos := 1
|
|
||||||
binary.BigEndian.PutUint16(buf[pos:], uint16(len(key)))
|
|
||||||
pos += 2
|
|
||||||
copy(buf[pos:], key)
|
|
||||||
|
|
||||||
t.batch = append(t.batch, buf)
|
t.batch = append(t.batch, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,18 +61,20 @@ func (t *tx) Unlock() {
|
||||||
func (t *tx) Commit() error {
|
func (t *tx) Commit() error {
|
||||||
var err error
|
var err error
|
||||||
if t.binlog != nil {
|
if t.binlog != nil {
|
||||||
t.binlog.Lock()
|
t.l.Lock()
|
||||||
err = t.wb.Commit()
|
err = t.wb.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.binlog.Unlock()
|
t.l.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.binlog.Log(t.batch...)
|
err = t.binlog.Log(t.batch...)
|
||||||
|
|
||||||
t.binlog.Unlock()
|
t.l.Unlock()
|
||||||
} else {
|
} else {
|
||||||
|
t.l.Lock()
|
||||||
err = t.wb.Commit()
|
err = t.wb.Commit()
|
||||||
|
t.l.Unlock()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue