diff --git a/cli/cmd/flashgroup.go b/cli/cmd/flashgroup.go index 14d2e9a24..5bff0c754 100644 --- a/cli/cmd/flashgroup.go +++ b/cli/cmd/flashgroup.go @@ -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 +} diff --git a/cli/cmd/flashnode.go b/cli/cmd/flashnode.go index 8ab8944ac..822a95f33 100644 --- a/cli/cmd/flashnode.go +++ b/cli/cmd/flashnode.go @@ -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) +} diff --git a/flashnode/serve_http.go b/flashnode/serve_http.go index 15f76593d..6faf6d56d 100644 --- a/flashnode/serve_http.go +++ b/flashnode/serve_http.go @@ -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{}) { diff --git a/master/const.go b/master/const.go index 48b703655..6ce9da1ed 100644 --- a/master/const.go +++ b/master/const.go @@ -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 ( diff --git a/master/flash_node_topology.go b/master/flash_node_topology.go index edd7ed628..6b167cfdb 100644 --- a/master/flash_node_topology.go +++ b/master/flash_node_topology.go @@ -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 } diff --git a/master/metadata_fsm.go b/master/metadata_fsm.go index 2ae6c2282..f4efc6d3d 100644 --- a/master/metadata_fsm.go +++ b/master/metadata_fsm.go @@ -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) } diff --git a/sdk/master/api_node.go b/sdk/master/api_node.go index 5c99c632a..fd9e63de7 100644 --- a/sdk/master/api_node.go +++ b/sdk/master/api_node.go @@ -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)) }