ledisdb/ledis/event.go

223 lines
4.8 KiB
Go
Raw Normal View History

2014-05-29 11:07:14 +04:00
package ledis
import (
2014-09-17 13:54:04 +04:00
"bytes"
2014-05-29 11:07:14 +04:00
"encoding/binary"
2014-06-04 10:42:02 +04:00
"errors"
2014-07-11 09:28:34 +04:00
"fmt"
2014-09-17 13:54:04 +04:00
"io"
2014-07-11 09:28:34 +04:00
"strconv"
2014-06-04 10:42:02 +04:00
)
2014-09-17 13:54:04 +04:00
const (
kTypeDeleteEvent uint8 = 0
kTypePutEvent uint8 = 1
)
2014-06-04 10:42:02 +04:00
var (
2014-09-17 13:54:04 +04:00
errInvalidPutEvent = errors.New("invalid put event")
errInvalidDeleteEvent = errors.New("invalid delete event")
errInvalidEvent = errors.New("invalid event")
2014-05-29 11:07:14 +04:00
)
2014-09-17 13:54:04 +04:00
type eventBatch struct {
bytes.Buffer
2014-05-29 11:07:14 +04:00
}
2014-09-17 13:54:04 +04:00
func (b *eventBatch) Put(key []byte, value []byte) {
l := uint32(len(key) + len(value) + 1 + 2)
binary.Write(b, binary.BigEndian, l)
b.WriteByte(kTypePutEvent)
keyLen := uint16(len(key))
binary.Write(b, binary.BigEndian, keyLen)
b.Write(key)
b.Write(value)
2014-06-04 10:42:02 +04:00
}
2014-09-17 13:54:04 +04:00
func (b *eventBatch) Delete(key []byte) {
l := uint32(len(key) + 1)
binary.Write(b, binary.BigEndian, l)
b.WriteByte(kTypeDeleteEvent)
b.Write(key)
2014-05-29 11:07:14 +04:00
}
2014-09-22 13:50:51 +04:00
type eventWriter interface {
Put(key []byte, value []byte)
Delete(key []byte)
2014-06-04 10:42:02 +04:00
}
2014-09-22 13:50:51 +04:00
func decodeEventBatch(w eventWriter, data []byte) error {
2014-09-17 13:54:04 +04:00
for {
if len(data) == 0 {
2014-09-22 13:50:51 +04:00
return nil
2014-09-17 13:54:04 +04:00
}
2014-07-11 09:28:34 +04:00
2014-09-17 13:54:04 +04:00
if len(data) < 4 {
2014-09-22 13:50:51 +04:00
return io.ErrUnexpectedEOF
2014-09-17 13:54:04 +04:00
}
2014-07-11 09:28:34 +04:00
2014-09-17 13:54:04 +04:00
l := binary.BigEndian.Uint32(data)
data = data[4:]
if uint32(len(data)) < l {
2014-09-22 13:50:51 +04:00
return io.ErrUnexpectedEOF
2014-09-17 13:54:04 +04:00
}
2014-07-11 09:28:34 +04:00
2014-09-22 13:50:51 +04:00
if err := decodeEvent(w, data[0:l]); err != nil {
return err
2014-09-17 13:54:04 +04:00
}
data = data[l:]
2014-07-11 09:28:34 +04:00
}
2014-09-17 13:54:04 +04:00
}
2014-07-11 09:28:34 +04:00
2014-09-22 13:50:51 +04:00
func decodeEvent(w eventWriter, b []byte) error {
2014-09-17 13:54:04 +04:00
if len(b) == 0 {
return errInvalidEvent
2014-07-11 09:28:34 +04:00
}
2014-09-17 13:54:04 +04:00
switch b[0] {
case kTypePutEvent:
if len(b[1:]) < 2 {
return errInvalidPutEvent
}
2014-07-11 09:28:34 +04:00
2014-09-17 13:54:04 +04:00
keyLen := binary.BigEndian.Uint16(b[1:3])
b = b[3:]
if len(b) < int(keyLen) {
return errInvalidPutEvent
}
2014-07-11 09:28:34 +04:00
2014-09-22 13:50:51 +04:00
w.Put(b[0:keyLen], b[keyLen:])
2014-09-17 13:54:04 +04:00
case kTypeDeleteEvent:
2014-09-22 13:50:51 +04:00
w.Delete(b[1:])
2014-09-17 13:54:04 +04:00
default:
return errInvalidEvent
2014-07-11 09:28:34 +04:00
}
2014-09-17 13:54:04 +04:00
return nil
2014-07-11 09:28:34 +04:00
}
2014-09-17 13:54:04 +04:00
func formatEventKey(buf []byte, k []byte) ([]byte, error) {
2014-07-11 09:28:34 +04:00
if len(k) < 2 {
2014-09-17 13:54:04 +04:00
return nil, errInvalidEvent
2014-07-11 09:28:34 +04:00
}
buf = append(buf, fmt.Sprintf("DB:%2d ", k[0])...)
buf = append(buf, fmt.Sprintf("%s ", TypeName[k[1]])...)
db := new(DB)
db.index = k[0]
//to do format at respective place
switch k[1] {
case KVType:
if key, err := db.decodeKVKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
case HashType:
if key, field, err := db.hDecodeHashKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(field))
}
case HSizeType:
if key, err := db.hDecodeSizeKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
case ListType:
if key, seq, err := db.lDecodeListKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendInt(buf, int64(seq), 10)
}
case LMetaType:
if key, err := db.lDecodeMetaKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
case ZSetType:
if key, m, err := db.zDecodeSetKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(m))
}
case ZSizeType:
if key, err := db.zDecodeSizeKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
case ZScoreType:
if key, m, score, err := db.zDecodeScoreKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(m))
buf = append(buf, ' ')
buf = strconv.AppendInt(buf, score, 10)
}
case BitType:
if key, seq, err := db.bDecodeBinKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendUint(buf, uint64(seq), 10)
}
case BitMetaType:
if key, err := db.bDecodeMetaKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
2014-08-25 10:18:23 +04:00
case SetType:
if key, member, err := db.sDecodeSetKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(member))
}
case SSizeType:
if key, err := db.sDecodeSizeKey(k); err != nil {
return nil, err
} else {
buf = strconv.AppendQuote(buf, String(key))
}
2014-07-11 09:28:34 +04:00
case ExpTimeType:
if tp, key, t, err := db.expDecodeTimeKey(k); err != nil {
return nil, err
} else {
buf = append(buf, TypeName[tp]...)
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(key))
buf = append(buf, ' ')
buf = strconv.AppendInt(buf, t, 10)
}
case ExpMetaType:
if tp, key, err := db.expDecodeMetaKey(k); err != nil {
return nil, err
} else {
buf = append(buf, TypeName[tp]...)
buf = append(buf, ' ')
buf = strconv.AppendQuote(buf, String(key))
}
default:
2014-09-17 13:54:04 +04:00
return nil, errInvalidEvent
2014-07-11 09:28:34 +04:00
}
return buf, nil
}