func (slv *slave) SendSlaveOfToMaster() error { slv.mtx.Lock() var mi = slv.mi var cli = slv.cli slv.mtx.Unlock() if cli == nil { return nil } var err error var pkg []byte if mi.Migration { var p ctrl.PkgMigrate p.ClientReq = false p.MasterAddr = mi.MasterAddr p.SlaveAddr = mi.SlaveAddr p.SlotId = mi.SlotId pkg, err = ctrl.Encode(proto.CmdMigrate, 0, 0, &p) if err != nil { return err } } else { lastSeq, valid := slv.bin.GetMasterSeq() if !valid { slv.mc.SetStatus(ctrl.SlaveNeedClear) // Any better solution? log.Fatalf("Slave lastSeq %d is out of sync, please clear old data! "+ "(Restart may fix this issue)", lastSeq) } var p ctrl.PkgSlaveOf p.ClientReq = false p.MasterAddr = mi.MasterAddr p.SlaveAddr = mi.SlaveAddr p.LastSeq = lastSeq log.Printf("Connect to master %s with lastSeq %d\n", mi.MasterAddr, p.LastSeq) pkg, err = ctrl.Encode(proto.CmdSlaveOf, 0, 0, &p) if err != nil { return err } } cli.AddResp(pkg) return slv.mc.SetStatus(ctrl.SlaveFullSync) }
func (srv *Server) slaveOf(req *Request) { var cliType uint32 = ClientTypeNormal if req.Cli != nil { cliType = req.Cli.ClientType() } var p ctrl.PkgSlaveOf var err = ctrl.Decode(req.Pkg, nil, &p) if err == nil && !p.ClientReq { srv.newNormalMaster(req, &p) return } switch cliType { case ClientTypeNormal: if err != nil { log.Printf("Failed to Decode pkg: %s\n", err) srv.replySlaveOf(req, fmt.Sprintf("decode failed(%s)", err)) return } if !req.Cli.IsAuth(proto.AdminDbId) { log.Printf("Not authorized!\n") srv.replySlaveOf(req, "no priviledge") return } if len(p.SlaveAddr) == 0 { p.SlaveAddr = req.Cli.LocalAddr().String() } if sameAddress(p.MasterAddr, p.SlaveAddr, req) { log.Printf("Master and slave addresses are the same!\n") srv.replyMigrate(req, "master and slave addresses are the same") return } err = srv.mc.SetMaster(p.MasterAddr, p.SlaveAddr) if err != nil { log.Printf("Failed to set config: %s\n", err) srv.replySlaveOf(req, fmt.Sprintf("set config failed(%s)", err)) return } srv.rwMtx.Lock() slv := srv.slv srv.slv = nil srv.rwMtx.Unlock() if len(p.MasterAddr) > 0 { if slv != nil { slv.Close() } srv.bin.AsSlave() srv.connectToMaster(srv.mc) } else { if slv != nil { go slv.DelayClose() } srv.bin.AsMaster() } srv.replySlaveOf(req, "") // Success case ClientTypeSlave: fallthrough case ClientTypeMaster: if err != nil { log.Printf("Failed to Decode pkg: %s\n", err) } else { log.Println("Invalid client type %d for SlaveOf command, close now!", cliType) } req.Cli.Close() } }