1
// Copyright 2022 The CubeFS Authors.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
25
bloberr "github.com/cubefs/cubefs/blobstore/common/errors"
26
"github.com/cubefs/cubefs/blobstore/common/proto"
27
"github.com/cubefs/cubefs/blobstore/common/rpc"
31
ChunkStatusDefault ChunkStatus = iota // 0
32
ChunkStatusNormal // 1
33
ChunkStatusReadOnly // 2
34
ChunkStatusRelease // 3
39
ReleaseForUser = "release for user"
40
ReleaseForCompact = "release for compact"
48
ChunkIdLength = chunkVuidLen + chunkTimestmapLen
51
var InvalidChunkId ChunkId = [ChunkIdLength]byte{}
54
_vuidHexLen = hex.EncodedLen(chunkVuidLen)
55
_timestampHexLen = hex.EncodedLen(chunkTimestmapLen)
57
// ${vuid_hex}-${tiemstamp_hex}
58
// |-- 8 Bytes --|-- 1 Bytes --|-- 8 Bytes --|
59
delimiter = []byte("-")
60
ChunkIdEncodeLen = _vuidHexLen + _timestampHexLen + len(delimiter)
64
ChunkId [ChunkIdLength]byte
68
func (c ChunkId) UnixTime() uint64 {
69
return binary.BigEndian.Uint64(c[chunkVuidLen:ChunkIdLength])
72
func (c ChunkId) VolumeUnitId() proto.Vuid {
73
return proto.Vuid(binary.BigEndian.Uint64(c[:chunkVuidLen]))
76
func (c *ChunkId) Marshal() ([]byte, error) {
77
buf := make([]byte, ChunkIdEncodeLen)
80
hex.Encode(buf[i:_vuidHexLen], c[:chunkVuidLen])
83
copy(buf[i:i+len(delimiter)], delimiter)
86
hex.Encode(buf[i:], c[chunkVuidLen:ChunkIdLength])
91
func (c *ChunkId) Unmarshal(data []byte) error {
92
if len(data) != ChunkIdEncodeLen {
93
panic(errors.New("chunk buf size not match"))
98
_, err := hex.Decode(c[:chunkVuidLen], data[i:_vuidHexLen])
106
_, err = hex.Decode(c[chunkVuidLen:], data[i:])
114
func (c ChunkId) String() string {
115
buf, _ := c.Marshal()
116
return string(buf[:])
119
func (c ChunkId) MarshalJSON() ([]byte, error) {
120
b := make([]byte, ChunkIdEncodeLen+2)
121
b[0], b[ChunkIdEncodeLen+1] = '"', '"'
123
buf, _ := c.Marshal()
129
func (c *ChunkId) UnmarshalJSON(data []byte) (err error) {
130
if len(data) != ChunkIdEncodeLen+2 {
131
return errors.New("failed unmarshal json")
134
return c.Unmarshal(data[1 : ChunkIdEncodeLen+1])
137
func EncodeChunk(id ChunkId) string {
141
func NewChunkId(vuid proto.Vuid) (chunkId ChunkId) {
142
binary.BigEndian.PutUint64(chunkId[:chunkVuidLen], uint64(vuid))
143
binary.BigEndian.PutUint64(chunkId[chunkVuidLen:ChunkIdLength], uint64(time.Now().UnixNano()))
147
func IsValidDiskID(id proto.DiskID) bool {
148
return id != proto.InvalidDiskID
151
func IsValidChunkId(id ChunkId) bool {
152
return id != InvalidChunkId
155
func IsValidChunkStatus(status ChunkStatus) bool {
156
return status < ChunkNumStatus
159
func DecodeChunk(name string) (id ChunkId, err error) {
161
if len(buf) != ChunkIdEncodeLen {
162
return InvalidChunkId, errors.New("invalid chunk name")
165
if err = id.Unmarshal(buf); err != nil {
166
return InvalidChunkId, errors.New("chunk unmarshal failed")
172
type CreateChunkArgs struct {
173
DiskID proto.DiskID `json:"diskid"`
174
Vuid proto.Vuid `json:"vuid"`
175
ChunkSize int64 `json:"chunksize,omitempty"`
178
func (c *client) CreateChunk(ctx context.Context, host string, args *CreateChunkArgs) (err error) {
179
if !IsValidDiskID(args.DiskID) {
180
err = bloberr.ErrInvalidDiskId
184
urlStr := fmt.Sprintf("%v/chunk/create/diskid/%v/vuid/%v?chunksize=%v",
185
host, args.DiskID, args.Vuid, args.ChunkSize)
187
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
191
type StatChunkArgs struct {
192
DiskID proto.DiskID `json:"diskid"`
193
Vuid proto.Vuid `json:"vuid"`
196
func (c *client) StatChunk(ctx context.Context, host string, args *StatChunkArgs) (ci *ChunkInfo, err error) {
197
if !IsValidDiskID(args.DiskID) {
198
err = bloberr.ErrInvalidDiskId
202
urlStr := fmt.Sprintf("%v/chunk/stat/diskid/%v/vuid/%v", host, args.DiskID, args.Vuid)
204
err = c.GetWith(ctx, urlStr, ci)
208
type ChangeChunkStatusArgs struct {
209
DiskID proto.DiskID `json:"diskid"`
210
Vuid proto.Vuid `json:"vuid"`
211
Force bool `json:"force,omitempty"`
214
type ChunkInspectArgs struct {
215
DiskID proto.DiskID `json:"diskid"`
216
Vuid proto.Vuid `json:"vuid"`
219
func (c *client) ReleaseChunk(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error) {
220
if !IsValidDiskID(args.DiskID) {
221
err = bloberr.ErrInvalidDiskId
225
urlStr := fmt.Sprintf("%v/chunk/release/diskid/%v/vuid/%v?force=%v", host, args.DiskID, args.Vuid, args.Force)
226
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
230
func (c *client) SetChunkReadonly(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error) {
231
if !IsValidDiskID(args.DiskID) {
232
err = bloberr.ErrInvalidDiskId
236
urlStr := fmt.Sprintf("%v/chunk/readonly/diskid/%v/vuid/%v", host, args.DiskID, args.Vuid)
238
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
242
func (c *client) SetChunkReadwrite(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error) {
243
if !IsValidDiskID(args.DiskID) {
244
err = bloberr.ErrInvalidDiskId
248
urlStr := fmt.Sprintf("%v/chunk/readwrite/diskid/%v/vuid/%v", host, args.DiskID, args.Vuid)
249
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
253
type ListChunkArgs struct {
254
DiskID proto.DiskID `json:"diskid"`
257
type ListChunkRet struct {
258
ChunkInfos []*ChunkInfo `json:"chunk_infos"`
261
func (c *client) ListChunks(ctx context.Context, host string, args *ListChunkArgs) (ret []*ChunkInfo, err error) {
262
if !IsValidDiskID(args.DiskID) {
263
err = bloberr.ErrInvalidDiskId
267
urlStr := fmt.Sprintf("%v/chunk/list/diskid/%v", host, args.DiskID)
269
listRet := &ListChunkRet{}
270
err = c.GetWith(ctx, urlStr, listRet)
275
return listRet.ChunkInfos, nil
278
type CompactChunkArgs struct {
279
DiskID proto.DiskID `json:"diskid"`
280
Vuid proto.Vuid `json:"vuid"`
283
type DiskProbeArgs struct {
284
Path string `json:"path"`
287
type BadShard struct {