mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
with: #1000150848
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6e6373b1d6)
778 lines
23 KiB
Go
778 lines
23 KiB
Go
package proto
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cubefs/cubefs/util/fastcrc32"
|
|
)
|
|
|
|
const (
|
|
PageSize = 4 * 1024
|
|
CACHE_BLOCK_PACKET_SIZE = 128 * PageSize
|
|
CACHE_WRITE_CHUCK_SIZE = 64 * 1024
|
|
CACHE_BLOCK_SIZE = 1 << 20
|
|
CACHE_OBJECT_BLOCK_SIZE = 4 * 1024 * 1024
|
|
SMALL_OBJECT_BLOCK_SIZE = 16 * 1024
|
|
ReadCacheTimeout = 1 // second
|
|
DefaultCacheTTLSec = 5 * 24 * 3600
|
|
FlashGroupDefaultWeight = 1
|
|
FlashGroupMaxWeight = 30
|
|
CACHE_BLOCK_CRC_SIZE = 4
|
|
WarnMagicNumber = 0x57 // 'W' for WarmUp
|
|
)
|
|
|
|
const (
|
|
FlashGroupStatus_Inactive FlashGroupStatus = 0x0
|
|
FlashGroupStatus_Active FlashGroupStatus = 0x1
|
|
)
|
|
|
|
const (
|
|
SlotStatus_Completed SlotStatus = 0x0
|
|
SlotStatus_Creating SlotStatus = 0x1
|
|
SlotStatus_Deleting SlotStatus = 0x2
|
|
|
|
FlashNodeTaskWorker = "task"
|
|
FlashNodeCacheWorker = "cache"
|
|
FlashManualWarmupAction = "warmup"
|
|
FlashManualClearAction = "clear"
|
|
FlashManualCheckAction = "check"
|
|
)
|
|
|
|
var (
|
|
ErrorNotExistShouldCache = fmt.Errorf("cache miss: should store and cache the key")
|
|
ErrorNotExistShouldNotCache = fmt.Errorf("only cache the miss after reaching the miss times")
|
|
ErrorUnableToBuildKeyFromPacket = fmt.Errorf("unable to build a key from the packet due to lack of available parameters")
|
|
ErrorParsingCacheWriteHead = fmt.Errorf("error parsing cache write head structure")
|
|
ErrorNoCacheDeleteRequest = fmt.Errorf("no cache delete request")
|
|
ErrorNoCacheReadRequest = fmt.Errorf("no cache read request")
|
|
ErrorNoCachePrepareRequest = fmt.Errorf("no cache prepare request")
|
|
ErrorDeleteBlockKeyNil = fmt.Errorf("delete block key is nil")
|
|
ErrorRequireDataIsCaching = fmt.Errorf("require data is caching")
|
|
ErrorReadTimeout = fmt.Errorf("read timeout")
|
|
ErrorNoAvailableHost = fmt.Errorf("no available host")
|
|
ErrorContextDeadLine = fmt.Errorf("context deadline exceeded")
|
|
ErrorRequestOutOfRange = fmt.Errorf("the requested read size is out of range")
|
|
ErrorUnableGetCreatedBlock = fmt.Errorf("unable to get created cacheblock")
|
|
ErrorNoFlashGroup = fmt.Errorf("cannot find any flashGroups")
|
|
ErrorInitRemoteTimeout = fmt.Errorf("init remote cache timeout for remote client")
|
|
)
|
|
|
|
var (
|
|
ErrorResultCodeNOKTpl = "ResultCode NOK (%v)"
|
|
ErrorUnknownOpcodeTpl = "unknown Opcode:%d"
|
|
ErrorTaskIDNotExistTpl = "task id(%v) not exist"
|
|
ErrorBlockAlreadyExistsTpl = "block %v already exist expireTime(%v)"
|
|
ErrorCreateBlockFailedTpl = "create block(%v) error %v"
|
|
ErrorBlockAlreadyCreatedTpl = "block(%v) already created expireTime(%v)"
|
|
ErrorPutDataLengthInvalidTpl = "put data length %v is leq 0 or gt 4M"
|
|
ErrorInconsistentCRCTpl = "inconsistent CRC, expect(%v) reply(%v)"
|
|
ErrorExpectedReadBytesMismatchTpl = "expected to read %d bytes, but only read %d"
|
|
ErrorUnexpectedDataLengthTpl = "unexpected data length: expected %d bytes, got %d"
|
|
ErrorWriteDataAndCRCToFlashNodeTpl = "write data and crc to flashNode get err %v"
|
|
ErrorReadFromCloseReaderTpl = "read from close reader reqID(%v)"
|
|
ErrorInconsistentCRCObjectTpl = "inconsistent CRC, offset(%v) extentOffset(%v) expect(%v) actualCrc(%v)"
|
|
ErrorInvalidRangeTpl = "invalid range: from(%v) to(%v)"
|
|
ErrorContextErrorTpl = "context error: %v"
|
|
ErrorRemoteErrorTpl = "remote error: %v"
|
|
ErrorReadErrorTpl = "read error: %v"
|
|
ErrorIOErrorTpl = "io error: %v"
|
|
ErrorFlowLimitErrorTpl = "flow limit error: %v"
|
|
)
|
|
|
|
const (
|
|
WarmStatusInitializing = 1
|
|
WarmStatusRunning = 2
|
|
WarmStatusCompleted = 3
|
|
WarmStatusFailed = 4
|
|
)
|
|
|
|
const (
|
|
WarmupMetaTokenApply = 1 // apply for warmup meta token
|
|
WarmupMetaTokenRenew = 2 // renew warmup meta token
|
|
WarmupMetaTokenRelease = 3 // release warmup meta token
|
|
)
|
|
|
|
type FlashGroupStatus int
|
|
|
|
type SlotStatus int
|
|
|
|
func (status FlashGroupStatus) String() string {
|
|
switch status {
|
|
case FlashGroupStatus_Inactive:
|
|
return "Inactive"
|
|
case FlashGroupStatus_Active:
|
|
return "Active"
|
|
default:
|
|
return "Unknown"
|
|
}
|
|
}
|
|
|
|
func (status FlashGroupStatus) IsActive() bool {
|
|
return status == FlashGroupStatus_Active
|
|
}
|
|
|
|
type ManualTaskStatus int
|
|
|
|
// 0 init,1 running,2 pause,3 success,4 failed
|
|
const (
|
|
Flash_Task_Init ManualTaskStatus = iota
|
|
Flash_Task_Running
|
|
Flash_Task_Pause
|
|
Flash_Task_Success
|
|
Flash_Task_Failed
|
|
Flash_Task_Stop
|
|
)
|
|
|
|
func ManualTaskDone(status int) bool {
|
|
success, failed, stop := int(Flash_Task_Success), int(Flash_Task_Failed), int(Flash_Task_Stop)
|
|
return status == success || status == failed || status == stop
|
|
}
|
|
|
|
func ManualTaskIsRunning(status int) bool {
|
|
running := int(Flash_Task_Running)
|
|
return status == running
|
|
}
|
|
|
|
type FlashGroupInfo struct {
|
|
ID uint64 `json:"i"`
|
|
Slot []uint32 `json:"s"` // FlashGroup's position in hasher ring
|
|
Hosts []string `json:"h"`
|
|
}
|
|
|
|
type FlashGroupView struct {
|
|
Enable bool
|
|
FlashGroups []*FlashGroupInfo
|
|
}
|
|
|
|
type CoonHandler struct {
|
|
RemoteError error
|
|
Completed chan struct{}
|
|
WaitAckChanClosed bool
|
|
WaitAckChan chan struct{}
|
|
}
|
|
|
|
func (f *FlashGroupInfo) String() string {
|
|
return fmt.Sprintf("{ID: %d, Hosts: %v}", f.ID, f.Hosts)
|
|
}
|
|
|
|
func (ds *DataSource) EncodeBinaryTo(b []byte) {
|
|
binary.BigEndian.PutUint64(b[:8], ds.FileOffset)
|
|
binary.BigEndian.PutUint64(b[8:16], ds.PartitionID)
|
|
binary.BigEndian.PutUint64(b[16:24], ds.ExtentID)
|
|
binary.BigEndian.PutUint64(b[24:32], ds.ExtentOffset)
|
|
binary.BigEndian.PutUint64(b[32:40], ds.Size_)
|
|
binary.BigEndian.PutUint16(b[40:42], uint16(len(ds.Hosts)))
|
|
off := 42
|
|
for i := 0; i < len(ds.Hosts); i++ {
|
|
b[off] = uint8(len(ds.Hosts[i]))
|
|
off += 1
|
|
copy(b[off:off+len(ds.Hosts[i])], ds.Hosts[i])
|
|
off += len(ds.Hosts[i])
|
|
}
|
|
}
|
|
|
|
func (ds *DataSource) DecodeBinaryFrom(b []byte) uint32 {
|
|
ds.FileOffset = binary.BigEndian.Uint64(b[:8])
|
|
ds.PartitionID = binary.BigEndian.Uint64(b[8:16])
|
|
ds.ExtentID = binary.BigEndian.Uint64(b[16:24])
|
|
ds.ExtentOffset = binary.BigEndian.Uint64(b[24:32])
|
|
ds.Size_ = binary.BigEndian.Uint64(b[32:40])
|
|
hostLen := binary.BigEndian.Uint16(b[40:42])
|
|
off := 42
|
|
ds.Hosts = make([]string, 0)
|
|
for i := uint16(0); i < hostLen; i++ {
|
|
l := b[off]
|
|
off += 1
|
|
ds.Hosts = append(ds.Hosts, string(b[off:uint8(off)+l]))
|
|
off += int(l)
|
|
}
|
|
return uint32(off)
|
|
}
|
|
|
|
func (ds *DataSource) EncodeBinaryLen() int {
|
|
hostsLen := 0
|
|
for i := 0; i < len(ds.Hosts); i++ {
|
|
hostsLen += 1 + len(ds.Hosts[i])
|
|
}
|
|
return 40 + 2 + hostsLen
|
|
}
|
|
|
|
func (cr *CacheRequest) DecodeBinaryFrom(b []byte) {
|
|
volLen := binary.BigEndian.Uint16(b[:2])
|
|
cr.Volume = string(b[2 : 2+volLen])
|
|
off := 2 + uint32(volLen)
|
|
cr.FixedFileOffset = binary.BigEndian.Uint64(b[off : off+8]) // FixedFileOffset (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Inode = binary.BigEndian.Uint64(b[off : off+8]) // Inode (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Version = binary.BigEndian.Uint32(b[off : off+4]) // Version (uint32, 4 bytes)
|
|
off += 4
|
|
cr.TTL = int64(binary.BigEndian.Uint64(b[off : off+8])) // TTL (uint64, 8 bytes)
|
|
off += 8
|
|
sourceNum := binary.BigEndian.Uint32(b[off : off+4]) // Number of sources (uint32, 4 bytes)
|
|
off += 4
|
|
cr.Sources = make([]*DataSource, 0)
|
|
for i := uint32(0); i < sourceNum; i++ {
|
|
source := new(DataSource)
|
|
sourceLen := binary.BigEndian.Uint16(b[off : off+2])
|
|
off += 2
|
|
source.DecodeBinaryFrom(b[off : off+uint32(sourceLen)])
|
|
off += uint32(sourceLen)
|
|
cr.Sources = append(cr.Sources, source)
|
|
}
|
|
}
|
|
|
|
func (cr *CacheRequest) EncodeBinaryTo(b []byte) {
|
|
binary.BigEndian.PutUint16(b[:2], uint16(len(cr.Volume))) // Length of Volume (uint16, 2bytes)
|
|
copy(b[2:2+len(cr.Volume)], cr.Volume) // Volume
|
|
off := 2 + len(cr.Volume)
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.FixedFileOffset) // FixedFileOffset (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Inode) // Inode (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint32(b[off:off+4], cr.Version) // Version (uint32, 4 bytes)
|
|
off += 4
|
|
binary.BigEndian.PutUint64(b[off:off+8], uint64(cr.TTL)) // TTL (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint32(b[off:off+4], uint32(len(cr.Sources))) // Number of sources (uint32, 4 bytes)
|
|
off += 4
|
|
for i := 0; i < len(cr.Sources); i++ {
|
|
sourceLen := cr.Sources[i].EncodeBinaryLen()
|
|
binary.BigEndian.PutUint16(b[off:off+2], uint16(sourceLen))
|
|
off += 2
|
|
cr.Sources[i].EncodeBinaryTo(b[off : off+sourceLen])
|
|
off += sourceLen
|
|
}
|
|
}
|
|
|
|
func (cr *CacheRequest) EncodeBinaryLen() int {
|
|
var sourcesLen int
|
|
for i := 0; i < len(cr.Sources); i++ {
|
|
sourcesLen += 2 + cr.Sources[i].EncodeBinaryLen()
|
|
}
|
|
return 2 + len(cr.Volume) + 8 + 8 + 4 + 4 + sourcesLen + 8
|
|
}
|
|
|
|
func (cr *CacheReadRequest) EncodeBinaryTo(b []byte) {
|
|
var off int
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Offset)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Size_)
|
|
off += 8
|
|
crLen := cr.CacheRequest.EncodeBinaryLen()
|
|
binary.BigEndian.PutUint32(b[off:off+4], uint32(crLen))
|
|
off += 4
|
|
cr.CacheRequest.EncodeBinaryTo(b[off : off+crLen])
|
|
}
|
|
|
|
func (cr *CacheReadRequest) DecodeBinaryFrom(b []byte) {
|
|
var off uint32
|
|
cr.Offset = binary.BigEndian.Uint64(b[off : off+8])
|
|
off += 8
|
|
cr.Size_ = binary.BigEndian.Uint64(b[off : off+8])
|
|
off += 8
|
|
crLen := binary.BigEndian.Uint32(b[off : off+4])
|
|
off += 4
|
|
cr.CacheRequest = new(CacheRequest)
|
|
cr.CacheRequest.DecodeBinaryFrom(b[off:crLen])
|
|
}
|
|
|
|
func (cr *CacheReadRequest) EncodeBinaryLen() int {
|
|
return 4 + cr.CacheRequest.EncodeBinaryLen() + 8 + 8
|
|
}
|
|
|
|
func (ds *DataSource) String() string {
|
|
if ds == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("FileOffset(%v) PartitionID(%v) ExtentID(%v) ExtentOffset(%v) Size(%v) Hosts(%v)", ds.FileOffset, ds.PartitionID, ds.ExtentID, ds.ExtentOffset, ds.Size_, ds.Hosts)
|
|
}
|
|
|
|
func (cacheReq *CacheRequest) String() string {
|
|
if cacheReq == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("CacheRequest[Volume(%v) Inode(%v) FixedFileOffset(%v) Sources(%v) TTL(%v) ]", cacheReq.Volume, cacheReq.Inode, cacheReq.FixedFileOffset, len(cacheReq.Sources), cacheReq.TTL)
|
|
}
|
|
|
|
func (cr *CacheReadRequest) String() string {
|
|
if cr == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("cacheReadRequest[Volume(%v) Inode(%v) FixedFileOffset(%v) Sources(%v) TTL(%v) Offset(%v) Size(%v)]",
|
|
cr.CacheRequest.Volume, cr.CacheRequest.Inode, cr.CacheRequest.FixedFileOffset, len(cr.CacheRequest.Sources), cr.CacheRequest.TTL, cr.Offset, cr.Size_)
|
|
}
|
|
|
|
func (pr *CachePrepareRequest) String() string {
|
|
if pr == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("cachePrepareRequest[Volume(%v) Inode(%v) FixedFileOffset(%v) Sources(%v) TTL(%v)]", pr.CacheRequest.Volume, pr.CacheRequest.Inode, pr.CacheRequest.FixedFileOffset, len(pr.CacheRequest.Sources), pr.CacheRequest.TTL)
|
|
}
|
|
|
|
func (pbh *PutBlockHead) String() string {
|
|
if pbh == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("PutBlockHead[UniKey(%v) BlockLen(%v) TTL(%v)]", pbh.UniKey, pbh.BlockLen, pbh.TTL)
|
|
}
|
|
|
|
func (m *BatchReadItem) String() string {
|
|
if m == nil {
|
|
return "BatchReadItem(nil)"
|
|
}
|
|
return fmt.Sprintf("BatchReadItem[Key(%s) Offset(%d) Size(%d) Slot(%d) ReqId(%d) Tid(%s)]",
|
|
m.Key, m.Offset, m.Size_, m.Slot, m.ReqId, m.Tid)
|
|
}
|
|
|
|
func (m *BatchReadReq) String() string {
|
|
if m == nil {
|
|
return "BatchReadReq(nil)"
|
|
}
|
|
return fmt.Sprintf("BatchReadReq[Deadline(%d) len(%d)]",
|
|
m.Deadline, len(m.Items))
|
|
}
|
|
|
|
func (m *ReadResult) String() string {
|
|
if m == nil {
|
|
return "ReadResult(nil)"
|
|
}
|
|
dataLen := 0
|
|
if m.Data != nil {
|
|
dataLen = len(m.Data)
|
|
}
|
|
return fmt.Sprintf("ReadResult[ReqId(%d) ResultCode(%d) CRC(%d) DataLen(%d)]",
|
|
m.ReqId, m.ResultCode, m.CRC, dataLen)
|
|
}
|
|
|
|
func (m *BatchReadResp) String() string {
|
|
if m == nil {
|
|
return "BatchReadResp(nil)"
|
|
}
|
|
return fmt.Sprintf("BatchReadResp[%d]", len(m.Results))
|
|
}
|
|
|
|
func (cr *CacheReadRequestBase) DecodeBinaryFrom(b []byte) {
|
|
keyLen := binary.BigEndian.Uint16(b[:2])
|
|
cr.Key = string(b[2 : 2+keyLen])
|
|
off := 2 + uint32(keyLen)
|
|
cr.TTL = int64(binary.BigEndian.Uint64(b[off : off+8])) // TTL (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Slot = binary.BigEndian.Uint64(b[off : off+8]) // Slot (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Offset = binary.BigEndian.Uint64(b[off : off+8]) // Offset (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Size_ = binary.BigEndian.Uint64(b[off : off+8]) // Size (uint64, 8 bytes)
|
|
off += 8
|
|
cr.Deadline = binary.BigEndian.Uint64(b[off : off+8]) // Deadline (uint64, 8 bytes)
|
|
}
|
|
|
|
func (cr *CacheReadRequestBase) EncodeBinaryTo(b []byte) {
|
|
binary.BigEndian.PutUint16(b[:2], uint16(len(cr.Key))) // Length of Key (uint16, 2bytes)
|
|
copy(b[2:2+len(cr.Key)], cr.Key) // Key
|
|
off := 2 + len(cr.Key)
|
|
binary.BigEndian.PutUint64(b[off:off+8], uint64(cr.TTL)) // TTL (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Slot) // Slot (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Offset) // Offset (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Size_) // Size (uint64, 8 bytes)
|
|
off += 8
|
|
binary.BigEndian.PutUint64(b[off:off+8], cr.Deadline) // Deadline (uint64, 8 bytes)
|
|
}
|
|
|
|
func (cr *CacheReadRequestBase) EncodeBinaryLen() int {
|
|
return 2 + len(cr.Key) + 8 + 8 + 8 + 8 + 8
|
|
}
|
|
|
|
func (cr *CacheReadRequestBase) String() string {
|
|
if cr == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("cacheReadRequestBase[Key(%v) TTL(%v) Slot(%v) Offset(%v) Size(%v) Deadline(%v)]",
|
|
cr.Key, cr.TTL, cr.Slot, cr.Offset, cr.Size_, cr.Deadline)
|
|
}
|
|
|
|
type FlashGroupsAdminView struct {
|
|
FlashGroups []FlashGroupAdminView
|
|
}
|
|
|
|
type FlashGroupAdminView struct {
|
|
ID uint64
|
|
Slots []uint32
|
|
ReservedSlots []uint32
|
|
IsReducingSlots bool
|
|
Weight uint32
|
|
Status FlashGroupStatus
|
|
SlotStatus SlotStatus
|
|
PendingSlots []uint32
|
|
Step uint32
|
|
FlashNodeCount int
|
|
ZoneFlashNodes map[string][]*FlashNodeViewInfo
|
|
}
|
|
|
|
type FlashNodeViewInfo struct {
|
|
ID uint64
|
|
Addr string
|
|
ReportTime time.Time
|
|
IsActive bool
|
|
Version string
|
|
ZoneName string
|
|
FlashGroupID uint64
|
|
IsEnable bool
|
|
DiskStat []*FlashNodeDiskCacheStat
|
|
LimiterStatus *FlashNodeLimiterStatusInfo
|
|
}
|
|
|
|
type FlashNodeStat struct {
|
|
WaitForCacheBlock bool
|
|
NodeLimit uint64
|
|
VolLimit map[string]uint64
|
|
CacheStatus []*CacheStatus
|
|
}
|
|
|
|
type FlashWriteParam struct {
|
|
Offset int64
|
|
Size int64
|
|
Data []byte
|
|
Crc []byte
|
|
DataSize int64
|
|
}
|
|
|
|
type CacheStatus struct {
|
|
DataPath string `json:"data_path"`
|
|
Medium string `json:"medium"`
|
|
MaxAlloc int64 `json:"max_alloc"`
|
|
HasAlloc int64 `json:"has_alloc"`
|
|
Used int64 `json:"used"`
|
|
Total int64 `json:"total"`
|
|
HitRate float64 `json:"hit_rate"`
|
|
Evicts int `json:"evicts"`
|
|
Num int `json:"num"`
|
|
Capacity int `json:"capacity"`
|
|
Keys []string `json:"keys"`
|
|
Status int `json:"status"`
|
|
}
|
|
|
|
type SlotStat struct {
|
|
SlotId uint32 `json:"slot_id"`
|
|
OwnerSlotId uint32 `json:"owner_slot_id"`
|
|
HitCount uint32 `json:"hit_count"`
|
|
HitRate float64 `json:"hit_rate"`
|
|
RecentTime time.Time `json:"recent_time"`
|
|
}
|
|
|
|
type FlashNodeSlotStat struct {
|
|
NodeId uint64
|
|
Addr string
|
|
SlotStat []*SlotStat
|
|
}
|
|
|
|
type RemoteCacheConfig struct {
|
|
FlashNodeHandleReadTimeout int
|
|
FlashNodeReadDataNodeTimeout int
|
|
RemoteCacheTTL int64
|
|
RemoteCacheReadTimeout int64
|
|
RemoteCacheMultiRead bool
|
|
FlashNodeTimeoutCount int64
|
|
RemoteCacheSameZoneTimeout int64
|
|
RemoteCacheSameRegionTimeout int64
|
|
FlashHotKeyMissCount int
|
|
FlashReadFlowLimit int64
|
|
FlashWriteFlowLimit int64
|
|
FlashKeyFlowLimit int64
|
|
RemoteClientFlowLimit int64
|
|
WriteChunkSize int64
|
|
}
|
|
|
|
func ComputeSourcesVersion(sources []*DataSource, gen uint64) (version uint32) {
|
|
if len(sources) == 0 {
|
|
return 0
|
|
}
|
|
crcData := make([]byte, len(sources)*32+8)
|
|
for i, s := range sources {
|
|
binary.BigEndian.PutUint64(crcData[i*32:i*32+8], s.PartitionID)
|
|
binary.BigEndian.PutUint64(crcData[i*32+8:i*32+16], s.ExtentID)
|
|
binary.BigEndian.PutUint64(crcData[i*32+16:i*32+24], s.ExtentOffset)
|
|
binary.BigEndian.PutUint64(crcData[i*32+24:i*32+32], s.Size_)
|
|
}
|
|
binary.BigEndian.PutUint64(crcData[len(sources)*32:len(sources)*32+8], gen)
|
|
return fastcrc32.Checksum(crcData)
|
|
}
|
|
|
|
func ComputeCacheBlockSlot(volume string, inode, fixedFileOffset uint64) uint32 {
|
|
volLen := len(volume)
|
|
buf := make([]byte, volLen+16)
|
|
copy(buf[:volLen], volume)
|
|
binary.BigEndian.PutUint64(buf[volLen:volLen+8], inode)
|
|
binary.BigEndian.PutUint64(buf[volLen+8:volLen+16], fixedFileOffset)
|
|
return fastcrc32.Checksum(buf)
|
|
}
|
|
|
|
type FlashManualTask struct {
|
|
Id string
|
|
Action string
|
|
VolName string
|
|
Status int
|
|
ManualTaskConfig ManualTaskConfig
|
|
ManualTaskStatistics *ManualTaskStatistics
|
|
StartTime *time.Time
|
|
UpdateTime *time.Time
|
|
EndTime *time.Time
|
|
Done bool
|
|
sync.Mutex
|
|
}
|
|
|
|
type ManualTaskConfig struct {
|
|
Prefix string
|
|
TraverseFileConcurrency int
|
|
HandlerFileConcurrency int
|
|
TotalFileSizeLimit int64
|
|
MinFileSizeLimit int64
|
|
MaxFileSizeLimit int64
|
|
WarmUpPathExpire int64
|
|
}
|
|
|
|
type ManualTaskStatistics struct {
|
|
TotalFileScannedNum int64
|
|
TotalFileCachedNum int64
|
|
TotalDirScannedNum int64
|
|
TotalExtentKeyNum int64
|
|
ErrorCacheNum int64
|
|
ErrorReadDirNum int64
|
|
TotalCacheSize int64
|
|
LastCacheSize int64
|
|
FlashNode string
|
|
}
|
|
|
|
type FlashNodeManualTaskRequest struct {
|
|
MasterAddr string
|
|
FnNodeAddr string
|
|
Task *FlashManualTask
|
|
}
|
|
|
|
type FlashNodeManualTaskResponse struct {
|
|
ID string
|
|
FlashNode string
|
|
StartTime *time.Time
|
|
EndTime *time.Time
|
|
UpdateTime *time.Time
|
|
Done bool
|
|
Status uint8
|
|
StartErr string
|
|
Volume string
|
|
RcvStop bool
|
|
ManualTaskStatistics
|
|
}
|
|
|
|
type FlashNodeManualTaskCommand struct {
|
|
ID string
|
|
Command string
|
|
}
|
|
|
|
type ScanItem struct {
|
|
ParentId uint64 `json:"pid"` // FileID value of the parent inode.
|
|
Inode uint64 `json:"inode"` // FileID value of the current inode.
|
|
Name string `json:"name"` // Name of the current dentry.
|
|
Path string `json:"path"` // Path of the current dentry.
|
|
Type uint32 `json:"type"` // Type of the current dentry.
|
|
Op string `json:"op"` // to warmup or check
|
|
Size uint64 `json:"size"` // for warmup: size of the current dentry
|
|
StorageClass uint32 `json:"sc"` // for warmup: storage class of the current dentry
|
|
WriteGen uint64 `json:"gen"` // for warmup: used to determine whether a file is modified
|
|
}
|
|
|
|
func (flt *FlashManualTask) GetPathPrefix() string {
|
|
return strings.TrimPrefix(strings.TrimRight(flt.ManualTaskConfig.Prefix, "/"), "/")
|
|
}
|
|
|
|
func (flt *FlashManualTask) SetResponse(taskRsp *FlashNodeManualTaskResponse) {
|
|
t := time.Now()
|
|
flt.UpdateTime = &t
|
|
if flt.ManualTaskStatistics == nil {
|
|
flt.ManualTaskStatistics = &ManualTaskStatistics{}
|
|
}
|
|
flt.ManualTaskStatistics.FlashNode = taskRsp.FlashNode
|
|
flt.ManualTaskStatistics.TotalFileScannedNum = taskRsp.TotalFileScannedNum
|
|
flt.ManualTaskStatistics.TotalFileCachedNum = taskRsp.TotalFileCachedNum
|
|
flt.ManualTaskStatistics.TotalDirScannedNum = taskRsp.TotalDirScannedNum
|
|
flt.ManualTaskStatistics.ErrorCacheNum = taskRsp.ErrorCacheNum
|
|
flt.ManualTaskStatistics.ErrorReadDirNum = taskRsp.ErrorReadDirNum
|
|
flt.ManualTaskStatistics.TotalCacheSize = taskRsp.TotalCacheSize
|
|
flt.ManualTaskStatistics.LastCacheSize = taskRsp.LastCacheSize
|
|
flt.Done = taskRsp.Done
|
|
}
|
|
|
|
type CacheMissEntry struct {
|
|
UniKey string
|
|
MissCount int32
|
|
expiration int64
|
|
}
|
|
|
|
func CacheMissExpired(info *CacheMissEntry) bool {
|
|
return time.Now().UnixNano() > info.expiration
|
|
}
|
|
|
|
func SetMissEntryExpiration(info *CacheMissEntry, t time.Duration) {
|
|
info.expiration = time.Now().Add(t).UnixNano()
|
|
}
|
|
|
|
func GetMissEntryExpiration(info *CacheMissEntry) int64 {
|
|
return info.expiration
|
|
}
|
|
|
|
func IsCacheUnRetryable(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
errStr := err.Error()
|
|
if strings.Contains(errStr, ErrorNoFlashGroup.Error()) || strings.Contains(errStr, ErrorNoAvailableHost.Error()) ||
|
|
strings.Contains(errStr, ErrorContextDeadLine.Error()) || strings.Contains(errStr, ErrorReadTimeout.Error()) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func IsCacheMissError(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
if strings.Contains(err.Error(), ErrorNotExistShouldCache.Error()) ||
|
|
strings.Contains(err.Error(), ErrorNotExistShouldNotCache.Error()) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
type WarmUpPathInfo struct {
|
|
DirPath string
|
|
VolName string
|
|
Expiration int64
|
|
StartTime int64
|
|
Status int32
|
|
FlashAddr string
|
|
LoadedCount int64
|
|
}
|
|
|
|
type WarmUpMetaResource struct {
|
|
DirPath string
|
|
ServerAddr string
|
|
}
|
|
|
|
func MarshalBinaryWPSlice(warmUpPaths []*WarmUpPathInfo) ([]byte, error) {
|
|
buff := bytes.NewBuffer([]byte{})
|
|
if err := buff.WriteByte(WarnMagicNumber); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := binary.Write(buff, binary.BigEndian, int32(len(warmUpPaths))); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, pathInfo := range warmUpPaths {
|
|
data, err := pathInfo.MarshalBinary()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := buff.Write(data); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return buff.Bytes(), nil
|
|
}
|
|
|
|
func (w *WarmUpPathInfo) MarshalBinary() ([]byte, error) {
|
|
buff := bytes.NewBuffer([]byte{})
|
|
if err := w.MarshalBinaryWithBuffer(buff); err != nil {
|
|
return nil, err
|
|
}
|
|
return buff.Bytes(), nil
|
|
}
|
|
|
|
func (w *WarmUpPathInfo) MarshalBinaryWithBuffer(buff *bytes.Buffer) error {
|
|
dirPathBytes := []byte(w.DirPath)
|
|
if err := binary.Write(buff, binary.BigEndian, uint32(len(dirPathBytes))); err != nil {
|
|
return err
|
|
}
|
|
if _, err := buff.Write(dirPathBytes); err != nil {
|
|
return err
|
|
}
|
|
volNameBytes := []byte(w.VolName)
|
|
if err := binary.Write(buff, binary.BigEndian, uint32(len(volNameBytes))); err != nil {
|
|
return err
|
|
}
|
|
if _, err := buff.Write(volNameBytes); err != nil {
|
|
return err
|
|
}
|
|
if err := binary.Write(buff, binary.BigEndian, w.Expiration); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UnmarshalBinaryWPSlice(data []byte) ([]*WarmUpPathInfo, error) {
|
|
if len(data) <= 0 {
|
|
return nil, fmt.Errorf("empty data")
|
|
}
|
|
magic := data[0]
|
|
if magic != WarnMagicNumber {
|
|
return nil, fmt.Errorf("invalid magic number: expected %d, got %d", WarnMagicNumber, magic)
|
|
}
|
|
buff := bytes.NewBuffer(data[1:])
|
|
var length int32
|
|
if err := binary.Read(buff, binary.BigEndian, &length); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
warmUpPaths := make([]*WarmUpPathInfo, length)
|
|
for i := int32(0); i < length; i++ {
|
|
pathInfo := &WarmUpPathInfo{}
|
|
if err := pathInfo.UnmarshalBinaryWithBuffer(buff); err != nil {
|
|
return nil, err
|
|
}
|
|
warmUpPaths[i] = pathInfo
|
|
}
|
|
|
|
return warmUpPaths, nil
|
|
}
|
|
|
|
func (w *WarmUpPathInfo) UnmarshalBinaryWithBuffer(buff *bytes.Buffer) error {
|
|
var dirPathLen uint32
|
|
if err := binary.Read(buff, binary.BigEndian, &dirPathLen); err != nil {
|
|
return err
|
|
}
|
|
dirPathBytes := make([]byte, dirPathLen)
|
|
if _, err := buff.Read(dirPathBytes); err != nil {
|
|
return err
|
|
}
|
|
w.DirPath = string(dirPathBytes)
|
|
|
|
var volNameLen uint32
|
|
if err := binary.Read(buff, binary.BigEndian, &volNameLen); err != nil {
|
|
return err
|
|
}
|
|
volNameBytes := make([]byte, volNameLen)
|
|
if _, err := buff.Read(volNameBytes); err != nil {
|
|
return err
|
|
}
|
|
w.VolName = string(volNameBytes)
|
|
if err := binary.Read(buff, binary.BigEndian, &w.Expiration); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *WarmUpPathInfo) UnmarshalBinary(data []byte) error {
|
|
return w.UnmarshalBinaryWithBuffer(bytes.NewBuffer(data))
|
|
}
|
|
|
|
func (w *WarmUpPathInfo) SetExpiration(t time.Duration) {
|
|
w.Expiration = time.Now().Add(t).UnixNano()
|
|
}
|