func (s *testReplSuite) testReplication(c *C, master testReplNode, slave testReplNode) { // first let both stop replication s.doCmdMustOK(c, master.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, slave.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, master.Port(), "SET", "a", "100") offset := int64(-1) // slaveof, will do full sync first, must support psync nc := slave.Slaveof(c, master.Port()) defer nc.Close(c) s.waitAndCheckSyncOffset(c, slave, offset) resp := s.doCmd(c, slave.Port(), "GET", "a") c.Assert(slave.SyncOffset(c), Not(Equals), int64(-1)) c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("100")) s.doCmdMustOK(c, master.Port(), "SET", "b", "100") time.Sleep(500 * time.Millisecond) resp = s.doCmd(c, slave.Port(), "GET", "b") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("100")) s.doCmdMustOK(c, master.Port(), "SET", "c", "") time.Sleep(500 * time.Millisecond) resp = s.doCmd(c, slave.Port(), "GET", "c") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("")) offset = slave.SyncOffset(c) // now close replication connection nc.Close(c) s.doCmdMustOK(c, master.Port(), "SET", "b", "1000") s.doCmdMustOK(c, master.Port(), "SET", "c", "123") s.waitAndCheckSyncOffset(c, slave, offset) resp = s.doCmd(c, slave.Port(), "GET", "b") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("1000")) resp = s.doCmd(c, slave.Port(), "GET", "c") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("123")) s.checkRole(c, master.Port(), "master") s.checkRole(c, slave.Port(), "slave") s.doCmdMustOK(c, slave.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, master.Port(), "SLAVEOF", "NO", "ONE") s.checkRole(c, master.Port(), "master") s.checkRole(c, slave.Port(), "master") }
// HINCRBYFLOAT key field delta func HIncrByFloatCmd(s Session, args [][]byte) (redis.Resp, error) { if v, err := s.Store().HIncrByFloat(s.DB(), args); err != nil { return toRespError(err) } else { return redis.NewBulkBytesWithString(store.FormatFloatString(v)), nil } }
// ROLE func RoleCmd(s Session, args [][]byte) (redis.Resp, error) { if len(args) != 0 { return toRespErrorf("len(args) = %d, expect = 0", len(args)) } c, _ := s.(*conn) if c == nil { return nil, errors.New("invalid connection") } ay := redis.NewArray() if masterAddr := c.h.masterAddr.Get(); masterAddr == "" { // master ay.Append(redis.NewBulkBytesWithString("master")) c.h.repl.RLock() defer c.h.repl.RUnlock() ay.Append(redis.NewInt(c.h.repl.masterOffset)) slaves := redis.NewArray() for slave, _ := range c.h.repl.slaves { a := redis.NewArray() if addr := slave.nc.RemoteAddr(); addr == nil { continue } else { a.Append(redis.NewBulkBytesWithString(strings.Split(addr.String(), ":")[0])) } a.Append(redis.NewBulkBytesWithString(fmt.Sprintf("%d", slave.listeningPort.Get()))) a.Append(redis.NewBulkBytesWithString(fmt.Sprintf("%d", slave.syncOffset.Get()))) slaves.Append(a) } ay.Append(slaves) } else { // slave ay.Append(redis.NewBulkBytesWithString("slave")) seps := strings.Split(masterAddr, ":") if len(seps) == 2 { port, err := strconv.ParseInt(seps[1], 10, 16) if err != nil { return toRespError(err) } ay.Append(redis.NewBulkBytesWithString(seps[0])) ay.Append(redis.NewInt(int64(port))) } else { return toRespErrorf("invalid master addr, must ip:port, but %s", masterAddr) } ay.Append(redis.NewBulkBytesWithString(c.h.masterConnState.Get())) ay.Append(redis.NewInt(c.h.syncOffset.Get())) } return ay, nil }
func (s *testReplSuite) testReplication(c *C, master testReplNode, slave testReplNode) { // first let both stop replication s.doCmdMustOK(c, master.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, slave.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, master.Port(), "SET", "a", "100") offset := int64(-1) // slaveof, will do full sync first, must support psync nc := slave.Slaveof(c, master.Port()) defer nc.Close(c) s.waitAndCheckSyncOffset(c, slave, offset) resp := s.doCmd(c, slave.Port(), "GET", "a") c.Assert(slave.SyncOffset(c), Not(Equals), int64(-1)) c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("100")) // write to a slave, must error resp = s.doCmd(c, slave.Port(), "SET", "e", "1") c.Assert(resp, FitsTypeOf, (*redis.Error)(nil)) c.Assert(resp.(*redis.Error).Value, Matches, "READONLY.*") s.doCmdMustOK(c, master.Port(), "SET", "b", "100") time.Sleep(500 * time.Millisecond) resp = s.doCmd(c, slave.Port(), "GET", "b") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("100")) s.doCmdMustOK(c, master.Port(), "SET", "c", "") // set another value with TTL s.doCmdMustOK(c, master.Port(), "SET", "ttl_key", "1", "PX", 100) time.Sleep(500 * time.Millisecond) resp = s.doCmd(c, slave.Port(), "GET", "c") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("")) // get expired key to let master force delete it resp = s.doCmd(c, master.Port(), "GET", "ttl_key") c.Assert(resp, DeepEquals, redis.NewBulkBytes(nil)) time.Sleep(500 * time.Millisecond) // the key must be deleted from master repliction resp = s.doCmd(c, slave.Port(), "GET", "ttl_key") c.Assert(resp, DeepEquals, redis.NewBulkBytes(nil)) offset = slave.SyncOffset(c) // now close replication connection nc.Close(c) s.doCmdMustOK(c, master.Port(), "SET", "b", "1000") s.doCmdMustOK(c, master.Port(), "SET", "c", "123") s.waitAndCheckSyncOffset(c, slave, offset) resp = s.doCmd(c, slave.Port(), "GET", "b") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("1000")) resp = s.doCmd(c, slave.Port(), "GET", "c") c.Assert(resp, DeepEquals, redis.NewBulkBytesWithString("123")) s.checkRole(c, master.Port(), "master") s.checkRole(c, slave.Port(), "slave") s.doCmdMustOK(c, slave.Port(), "SLAVEOF", "NO", "ONE") s.doCmdMustOK(c, master.Port(), "SLAVEOF", "NO", "ONE") s.checkRole(c, master.Port(), "master") s.checkRole(c, slave.Port(), "master") }