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) deleteSlot(req *Request) { var cliType uint32 = ClientTypeNormal if req.Cli != nil { cliType = req.Cli.ClientType() } switch cliType { case ClientTypeNormal: var p ctrl.PkgDelSlot var err = ctrl.Decode(req.Pkg, nil, &p) p.ErrMsg = "" if err != nil { p.ErrMsg = fmt.Sprintf("decode failed %s", err) } else { err = srv.deleteMigrationSlot(p.SlotId, srv.mc.GetMaster()) if err != nil { p.ErrMsg = fmt.Sprintf("delete slot failed %s", err) } } pkg, err := ctrl.Encode(req.Cmd, req.DbId, req.Seq, &p) if err == nil { srv.sendResp(false, req, pkg) } case ClientTypeSlave: fallthrough case ClientTypeMaster: log.Println("Invalid client type %d for DelSlot command, close now!", cliType) req.Cli.Close() } }
// Internal control command. // DelSlot deletes one slot data. func (c *CtrlContext) DelSlot(slotId uint16) error { call := c.cli.newCall(proto.CmdDelSlot, nil) if call.err != nil { return call.err } var p ctrl.PkgDelSlot p.SlotId = slotId pkg, err := ctrl.Encode(call.cmd, c.dbId, call.seq, &p) if err != nil { c.cli.errCall(call, err) return call.err } call.pkg = pkg c.cli.sending <- call r, err := (<-call.Done).Reply() if err != nil { return call.err } t := r.(*ctrl.PkgDelSlot) if t.ErrMsg != "" { return errors.New(t.ErrMsg) } return nil }
// Internal control command. // SlaveStatus reads migration/slave status. func (c *CtrlContext) SlaveStatus(migration bool, slotId uint16) (int, error) { call := c.cli.newCall(proto.CmdSlaveSt, nil) if call.err != nil { return ctrl.NotSlave, call.err } var p ctrl.PkgSlaveStatus p.Migration = migration p.SlotId = slotId pkg, err := ctrl.Encode(call.cmd, c.dbId, call.seq, &p) if err != nil { c.cli.errCall(call, err) return ctrl.NotSlave, call.err } call.pkg = pkg c.cli.sending <- call r, err := (<-call.Done).Reply() if err != nil { return ctrl.NotSlave, call.err } t := r.(*ctrl.PkgSlaveStatus) if t.ErrMsg != "" { return ctrl.NotSlave, errors.New(t.ErrMsg) } return t.Status, nil }
// Internal control command. // Migrate moves one slot data to another server on the fly. func (c *CtrlContext) Migrate(host string, slotId uint16) error { call := c.cli.newCall(proto.CmdMigrate, nil) if call.err != nil { return call.err } var p ctrl.PkgMigrate p.ClientReq = true p.MasterAddr = host p.SlotId = slotId pkg, err := ctrl.Encode(call.cmd, c.dbId, call.seq, &p) if err != nil { c.cli.errCall(call, err) return err } call.pkg = pkg c.cli.sending <- call r, err := (<-call.Done).Reply() if err != nil { return err } t := r.(*ctrl.PkgMigrate) if t.ErrMsg != "" { return errors.New(t.ErrMsg) } return nil }
// Internal control command. // SlaveOf can change the replication settings of a slave on the fly. func (c *CtrlContext) SlaveOf(host string) error { call := c.cli.newCall(proto.CmdSlaveOf, nil) if call.err != nil { return call.err } var p ctrl.PkgSlaveOf p.ClientReq = true p.MasterAddr = host pkg, err := ctrl.Encode(call.cmd, c.dbId, call.seq, &p) if err != nil { c.cli.errCall(call, err) return err } call.pkg = pkg c.cli.sending <- call r, err := (<-call.Done).Reply() if err != nil { return err } t := r.(*ctrl.PkgSlaveOf) if t.ErrMsg != "" { return errors.New(t.ErrMsg) } return nil }
func (srv *Server) replyMigrate(req *Request, msg string) { ps := ctrl.PkgMigrate{} ps.ErrMsg = msg pkg, err := ctrl.Encode(req.Cmd, req.DbId, req.Seq, &ps) if err == nil { srv.sendResp(false, req, pkg) } }
func (srv *Server) slaveStatus(req *Request) { var cliType uint32 = ClientTypeNormal if req.Cli != nil { cliType = req.Cli.ClientType() } switch cliType { case ClientTypeNormal: var p ctrl.PkgSlaveStatus var err = ctrl.Decode(req.Pkg, nil, &p) p.ErrMsg = "" if err != nil { p.ErrMsg = fmt.Sprintf("decode failed %s", err) } else { m := srv.mc.GetMaster() if len(m.MasterAddr) > 0 { if p.Migration { if !m.Migration { p.ErrMsg = fmt.Sprintf("check migration status on normal slave") } else if m.SlotId != p.SlotId { p.ErrMsg = fmt.Sprintf("slot id mismatch (%d, %d)", m.SlotId, p.SlotId) } } else { if m.Migration { p.ErrMsg = fmt.Sprintf("check normal slave status on migration") } } } if len(p.ErrMsg) == 0 { p.Status = m.Status } } pkg, err := ctrl.Encode(req.Cmd, req.DbId, req.Seq, &p) if err == nil { srv.sendResp(false, req, pkg) } case ClientTypeSlave: fallthrough case ClientTypeMaster: log.Println("Invalid client type %d for MigStatus command, close now!", cliType) req.Cli.Close() } }