Ejemplo n.º 1
0
func (s *Slot) Update(coordConn zkhelper.Conn) error {
	// status validation
	switch s.State.Status {
	case SLOT_STATUS_MIGRATE, SLOT_STATUS_OFFLINE,
		SLOT_STATUS_ONLINE, SLOT_STATUS_PRE_MIGRATE:
		{
			// valid status, OK
		}
	default:
		{
			return errors.Trace(ErrUnknownSlotStatus)
		}
	}

	data, err := json.Marshal(s)
	if err != nil {
		return errors.Trace(err)
	}
	coordPath := GetSlotPath(s.ProductName, s.Id)
	_, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(data), 0, zkhelper.DefaultFileACLs(), true)
	if err != nil {
		return errors.Trace(err)
	}

	if s.State.Status == SLOT_STATUS_MIGRATE {
		err = NewAction(coordConn, s.ProductName, ACTION_TYPE_SLOT_MIGRATE, s, "", true)
	} else {
		err = NewAction(coordConn, s.ProductName, ACTION_TYPE_SLOT_CHANGED, s, "", true)
	}

	return errors.Trace(err)
}
Ejemplo n.º 2
0
Archivo: slot.go Proyecto: banyue/codis
func SetSlotRange(zkConn zkhelper.Conn, productName string, fromSlot, toSlot, groupId int, status SlotStatus) error {
	if status != SLOT_STATUS_OFFLINE && status != SLOT_STATUS_ONLINE {
		return errors.New("invalid status")
	}

	for i := fromSlot; i <= toSlot; i++ {
		s, err := GetSlot(zkConn, productName, i)
		if err != nil {
			return errors.Trace(err)
		}
		s.GroupId = groupId
		s.State.Status = status
		data, err := json.Marshal(s)
		if err != nil {
			return errors.Trace(err)
		}

		zkPath := GetSlotPath(productName, i)
		_, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(data), 0, zkhelper.DefaultFileACLs(), true)
		if err != nil {
			return errors.Trace(err)
		}
	}

	param := SlotMultiSetParam{
		From:    fromSlot,
		To:      toSlot,
		GroupId: groupId,
		Status:  status,
	}
	err := NewAction(zkConn, productName, ACTION_TYPE_MULTI_SLOT_CHANGED, param, "", true)
	return errors.Trace(err)
}
Ejemplo n.º 3
0
func (self *ServerGroup) AddServer(zkConn zkhelper.Conn, s *Server) error {
	s.GroupId = self.Id

	servers, err := self.GetServers(zkConn)
	if err != nil {
		return errors.Trace(err)
	}
	var masterAddr string
	for _, server := range servers {
		if server.Type == SERVER_TYPE_MASTER {
			masterAddr = server.Addr
		}
	}

	// make sure there is only one master
	if s.Type == SERVER_TYPE_MASTER && len(masterAddr) > 0 {
		return errors.Trace(ErrNodeExists)
	}

	// if this group has no server. auto promote this server to master
	if len(servers) == 0 {
		s.Type = SERVER_TYPE_MASTER
	}

	val, err := json.Marshal(s)
	if err != nil {
		return errors.Trace(err)
	}

	zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d/%s", self.ProductName, self.Id, s.Addr)
	_, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(val), 0, zkhelper.DefaultFileACLs(), true)

	// update servers
	servers, err = self.GetServers(zkConn)
	if err != nil {
		return errors.Trace(err)
	}
	self.Servers = servers

	if s.Type == SERVER_TYPE_MASTER {
		err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", true)
		if err != nil {
			return errors.Trace(err)
		}
	} else if s.Type == SERVER_TYPE_SLAVE && len(masterAddr) > 0 {
		// send command slaveof to slave
		err := utils.SlaveOf(s.Addr, masterAddr)
		if err != nil {
			return errors.Trace(err)
		}
	}

	return nil
}
Ejemplo n.º 4
0
func CreateActionRootPath(zkConn zkhelper.Conn, path string) error {
	// if action dir not exists, create it first
	exists, err := zkhelper.NodeExists(zkConn, path)
	if err != nil {
		return errors.Trace(err)
	}

	if !exists {
		_, err := zkhelper.CreateOrUpdate(zkConn, path, "", 0, zkhelper.DefaultDirACLs(), true)
		if err != nil {
			return errors.Trace(err)
		}
	}

	return nil
}
Ejemplo n.º 5
0
func (self *ServerGroup) AddServer(zkConn zkhelper.Conn, s *Server) error {
	s.GroupId = self.Id
	val, err := json.Marshal(s)
	if err != nil {
		return errors.Trace(err)
	}

	if s.Type == SERVER_TYPE_MASTER {
		// make sure there is only one master
		servers, err := self.GetServers(zkConn)
		if err != nil {
			return errors.Trace(err)
		}
		for _, server := range servers {
			if server.Type == SERVER_TYPE_MASTER {
				return errors.Trace(ErrNodeExists)
			}
		}
	}

	zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d/%s", self.ProductName, self.Id, s.Addr)
	_, err = zkhelper.CreateOrUpdate(zkConn, zkPath, string(val), 0, zkhelper.DefaultFileACLs(), true)

	// update servers
	servers, err := self.GetServers(zkConn)
	if err != nil {
		return errors.Trace(err)
	}
	self.Servers = servers

	if s.Type == SERVER_TYPE_MASTER {
		err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", true)
		if err != nil {
			return errors.Trace(err)
		}
	}

	return nil
}
Ejemplo n.º 6
0
func (self *ServerGroup) Create(zkConn zkhelper.Conn) error {
	if self.Id < 0 {
		return errors.NotSupportedf("invalid server group id %d", self.Id)
	}
	zkPath := fmt.Sprintf("/zk/codis/db_%s/servers/group_%d", self.ProductName, self.Id)
	_, err := zkhelper.CreateOrUpdate(zkConn, zkPath, "", 0, zkhelper.DefaultDirACLs(), true)
	if err != nil {
		return errors.Trace(err)
	}
	err = NewAction(zkConn, self.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, self, "", false)
	if err != nil {
		return errors.Trace(err)
	}

	// set no server slots' group id to this server group, no need to return error
	slots, err := NoGroupSlots(zkConn, self.ProductName)
	if err == nil && len(slots) > 0 {
		SetSlots(zkConn, self.ProductName, slots, self.Id, SLOT_STATUS_ONLINE)
	}

	return nil
}
Ejemplo n.º 7
0
func SetSlots(coordConn zkhelper.Conn, productName string, slots []*Slot, groupId int, status SlotStatus) error {
	if status != SLOT_STATUS_OFFLINE && status != SLOT_STATUS_ONLINE {
		return errors.New("invalid status")
	}

	ok, err := GroupExists(coordConn, productName, groupId)
	if err != nil {
		return errors.Trace(err)
	}
	if !ok {
		return errors.NotFoundf("group %d", groupId)
	}

	for _, s := range slots {
		s.GroupId = groupId
		s.State.Status = status
		data, err := json.Marshal(s)
		if err != nil {
			return errors.Trace(err)
		}

		coordPath := GetSlotPath(productName, s.Id)
		_, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(data), 0, zkhelper.DefaultFileACLs(), true)
		if err != nil {
			return errors.Trace(err)
		}
	}

	param := SlotMultiSetParam{
		From:    -1,
		To:      -1,
		GroupId: groupId,
		Status:  status,
	}

	err = NewAction(coordConn, productName, ACTION_TYPE_MULTI_SLOT_CHANGED, param, "", true)
	return errors.Trace(err)

}
Ejemplo n.º 8
0
func (sg *ServerGroup) AddServer(coordConn zkhelper.Conn, s *Server, auth string) error {
	switch s.Type {
	case SERVER_TYPE_MASTER, SERVER_TYPE_SLAVE, SERVER_TYPE_OFFLINE:
	default:
		return errors.NotSupportedf("server type %q", s.Type)
	}
	// if type is offline, the server may be down, so we cannot use store function
	if s.Type != SERVER_TYPE_OFFLINE {
		// we only support reborn-server and qdb-server
		// origin redis has no slot_info command
		// atm, we can use this command to check whether server is alive or not.
		if _, err := utils.SlotsInfo(s.Addr, 0, 0, auth); err != nil {
			return errors.Trace(err)
		}
	}

	s.GroupId = sg.Id

	servers, err := sg.GetServers(coordConn)
	if err != nil {
		return errors.Trace(err)
	}
	var masterAddr string
	for _, server := range servers {
		if server.Type == SERVER_TYPE_MASTER {
			masterAddr = server.Addr
		}
	}

	// make sure there is only one master
	if s.Type == SERVER_TYPE_MASTER && len(masterAddr) > 0 {
		return errors.Trace(ErrNodeExists)
	}

	// if this group has no server.
	// promote this server to master automatically if type is not offline
	if len(servers) == 0 && s.Type != SERVER_TYPE_OFFLINE {
		s.Type = SERVER_TYPE_MASTER
	}

	if s.Type == SERVER_TYPE_MASTER {
		if role, err := utils.GetRole(s.Addr, auth); err != nil {
			return errors.Trace(err)
		} else if role != "master" {
			return errors.Errorf("we need master, but server %s is %s", s.Addr, role)
		}
	}

	val, err := json.Marshal(s)
	if err != nil {
		return errors.Trace(err)
	}

	coordPath := fmt.Sprintf("/zk/reborn/db_%s/servers/group_%d/%s", sg.ProductName, sg.Id, s.Addr)
	_, err = zkhelper.CreateOrUpdate(coordConn, coordPath, string(val), 0, zkhelper.DefaultFileACLs(), true)

	// update servers
	servers, err = sg.GetServers(coordConn)
	if err != nil {
		return errors.Trace(err)
	}
	sg.Servers = servers

	if s.Type == SERVER_TYPE_MASTER {
		err = NewAction(coordConn, sg.ProductName, ACTION_TYPE_SERVER_GROUP_CHANGED, sg, "", true)
		if err != nil {
			return errors.Trace(err)
		}
	} else if s.Type == SERVER_TYPE_SLAVE && len(masterAddr) > 0 {
		// send command slaveof to slave
		err := utils.SlaveOf(s.Addr, masterAddr, auth)
		if err != nil {
			return errors.Trace(err)
		}
	}

	return nil
}