ledisdb/ledis/dump.go

212 lines
3.7 KiB
Go
Raw Normal View History

2014-05-28 10:20:45 +04:00
package ledis
import (
"bufio"
"bytes"
"encoding/binary"
"io"
"os"
2015-05-04 17:42:28 +03:00
2020-04-24 09:10:03 +03:00
"github.com/ledisdb/ledisdb/store"
2015-05-04 17:42:28 +03:00
"github.com/siddontang/go/snappy"
2014-05-28 10:20:45 +04:00
)
2018-03-29 15:33:36 +03:00
// DumpHead is the head of a dump.
2014-09-22 13:50:51 +04:00
type DumpHead struct {
CommitID uint64
2014-06-09 13:23:32 +04:00
}
2018-03-29 15:33:36 +03:00
// Read reads meta from the Reader.
2014-09-22 13:50:51 +04:00
func (h *DumpHead) Read(r io.Reader) error {
2018-03-29 15:33:36 +03:00
return binary.Read(r, binary.BigEndian, &h.CommitID)
2014-06-09 13:23:32 +04:00
}
2018-03-29 15:33:36 +03:00
// Write writes meta to the Writer
2014-09-22 13:50:51 +04:00
func (h *DumpHead) Write(w io.Writer) error {
2018-03-29 15:33:36 +03:00
return binary.Write(w, binary.BigEndian, h.CommitID)
2014-05-28 10:20:45 +04:00
}
2018-03-29 15:33:36 +03:00
// DumpFile dumps data to the file
2014-05-28 10:20:45 +04:00
func (l *Ledis) DumpFile(path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
return l.Dump(f)
}
2018-03-29 15:33:36 +03:00
// Dump dumps data to the Writer.
2014-05-28 10:20:45 +04:00
func (l *Ledis) Dump(w io.Writer) error {
2014-08-30 13:39:44 +04:00
var err error
2014-09-22 13:50:51 +04:00
var commitID uint64
var snap *store.Snapshot
2014-10-11 06:31:34 +04:00
l.wLock.Lock()
2014-07-25 13:58:00 +04:00
2014-10-11 06:31:34 +04:00
if l.r != nil {
if commitID, err = l.r.LastCommitID(); err != nil {
l.wLock.Unlock()
2014-09-22 13:50:51 +04:00
return err
}
2014-05-28 10:20:45 +04:00
}
2014-10-11 06:31:34 +04:00
if snap, err = l.ldb.NewSnapshot(); err != nil {
l.wLock.Unlock()
return err
}
defer snap.Close()
2014-10-11 06:31:34 +04:00
l.wLock.Unlock()
2014-05-28 10:20:45 +04:00
wb := bufio.NewWriterSize(w, 4096)
2014-09-22 13:50:51 +04:00
h := &DumpHead{commitID}
if err = h.Write(wb); err != nil {
2014-05-28 10:20:45 +04:00
return err
}
2014-09-22 13:50:51 +04:00
it := snap.NewIterator()
defer it.Close()
2014-06-19 13:19:40 +04:00
it.SeekToFirst()
2014-07-04 13:55:47 +04:00
compressBuf := make([]byte, 4096)
2014-05-28 10:20:45 +04:00
var key []byte
var value []byte
for ; it.Valid(); it.Next() {
2014-09-01 04:34:03 +04:00
key = it.RawKey()
value = it.RawValue()
2014-05-28 10:20:45 +04:00
2014-07-04 13:55:47 +04:00
if key, err = snappy.Encode(compressBuf, key); err != nil {
return err
}
2014-05-28 10:20:45 +04:00
if err = binary.Write(wb, binary.BigEndian, uint16(len(key))); err != nil {
return err
}
if _, err = wb.Write(key); err != nil {
return err
}
2014-07-04 13:55:47 +04:00
if value, err = snappy.Encode(compressBuf, value); err != nil {
return err
}
2014-05-28 10:20:45 +04:00
if err = binary.Write(wb, binary.BigEndian, uint32(len(value))); err != nil {
return err
}
if _, err = wb.Write(value); err != nil {
return err
}
}
return wb.Flush()
2014-05-28 10:20:45 +04:00
}
2018-03-29 15:33:36 +03:00
// LoadDumpFile clears all data and loads dump file to db
2014-09-22 13:50:51 +04:00
func (l *Ledis) LoadDumpFile(path string) (*DumpHead, error) {
2014-05-28 10:20:45 +04:00
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return l.LoadDump(f)
}
2018-03-29 15:33:36 +03:00
// LoadDump clears all data and loads dump file to db
2014-09-22 13:50:51 +04:00
func (l *Ledis) LoadDump(r io.Reader) (*DumpHead, error) {
2014-08-30 13:39:44 +04:00
l.wLock.Lock()
defer l.wLock.Unlock()
2014-05-29 11:07:14 +04:00
2014-09-22 13:50:51 +04:00
var err error
if err = l.flushAll(); err != nil {
2014-09-22 13:50:51 +04:00
return nil, err
}
2014-06-09 13:23:32 +04:00
2014-05-28 10:20:45 +04:00
rb := bufio.NewReaderSize(r, 4096)
2014-09-22 13:50:51 +04:00
h := new(DumpHead)
if err = h.Read(rb); err != nil {
2014-05-28 10:20:45 +04:00
return nil, err
}
var keyLen uint16
var valueLen uint32
var keyBuf bytes.Buffer
var valueBuf bytes.Buffer
2014-07-04 13:55:47 +04:00
deKeyBuf := make([]byte, 4096)
deValueBuf := make([]byte, 4096)
var key, value []byte
2014-11-10 10:35:57 +03:00
wb := l.ldb.NewWriteBatch()
defer wb.Close()
n := 0
2014-05-28 10:20:45 +04:00
for {
if err = binary.Read(rb, binary.BigEndian, &keyLen); err != nil && err != io.EOF {
return nil, err
} else if err == io.EOF {
break
}
if _, err = io.CopyN(&keyBuf, rb, int64(keyLen)); err != nil {
return nil, err
}
2014-07-04 13:55:47 +04:00
if key, err = snappy.Decode(deKeyBuf, keyBuf.Bytes()); err != nil {
return nil, err
}
2014-05-28 10:20:45 +04:00
if err = binary.Read(rb, binary.BigEndian, &valueLen); err != nil {
return nil, err
}
if _, err = io.CopyN(&valueBuf, rb, int64(valueLen)); err != nil {
return nil, err
}
2014-07-04 13:55:47 +04:00
if value, err = snappy.Decode(deValueBuf, valueBuf.Bytes()); err != nil {
return nil, err
}
2014-11-10 10:35:57 +03:00
wb.Put(key, value)
n++
if n%1024 == 0 {
if err = wb.Commit(); err != nil {
return nil, err
}
2014-05-28 10:20:45 +04:00
}
2014-11-10 10:35:57 +03:00
// if err = l.ldb.Put(key, value); err != nil {
// return nil, err
// }
2014-05-28 10:20:45 +04:00
keyBuf.Reset()
valueBuf.Reset()
}
2014-11-10 10:35:57 +03:00
if err = wb.Commit(); err != nil {
return nil, err
}
2014-09-22 13:50:51 +04:00
if l.r != nil {
if err := l.r.UpdateCommitID(h.CommitID); err != nil {
return nil, err
}
2014-08-30 13:39:44 +04:00
}
2014-09-22 13:50:51 +04:00
return h, nil
2014-05-28 10:20:45 +04:00
}