Beispiel #1
0
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)
}
Beispiel #2
0
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()
	}
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
// 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
}
Beispiel #7
0
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)
	}
}
Beispiel #8
0
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()
	}
}