forked from mirror/ledisdb
refactor ledis lock and binlog
This commit is contained in:
parent
577d545486
commit
882e20a3e3
|
@ -11,6 +11,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +28,8 @@ timestamp(bigendian uint32, seconds)|PayloadLen(bigendian uint32)|PayloadData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type BinLog struct {
|
type BinLog struct {
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
path string
|
path string
|
||||||
|
|
||||||
cfg *config.BinLogConfig
|
cfg *config.BinLogConfig
|
||||||
|
@ -177,16 +180,20 @@ func (l *BinLog) checkLogFileSize() bool {
|
||||||
|
|
||||||
st, _ := l.logFile.Stat()
|
st, _ := l.logFile.Stat()
|
||||||
if st.Size() >= int64(l.cfg.MaxFileSize) {
|
if st.Size() >= int64(l.cfg.MaxFileSize) {
|
||||||
l.lastLogIndex++
|
l.closeLog()
|
||||||
|
|
||||||
l.logFile.Close()
|
|
||||||
l.logFile = nil
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *BinLog) closeLog() {
|
||||||
|
l.lastLogIndex++
|
||||||
|
|
||||||
|
l.logFile.Close()
|
||||||
|
l.logFile = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (l *BinLog) purge(n int) {
|
func (l *BinLog) purge(n int) {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
logPath := path.Join(l.path, l.logNames[i])
|
logPath := path.Join(l.path, l.logNames[i])
|
||||||
|
@ -238,6 +245,9 @@ func (l *BinLog) LogPath() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *BinLog) Purge(n int) error {
|
func (l *BinLog) Purge(n int) error {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
if len(l.logNames) == 0 {
|
if len(l.logNames) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -255,7 +265,18 @@ func (l *BinLog) Purge(n int) error {
|
||||||
return l.flushIndex()
|
return l.flushIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *BinLog) PurgeAll() error {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
l.closeLog()
|
||||||
|
return l.openNewLogFile()
|
||||||
|
}
|
||||||
|
|
||||||
func (l *BinLog) Log(args ...[]byte) error {
|
func (l *BinLog) Log(args ...[]byte) error {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if l.logFile == nil {
|
if l.logFile == nil {
|
||||||
|
|
|
@ -54,15 +54,6 @@ func decodeBinLogPut(sz []byte) ([]byte, []byte, error) {
|
||||||
return sz[3 : 3+keyLen], sz[3+keyLen:], nil
|
return sz[3 : 3+keyLen], sz[3+keyLen:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeBinLogCommand(commandType uint8, args ...[]byte) []byte {
|
|
||||||
//to do
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeBinLogCommand(sz []byte) (uint8, [][]byte, error) {
|
|
||||||
return 0, nil, errBinLogCommandType
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatBinLogEvent(event []byte) (string, error) {
|
func FormatBinLogEvent(event []byte) (string, error) {
|
||||||
logType := uint8(event[0])
|
logType := uint8(event[0])
|
||||||
|
|
||||||
|
|
|
@ -57,16 +57,17 @@ func (l *Ledis) DumpFile(path string) error {
|
||||||
|
|
||||||
func (l *Ledis) Dump(w io.Writer) error {
|
func (l *Ledis) Dump(w io.Writer) error {
|
||||||
var m *MasterInfo = new(MasterInfo)
|
var m *MasterInfo = new(MasterInfo)
|
||||||
l.Lock()
|
|
||||||
defer l.Unlock()
|
var err error
|
||||||
|
|
||||||
|
l.wLock.Lock()
|
||||||
|
defer l.wLock.Unlock()
|
||||||
|
|
||||||
if l.binlog != nil {
|
if l.binlog != nil {
|
||||||
m.LogFileIndex = l.binlog.LogFileIndex()
|
m.LogFileIndex = l.binlog.LogFileIndex()
|
||||||
m.LogPos = l.binlog.LogFilePos()
|
m.LogPos = l.binlog.LogFilePos()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
wb := bufio.NewWriterSize(w, 4096)
|
wb := bufio.NewWriterSize(w, 4096)
|
||||||
if err = m.WriteTo(wb); err != nil {
|
if err = m.WriteTo(wb); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -128,8 +129,8 @@ func (l *Ledis) LoadDumpFile(path string) (*MasterInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Ledis) LoadDump(r io.Reader) (*MasterInfo, error) {
|
func (l *Ledis) LoadDump(r io.Reader) (*MasterInfo, error) {
|
||||||
l.Lock()
|
l.wLock.Lock()
|
||||||
defer l.Unlock()
|
defer l.wLock.Unlock()
|
||||||
|
|
||||||
info := new(MasterInfo)
|
info := new(MasterInfo)
|
||||||
|
|
||||||
|
@ -182,10 +183,6 @@ func (l *Ledis) LoadDump(r io.Reader) (*MasterInfo, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.binlog != nil {
|
|
||||||
err = l.binlog.Log(encodeBinLogPut(key, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
keyBuf.Reset()
|
keyBuf.Reset()
|
||||||
valueBuf.Reset()
|
valueBuf.Reset()
|
||||||
}
|
}
|
||||||
|
@ -193,5 +190,10 @@ func (l *Ledis) LoadDump(r io.Reader) (*MasterInfo, error) {
|
||||||
deKeyBuf = nil
|
deKeyBuf = nil
|
||||||
deValueBuf = nil
|
deValueBuf = nil
|
||||||
|
|
||||||
|
//if binlog enable, we will delete all binlogs and open a new one for handling simply
|
||||||
|
if l.binlog != nil {
|
||||||
|
l.binlog.PurgeAll()
|
||||||
|
}
|
||||||
|
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Ledis struct {
|
type Ledis struct {
|
||||||
sync.Mutex
|
|
||||||
|
|
||||||
cfg *config.Config
|
cfg *config.Config
|
||||||
|
|
||||||
ldb *store.DB
|
ldb *store.DB
|
||||||
|
@ -21,11 +19,13 @@ type Ledis struct {
|
||||||
jobs *sync.WaitGroup
|
jobs *sync.WaitGroup
|
||||||
|
|
||||||
binlog *BinLog
|
binlog *BinLog
|
||||||
|
|
||||||
|
wLock sync.RWMutex //allow one write at same time
|
||||||
|
commitLock sync.Mutex //allow one write commit at same time
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(cfg *config.Config) (*Ledis, error) {
|
func Open(cfg *config.Config) (*Ledis, error) {
|
||||||
if len(cfg.DataDir) == 0 {
|
if len(cfg.DataDir) == 0 {
|
||||||
fmt.Printf("no datadir set, use default %s\n", config.DefaultDataDir)
|
|
||||||
cfg.DataDir = config.DefaultDataDir
|
cfg.DataDir = config.DefaultDataDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ func Open(cfg *config.Config) (*Ledis, error) {
|
||||||
l.ldb = ldb
|
l.ldb = ldb
|
||||||
|
|
||||||
if cfg.BinLog.MaxFileNum > 0 && cfg.BinLog.MaxFileSize > 0 {
|
if cfg.BinLog.MaxFileNum > 0 && cfg.BinLog.MaxFileSize > 0 {
|
||||||
println("binlog will be refactored later, use your own risk!!!")
|
|
||||||
l.binlog, err = NewBinLog(cfg)
|
l.binlog, err = NewBinLog(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -3,7 +3,6 @@ package ledis
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/siddontang/ledisdb/store"
|
"github.com/siddontang/ledisdb/store"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ibucket interface {
|
type ibucket interface {
|
||||||
|
@ -29,8 +28,6 @@ type DB struct {
|
||||||
|
|
||||||
bucket ibucket
|
bucket ibucket
|
||||||
|
|
||||||
dbLock *sync.RWMutex
|
|
||||||
|
|
||||||
index uint8
|
index uint8
|
||||||
|
|
||||||
kvBatch *batch
|
kvBatch *batch
|
||||||
|
@ -54,7 +51,6 @@ func (l *Ledis) newDB(index uint8) *DB {
|
||||||
|
|
||||||
d.isTx = false
|
d.isTx = false
|
||||||
d.index = index
|
d.index = index
|
||||||
d.dbLock = &sync.RWMutex{}
|
|
||||||
|
|
||||||
d.kvBatch = d.newBatch()
|
d.kvBatch = d.newBatch()
|
||||||
d.listBatch = d.newBatch()
|
d.listBatch = d.newBatch()
|
||||||
|
|
|
@ -14,8 +14,8 @@ func getTestDB() *DB {
|
||||||
f := func() {
|
f := func() {
|
||||||
cfg := new(config.Config)
|
cfg := new(config.Config)
|
||||||
cfg.DataDir = "/tmp/test_ledis"
|
cfg.DataDir = "/tmp/test_ledis"
|
||||||
cfg.BinLog.MaxFileSize = 1073741824
|
// cfg.BinLog.MaxFileSize = 1073741824
|
||||||
cfg.BinLog.MaxFileNum = 3
|
// cfg.BinLog.MaxFileNum = 3
|
||||||
|
|
||||||
os.RemoveAll(cfg.DataDir)
|
os.RemoveAll(cfg.DataDir)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/siddontang/go-log/log"
|
"github.com/siddontang/go-log/log"
|
||||||
|
"github.com/siddontang/ledisdb/store/driver"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
@ -19,7 +20,41 @@ var (
|
||||||
errInvalidBinLogFile = errors.New("invalid binlog file")
|
errInvalidBinLogFile = errors.New("invalid binlog file")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *Ledis) ReplicateEvent(event []byte) error {
|
type replBatch struct {
|
||||||
|
wb driver.IWriteBatch
|
||||||
|
events [][]byte
|
||||||
|
createTime uint32
|
||||||
|
l *Ledis
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *replBatch) Commit() error {
|
||||||
|
b.l.commitLock.Lock()
|
||||||
|
defer b.l.commitLock.Unlock()
|
||||||
|
|
||||||
|
err := b.wb.Commit()
|
||||||
|
if err != nil {
|
||||||
|
b.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.l.binlog != nil {
|
||||||
|
if err = b.l.binlog.Log(b.events...); err != nil {
|
||||||
|
b.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *replBatch) Rollback() error {
|
||||||
|
b.wb.Rollback()
|
||||||
|
b.events = [][]byte{}
|
||||||
|
b.createTime = 0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Ledis) replicateEvent(b *replBatch, event []byte) error {
|
||||||
if len(event) == 0 {
|
if len(event) == 0 {
|
||||||
return errInvalidBinLogEvent
|
return errInvalidBinLogEvent
|
||||||
}
|
}
|
||||||
|
@ -27,52 +62,42 @@ func (l *Ledis) ReplicateEvent(event []byte) error {
|
||||||
logType := uint8(event[0])
|
logType := uint8(event[0])
|
||||||
switch logType {
|
switch logType {
|
||||||
case BinLogTypePut:
|
case BinLogTypePut:
|
||||||
return l.replicatePutEvent(event)
|
return l.replicatePutEvent(b, event)
|
||||||
case BinLogTypeDeletion:
|
case BinLogTypeDeletion:
|
||||||
return l.replicateDeleteEvent(event)
|
return l.replicateDeleteEvent(b, event)
|
||||||
case BinLogTypeCommand:
|
|
||||||
return l.replicateCommandEvent(event)
|
|
||||||
default:
|
default:
|
||||||
return errInvalidBinLogEvent
|
return errInvalidBinLogEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Ledis) replicatePutEvent(event []byte) error {
|
func (l *Ledis) replicatePutEvent(b *replBatch, event []byte) error {
|
||||||
key, value, err := decodeBinLogPut(event)
|
key, value, err := decodeBinLogPut(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = l.ldb.Put(key, value); err != nil {
|
b.wb.Put(key, value)
|
||||||
return err
|
|
||||||
|
if b.l.binlog != nil {
|
||||||
|
b.events = append(b.events, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.binlog != nil {
|
return nil
|
||||||
err = l.binlog.Log(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
func (l *Ledis) replicateDeleteEvent(b *replBatch, event []byte) error {
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Ledis) replicateDeleteEvent(event []byte) error {
|
|
||||||
key, err := decodeBinLogDelete(event)
|
key, err := decodeBinLogDelete(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = l.ldb.Delete(key); err != nil {
|
b.wb.Delete(key)
|
||||||
return err
|
|
||||||
|
if b.l.binlog != nil {
|
||||||
|
b.events = append(b.events, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.binlog != nil {
|
return nil
|
||||||
err = l.binlog.Log(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Ledis) replicateCommandEvent(event []byte) error {
|
|
||||||
return errors.New("command event not supported now")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadEventFromReader(rb io.Reader, f func(createTime uint32, event []byte) error) error {
|
func ReadEventFromReader(rb io.Reader, f func(createTime uint32, event []byte) error) error {
|
||||||
|
@ -110,8 +135,23 @@ func ReadEventFromReader(rb io.Reader, f func(createTime uint32, event []byte) e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Ledis) ReplicateFromReader(rb io.Reader) error {
|
func (l *Ledis) ReplicateFromReader(rb io.Reader) error {
|
||||||
|
b := new(replBatch)
|
||||||
|
|
||||||
|
b.wb = l.ldb.NewWriteBatch()
|
||||||
|
b.l = l
|
||||||
|
|
||||||
f := func(createTime uint32, event []byte) error {
|
f := func(createTime uint32, event []byte) error {
|
||||||
err := l.ReplicateEvent(event)
|
if b.createTime == 0 {
|
||||||
|
b.createTime = createTime
|
||||||
|
} else if b.createTime != createTime {
|
||||||
|
if err := b.Commit(); err != nil {
|
||||||
|
log.Fatal("replication error %s, skip to next", err.Error())
|
||||||
|
return ErrSkipEvent
|
||||||
|
}
|
||||||
|
b.createTime = createTime
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.replicateEvent(b, event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("replication error %s, skip to next", err.Error())
|
log.Fatal("replication error %s, skip to next", err.Error())
|
||||||
return ErrSkipEvent
|
return ErrSkipEvent
|
||||||
|
@ -119,15 +159,18 @@ func (l *Ledis) ReplicateFromReader(rb io.Reader) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReadEventFromReader(rb, f)
|
err := ReadEventFromReader(rb, f)
|
||||||
|
if err != nil {
|
||||||
|
b.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return b.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Ledis) ReplicateFromData(data []byte) error {
|
func (l *Ledis) ReplicateFromData(data []byte) error {
|
||||||
rb := bytes.NewReader(data)
|
rb := bytes.NewReader(data)
|
||||||
|
|
||||||
l.Lock()
|
|
||||||
err := l.ReplicateFromReader(rb)
|
err := l.ReplicateFromReader(rb)
|
||||||
l.Unlock()
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -140,17 +183,13 @@ func (l *Ledis) ReplicateFromBinLog(filePath string) error {
|
||||||
|
|
||||||
rb := bufio.NewReaderSize(f, 4096)
|
rb := bufio.NewReaderSize(f, 4096)
|
||||||
|
|
||||||
l.Lock()
|
|
||||||
err = l.ReplicateFromReader(rb)
|
err = l.ReplicateFromReader(rb)
|
||||||
l.Unlock()
|
|
||||||
|
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxSyncEvents = 64
|
|
||||||
|
|
||||||
func (l *Ledis) ReadEventsTo(info *MasterInfo, w io.Writer) (n int, err error) {
|
func (l *Ledis) ReadEventsTo(info *MasterInfo, w io.Writer) (n int, err error) {
|
||||||
n = 0
|
n = 0
|
||||||
if l.binlog == nil {
|
if l.binlog == nil {
|
||||||
|
@ -205,8 +244,6 @@ func (l *Ledis) ReadEventsTo(info *MasterInfo, w io.Writer) (n int, err error) {
|
||||||
var createTime uint32
|
var createTime uint32
|
||||||
var dataLen uint32
|
var dataLen uint32
|
||||||
|
|
||||||
var eventsNum int = 0
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err = binary.Read(f, binary.BigEndian, &createTime); err != nil {
|
if err = binary.Read(f, binary.BigEndian, &createTime); err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
|
@ -222,13 +259,10 @@ func (l *Ledis) ReadEventsTo(info *MasterInfo, w io.Writer) (n int, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eventsNum++
|
|
||||||
if lastCreateTime == 0 {
|
if lastCreateTime == 0 {
|
||||||
lastCreateTime = createTime
|
lastCreateTime = createTime
|
||||||
} else if lastCreateTime != createTime {
|
} else if lastCreateTime != createTime {
|
||||||
return
|
return
|
||||||
} else if eventsNum > maxSyncEvents {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = binary.Read(f, binary.BigEndian, &dataLen); err != nil {
|
if err = binary.Read(f, binary.BigEndian, &dataLen); err != nil {
|
||||||
|
|
95
ledis/tx.go
95
ledis/tx.go
|
@ -24,42 +24,49 @@ type batch struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type dbBatchLocker struct {
|
type dbBatchLocker struct {
|
||||||
sync.Mutex
|
l *sync.Mutex
|
||||||
dbLock *sync.RWMutex
|
wrLock *sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *dbBatchLocker) Lock() {
|
||||||
|
l.wrLock.RLock()
|
||||||
|
l.l.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *dbBatchLocker) Unlock() {
|
||||||
|
l.l.Unlock()
|
||||||
|
l.wrLock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type txBatchLocker struct {
|
type txBatchLocker struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *txBatchLocker) Lock() {
|
func (l *txBatchLocker) Lock() {}
|
||||||
}
|
func (l *txBatchLocker) Unlock() {}
|
||||||
|
|
||||||
func (l *txBatchLocker) Unlock() {
|
func (l *Ledis) newBatch(wb store.WriteBatch, tx *Tx) *batch {
|
||||||
}
|
|
||||||
|
|
||||||
func (l *dbBatchLocker) Lock() {
|
|
||||||
l.dbLock.RLock()
|
|
||||||
l.Mutex.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *dbBatchLocker) Unlock() {
|
|
||||||
l.Mutex.Unlock()
|
|
||||||
l.dbLock.RUnlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *DB) newBatch() *batch {
|
|
||||||
b := new(batch)
|
b := new(batch)
|
||||||
|
b.l = l
|
||||||
|
b.WriteBatch = wb
|
||||||
|
|
||||||
b.WriteBatch = db.bucket.NewWriteBatch()
|
b.tx = tx
|
||||||
b.Locker = &dbBatchLocker{dbLock: db.dbLock}
|
if tx == nil {
|
||||||
b.l = db.l
|
b.Locker = &dbBatchLocker{l: &sync.Mutex{}, wrLock: &l.wLock}
|
||||||
|
} else {
|
||||||
|
b.Locker = &txBatchLocker{}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.logs = [][]byte{}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DB) newBatch() *batch {
|
||||||
|
return db.l.newBatch(db.bucket.NewWriteBatch(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *batch) Commit() error {
|
func (b *batch) Commit() error {
|
||||||
b.l.Lock()
|
b.l.commitLock.Lock()
|
||||||
defer b.l.Unlock()
|
defer b.l.commitLock.Unlock()
|
||||||
|
|
||||||
err := b.WriteBatch.Commit()
|
err := b.WriteBatch.Commit()
|
||||||
|
|
||||||
|
@ -85,7 +92,7 @@ func (b *batch) Unlock() {
|
||||||
if b.l.binlog != nil {
|
if b.l.binlog != nil {
|
||||||
b.logs = [][]byte{}
|
b.logs = [][]byte{}
|
||||||
}
|
}
|
||||||
b.Rollback()
|
b.WriteBatch.Rollback()
|
||||||
b.Locker.Unlock()
|
b.Locker.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,11 +136,10 @@ func (db *DB) Begin() (*Tx, error) {
|
||||||
tx := new(Tx)
|
tx := new(Tx)
|
||||||
|
|
||||||
tx.DB = new(DB)
|
tx.DB = new(DB)
|
||||||
tx.DB.dbLock = db.dbLock
|
|
||||||
|
|
||||||
tx.DB.dbLock.Lock()
|
|
||||||
|
|
||||||
tx.DB.l = db.l
|
tx.DB.l = db.l
|
||||||
|
|
||||||
|
tx.l.wLock.Lock()
|
||||||
|
|
||||||
tx.index = db.index
|
tx.index = db.index
|
||||||
|
|
||||||
tx.DB.sdb = db.sdb
|
tx.DB.sdb = db.sdb
|
||||||
|
@ -141,7 +147,7 @@ func (db *DB) Begin() (*Tx, error) {
|
||||||
var err error
|
var err error
|
||||||
tx.tx, err = db.sdb.Begin()
|
tx.tx, err = db.sdb.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.DB.dbLock.Unlock()
|
tx.l.wLock.Unlock()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,12 +157,12 @@ func (db *DB) Begin() (*Tx, error) {
|
||||||
|
|
||||||
tx.DB.index = db.index
|
tx.DB.index = db.index
|
||||||
|
|
||||||
tx.DB.kvBatch = tx.newBatch()
|
tx.DB.kvBatch = tx.newTxBatch()
|
||||||
tx.DB.listBatch = tx.newBatch()
|
tx.DB.listBatch = tx.newTxBatch()
|
||||||
tx.DB.hashBatch = tx.newBatch()
|
tx.DB.hashBatch = tx.newTxBatch()
|
||||||
tx.DB.zsetBatch = tx.newBatch()
|
tx.DB.zsetBatch = tx.newTxBatch()
|
||||||
tx.DB.binBatch = tx.newBatch()
|
tx.DB.binBatch = tx.newTxBatch()
|
||||||
tx.DB.setBatch = tx.newBatch()
|
tx.DB.setBatch = tx.newTxBatch()
|
||||||
|
|
||||||
return tx, nil
|
return tx, nil
|
||||||
}
|
}
|
||||||
|
@ -166,7 +172,7 @@ func (tx *Tx) Commit() error {
|
||||||
return ErrTxDone
|
return ErrTxDone
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.l.Lock()
|
tx.l.commitLock.Lock()
|
||||||
err := tx.tx.Commit()
|
err := tx.tx.Commit()
|
||||||
tx.tx = nil
|
tx.tx = nil
|
||||||
|
|
||||||
|
@ -174,9 +180,9 @@ func (tx *Tx) Commit() error {
|
||||||
tx.l.binlog.Log(tx.logs...)
|
tx.l.binlog.Log(tx.logs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.l.Unlock()
|
tx.l.commitLock.Unlock()
|
||||||
|
|
||||||
tx.DB.dbLock.Unlock()
|
tx.l.wLock.Unlock()
|
||||||
tx.DB = nil
|
tx.DB = nil
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -189,20 +195,13 @@ func (tx *Tx) Rollback() error {
|
||||||
err := tx.tx.Rollback()
|
err := tx.tx.Rollback()
|
||||||
tx.tx = nil
|
tx.tx = nil
|
||||||
|
|
||||||
tx.DB.dbLock.Unlock()
|
tx.l.wLock.Unlock()
|
||||||
tx.DB = nil
|
tx.DB = nil
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) newBatch() *batch {
|
func (tx *Tx) newTxBatch() *batch {
|
||||||
b := new(batch)
|
return tx.l.newBatch(tx.tx.NewWriteBatch(), tx)
|
||||||
|
|
||||||
b.l = tx.l
|
|
||||||
b.WriteBatch = tx.tx.NewWriteBatch()
|
|
||||||
b.Locker = &txBatchLocker{}
|
|
||||||
b.tx = tx
|
|
||||||
|
|
||||||
return b
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) Index() int {
|
func (tx *Tx) Index() int {
|
||||||
|
|
Loading…
Reference in New Issue