ledisdb/ledis/tx.go

98 lines
1.5 KiB
Go

package ledis
import (
"encoding/binary"
"github.com/siddontang/go-leveldb/leveldb"
"sync"
)
type tx struct {
m sync.Mutex
wb *leveldb.WriteBatch
binlog *BinLog
batch [][]byte
}
func newTx(l *Ledis) *tx {
t := new(tx)
t.wb = l.ldb.NewWriteBatch()
t.batch = make([][]byte, 0, 4)
t.binlog = l.binlog
return t
}
func (t *tx) Close() {
t.wb.Close()
}
func (t *tx) Put(key []byte, value []byte) {
t.wb.Put(key, value)
if t.binlog != nil {
buf := make([]byte, 9+len(key)+len(value))
buf[0] = BinLogTypeValue
pos := 1
binary.BigEndian.PutUint32(buf[pos:], uint32(len(key)))
pos += 4
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)
}
}
func (t *tx) Delete(key []byte) {
t.wb.Delete(key)
if t.binlog != nil {
buf := make([]byte, 5+len(key))
buf[0] = BinLogTypeDeletion
pos := 1
binary.BigEndian.PutUint32(buf[pos:], uint32(len(key)))
pos += 4
copy(buf[pos:], key)
t.batch = append(t.batch, buf)
}
}
func (t *tx) Lock() {
t.m.Lock()
}
func (t *tx) Unlock() {
t.batch = t.batch[0:0]
t.wb.Rollback()
t.m.Unlock()
}
func (t *tx) Commit() error {
var err error
if t.binlog != nil {
t.binlog.Lock()
err = t.wb.Commit()
if err != nil {
t.binlog.Unlock()
return err
}
err = t.binlog.Log(t.batch...)
t.binlog.Unlock()
} else {
err = t.wb.Commit()
}
return err
}
func (t *tx) Rollback() {
t.wb.Rollback()
}