2014-06-04 10:42:02 +04:00
|
|
|
package ledis
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2014-06-10 06:41:50 +04:00
|
|
|
"fmt"
|
2014-08-07 12:49:48 +04:00
|
|
|
"github.com/siddontang/ledisdb/config"
|
2014-07-25 13:58:00 +04:00
|
|
|
"github.com/siddontang/ledisdb/store"
|
2014-06-04 10:42:02 +04:00
|
|
|
"os"
|
2014-06-10 06:41:50 +04:00
|
|
|
"path"
|
2014-06-04 10:42:02 +04:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2014-06-10 06:41:50 +04:00
|
|
|
func checkLedisEqual(master *Ledis, slave *Ledis) error {
|
2014-07-25 13:58:00 +04:00
|
|
|
it := master.ldb.RangeLimitIterator(nil, nil, store.RangeClose, 0, -1)
|
2014-06-10 06:41:50 +04:00
|
|
|
for ; it.Valid(); it.Next() {
|
|
|
|
key := it.Key()
|
|
|
|
value := it.Value()
|
|
|
|
|
|
|
|
if v, err := slave.ldb.Get(key); err != nil {
|
|
|
|
return err
|
|
|
|
} else if !bytes.Equal(v, value) {
|
|
|
|
return fmt.Errorf("replication error %d != %d", len(v), len(value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-06-04 10:42:02 +04:00
|
|
|
func TestReplication(t *testing.T) {
|
|
|
|
var master *Ledis
|
|
|
|
var slave *Ledis
|
|
|
|
var err error
|
|
|
|
|
2014-08-07 12:49:48 +04:00
|
|
|
cfgM := new(config.Config)
|
|
|
|
cfgM.DataDir = "/tmp/test_repl/master"
|
|
|
|
|
|
|
|
cfgM.BinLog.MaxFileNum = 10
|
|
|
|
cfgM.BinLog.MaxFileSize = 50
|
|
|
|
|
|
|
|
os.RemoveAll(cfgM.DataDir)
|
|
|
|
|
|
|
|
master, err = Open(cfgM)
|
2014-06-04 10:42:02 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2014-08-07 12:49:48 +04:00
|
|
|
cfgS := new(config.Config)
|
|
|
|
cfgS.DataDir = "/tmp/test_repl/slave"
|
|
|
|
|
|
|
|
os.RemoveAll(cfgS.DataDir)
|
|
|
|
|
|
|
|
slave, err = Open(cfgS)
|
2014-06-04 10:42:02 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
db, _ := master.Select(0)
|
2014-06-10 06:41:50 +04:00
|
|
|
db.Set([]byte("a"), []byte("value"))
|
|
|
|
db.Set([]byte("b"), []byte("value"))
|
|
|
|
db.Set([]byte("c"), []byte("value"))
|
2014-06-04 10:42:02 +04:00
|
|
|
|
2014-06-10 06:41:50 +04:00
|
|
|
db.HSet([]byte("a"), []byte("1"), []byte("value"))
|
|
|
|
db.HSet([]byte("b"), []byte("2"), []byte("value"))
|
|
|
|
db.HSet([]byte("c"), []byte("3"), []byte("value"))
|
2014-06-04 10:42:02 +04:00
|
|
|
|
2014-06-10 06:41:50 +04:00
|
|
|
for _, name := range master.binlog.LogNames() {
|
2014-08-07 12:49:48 +04:00
|
|
|
p := path.Join(master.binlog.LogPath(), name)
|
2014-06-10 06:41:50 +04:00
|
|
|
|
|
|
|
err = slave.ReplicateFromBinLog(p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = checkLedisEqual(master, slave); err != nil {
|
2014-06-04 10:42:02 +04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:41:50 +04:00
|
|
|
slave.FlushAll()
|
2014-06-04 10:42:02 +04:00
|
|
|
|
2014-06-10 06:41:50 +04:00
|
|
|
db.Set([]byte("a1"), []byte("1"))
|
|
|
|
db.Set([]byte("b1"), []byte("2"))
|
|
|
|
db.Set([]byte("c1"), []byte("3"))
|
|
|
|
|
|
|
|
db.HSet([]byte("a1"), []byte("1"), []byte("value"))
|
|
|
|
db.HSet([]byte("b1"), []byte("2"), []byte("value"))
|
|
|
|
db.HSet([]byte("c1"), []byte("3"), []byte("value"))
|
|
|
|
|
|
|
|
info := new(MasterInfo)
|
|
|
|
info.LogFileIndex = 1
|
|
|
|
info.LogPos = 0
|
|
|
|
var buf bytes.Buffer
|
|
|
|
var n int
|
|
|
|
|
|
|
|
for {
|
|
|
|
buf.Reset()
|
|
|
|
n, err = master.ReadEventsTo(info, &buf)
|
|
|
|
if err != nil {
|
2014-06-04 10:42:02 +04:00
|
|
|
t.Fatal(err)
|
2014-06-10 06:41:50 +04:00
|
|
|
} else if info.LogFileIndex == -1 {
|
|
|
|
t.Fatal("invalid log file index -1")
|
|
|
|
} else if info.LogFileIndex == 0 {
|
|
|
|
t.Fatal("invalid log file index 0")
|
|
|
|
} else {
|
|
|
|
if err = slave.ReplicateFromReader(&buf); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if n == 0 {
|
|
|
|
break
|
|
|
|
}
|
2014-06-04 10:42:02 +04:00
|
|
|
}
|
|
|
|
}
|
2014-06-10 06:41:50 +04:00
|
|
|
|
|
|
|
if err = checkLedisEqual(master, slave); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-06-04 10:42:02 +04:00
|
|
|
}
|