feat(flashnode): make slot with user defined

. #22200518

Signed-off-by: slasher <mcq.sejust@gmail.com>
This commit is contained in:
slasher 2023-12-21 16:41:15 +08:00 committed by zhumingze1108
parent d30f8cae5b
commit 44e56bb610
7 changed files with 62 additions and 33 deletions

View File

@ -61,6 +61,10 @@ func newCmdFlashGroupCreate(client *master.MasterClient) *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
var err error
defer func() { errout(err) }()
if optSlots == "" {
err = fmt.Errorf("pls set --slots")
return
}
fgView, err := client.AdminAPI().CreateFlashGroup(optSlots)
if err != nil {
return
@ -339,6 +343,7 @@ func newCmdFlashGroupSearch(client *master.MasterClient) *cobra.Command {
return
}
}
stdoutlnf("Not found (%s %d %d) -> %d", volume, inode, offset, slotKey)
},
}
}
@ -378,13 +383,19 @@ func newCmdFlashGroupGraph(client *master.MasterClient) *cobra.Command {
return slots[i].slot < slots[j].slot
})
const _fgView = "%-10v %-10v %-18v %-6v %-6v"
stdoutln("[Flash Groups]")
stdoutlnf(_fgView, "SLOT", "ID", "STATUS", "Count", "Ref")
for _, slot := range slots {
tbl := table{arow("Slot", "ID", "Status", "Count", "Ref", "Proportion")}
for idx, slot := range slots {
g := groups[slot.fgID]
stdoutlnf(_fgView, slot.slot, g.ID, g.Status.String(), g.FlashNodeCount, groupn[g.ID])
var p string
if idx == len(slots)-1 {
p = proportion(slot.slot, math.MaxUint32)
} else {
p = proportion(slot.slot, slots[idx+1].slot)
}
tbl = tbl.append(arow(slot.slot, g.ID, g.Status.String(), g.FlashNodeCount, groupn[g.ID], p))
}
stdoutln(alignTable(tbl...))
fnView, err := client.AdminAPI().ListFlashNodes(true)
if err != nil {
@ -402,7 +413,7 @@ func newCmdFlashGroupGraph(client *master.MasterClient) *cobra.Command {
}
}
stdoutln("[FlashNodes Busy]")
tbl := showFlashNodesView(busyNodes, true, table{formatFlashNodeViewTableTitle})
tbl = showFlashNodesView(busyNodes, true, table{formatFlashNodeViewTableTitle})
stdoutln(alignTable(tbl...))
stdoutln("[FlashNodes Idle]")
tbl = showFlashNodesView(idleNodes, true, table{formatFlashNodeViewTableTitle})
@ -414,3 +425,13 @@ func newCmdFlashGroupGraph(client *master.MasterClient) *cobra.Command {
func parseFlashGroupID(id string) (uint64, error) {
return strconv.ParseUint(id, 10, 64)
}
const fullDot = ".................................................."
func proportion(s, e uint32) string {
p := "."
if n := int(float64(e-s) * float64(len(fullDot)) / float64(math.MaxUint32)); n > 0 {
p = fullDot[:n]
}
return p
}

View File

@ -18,6 +18,7 @@ import (
"fmt"
"sort"
"strconv"
"strings"
"github.com/cubefs/cubefs/proto"
"github.com/cubefs/cubefs/sdk/httpclient"
@ -130,7 +131,7 @@ func showFlashNodesView(flashNodeViewInfos []*proto.FlashNodeViewInfo, showStat
hitRate, evicts, limit := "N/A", "N/A", "N/A"
if fn.IsActive && fn.IsEnable {
if stat, e := client.WithAddr(fn.Addr).FlashNode().Stat(); e == nil {
if stat, e := client.WithAddr(addr2Prof(fn.Addr)).FlashNode().Stat(); e == nil {
hitRate = fmt.Sprintf("%.2f%%", stat.CacheStatus.HitRate*100)
evicts = strconv.Itoa(stat.CacheStatus.Evicts)
limit = strconv.FormatUint(stat.NodeLimit, 10)
@ -143,3 +144,10 @@ func showFlashNodesView(flashNodeViewInfos []*proto.FlashNodeViewInfo, showStat
}
return tbl
}
// TODO: mandatory design prof http port is service port+1
func addr2Prof(addr string) string {
arr := strings.SplitN(addr, ":", 2)
p, _ := strconv.ParseUint(arr[1], 10, 64)
return fmt.Sprintf("%s:%d", arr[0], p+1)
}

View File

@ -41,7 +41,7 @@ func (f *FlashNode) handleEvictVolume(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
volume := r.FormValue("volume")
if volume == "" {
replyErr(w, r, http.StatusBadRequest, "volume name can not be empty", nil)
replyErr(w, r, proto.ErrCodeParamError, "volume name can not be empty", nil)
return
}
replyOK(w, r, f.cacheEngine.EvictCacheByVolume(volume))
@ -53,7 +53,7 @@ func (f *FlashNode) handleEvictAll(w http.ResponseWriter, r *http.Request) {
}
func replyOK(w http.ResponseWriter, r *http.Request, data interface{}) {
replyErr(w, r, http.StatusOK, "OK", data)
replyErr(w, r, proto.ErrCodeSuccess, "OK", data)
}
func replyErr(w http.ResponseWriter, r *http.Request, code int32, msg string, data interface{}) {

View File

@ -246,7 +246,7 @@ const (
dataNodesUnAvailable = 3
unusedFlashNodeFlashGroupID = 0
defaultFlashGroupSlotsCount = 128
defaultFlashGroupSlotsCount = 32
)
const (
@ -317,13 +317,6 @@ const (
opSyncAddLcResult uint32 = 0x3a
opSyncDeleteLcResult uint32 = 0x3b
opSyncAddFlashNode uint32 = 0x3A
opSyncDeleteFlashNode uint32 = 0x3B
opSyncUpdateFlashNode uint32 = 0x3C
opSyncAddFlashGroup uint32 = 0x3D
opSyncDeleteFlashGroup uint32 = 0x3E
opSyncUpdateFlashGroup uint32 = 0x3F
opSyncAllocQuotaID uint32 = 0x40
opSyncSetQuota uint32 = 0x41
opSyncDeleteQuota uint32 = 0x42
@ -331,6 +324,13 @@ const (
opSyncS3QosSet uint32 = 0x60
opSyncS3QosDelete uint32 = 0x61
opSyncAddFlashNode uint32 = 0x6A
opSyncDeleteFlashNode uint32 = 0x6B
opSyncUpdateFlashNode uint32 = 0x6C
opSyncAddFlashGroup uint32 = 0x6D
opSyncDeleteFlashGroup uint32 = 0x6E
opSyncUpdateFlashGroup uint32 = 0x6F
)
const (

View File

@ -18,6 +18,7 @@ import (
"encoding/json"
"fmt"
"hash/crc32"
"sort"
"sync"
"github.com/cubefs/cubefs/proto"
@ -136,17 +137,22 @@ func (t *flashNodeTopology) deleteFlashNode(flashNode *FlashNode) {
// the function caller should use createFlashGroupLock
func (t *flashNodeTopology) allocateNewSlotsForCreateFlashGroup(fgID uint64, setSlots []uint32) (slots []uint32) {
slots = make([]uint32, 0, defaultFlashGroupSlotsCount)
if len(setSlots) != 0 {
slots = append(slots, setSlots...)
slots = make([]uint32, 0, len(setSlots))
for _, slot := range setSlots {
if _, ok := t.slotsMap[slot]; !ok {
slots = append(slots, slot)
}
}
if len(slots) > 0 {
return
}
for len(slots) < defaultFlashGroupSlotsCount {
slot := allocateNewSlot()
if _, ok := t.slotsMap[slot]; ok {
continue
}
slots = append(slots, slot)
t.slotsMap[slot] = fgID
}
return
}
@ -161,19 +167,22 @@ func (t *flashNodeTopology) removeSlots(slots []uint32) {
for _, slot := range slots {
delete(t.slotsMap, slot)
}
return
}
func (t *flashNodeTopology) createFlashGroup(fgID uint64, c *Cluster, setSlots []uint32) (flashGroup *FlashGroup, err error) {
t.createFlashGroupLock.Lock()
defer t.createFlashGroupLock.Unlock()
slots := t.allocateNewSlotsForCreateFlashGroup(fgID, setSlots)
sort.Slice(slots, func(i, j int) bool { return slots[i] < slots[j] })
flashGroup = newFlashGroup(fgID, slots, proto.FlashGroupStatus_Inactive)
if err = c.syncAddFlashGroup(flashGroup); err != nil {
t.removeSlots(slots)
return
}
t.flashGroupMap.Store(flashGroup.ID, flashGroup)
for _, slot := range slots {
t.slotsMap[slot] = flashGroup.ID
}
return
}
@ -219,19 +228,9 @@ func (t *flashNodeTopology) getFlashGroupView() (fgv *proto.FlashGroupView) {
Slot: fg.Slots,
Hosts: hosts,
})
//for _, slot := range fg.Slots {
// fgv.FlashGroups = append(fgv.FlashGroups, proto.FlashGroupInfo{
// ID: fg.ID,
// Slot: slot,
// Hosts: hosts,
// })
//}
}
return true
})
//sort.Slice(fgv.FlashGroups, func(i, j int) bool {
// return fgv.FlashGroups[i].Slot < fgv.FlashGroups[j].Slot
//})
return
}

View File

@ -155,7 +155,8 @@ func (mf *MetadataFsm) Apply(command []byte, index uint64) (resp interface{}, er
switch cmd.Op {
case opSyncDeleteDataNode, opSyncDeleteMetaNode, opSyncDeleteVol, opSyncDeleteDataPartition, opSyncDeleteMetaPartition,
opSyncDeleteUserInfo, opSyncDeleteAKUser, opSyncDeleteVolUser, opSyncDeleteQuota, opSyncDeleteLcNode,
opSyncDeleteLcConf, opSyncDeleteLcTask, opSyncDeleteLcResult, opSyncS3QosDelete, opSyncDeleteDecommissionDisk:
opSyncDeleteLcConf, opSyncDeleteLcTask, opSyncDeleteLcResult, opSyncS3QosDelete, opSyncDeleteDecommissionDisk,
opSyncDeleteFlashNode, opSyncDeleteFlashGroup:
if err = mf.delKeyAndPutIndex(cmd.K, cmdMap); err != nil {
panic(err)
}

View File

@ -197,7 +197,7 @@ func (api *NodeAPI) AddFlashNode(serverAddr, zoneName, version string) (id uint6
}
func (api *NodeAPI) SetFlashNode(addr, state string) (err error) {
return api.mc.request(newRequest(get, proto.FlashNodeSet).Header(api.h).
return api.mc.request(newRequest(post, proto.FlashNodeSet).Header(api.h).
addParam("addr", addr).addParam("state", state))
}