feat(master): cli support setting for persistting accessTime

Signed-off-by: chihe <chihe@oppo.com>
This commit is contained in:
chihe 2024-08-01 20:07:54 +08:00 committed by AmazingChi
parent 136ee9704e
commit a305b32b9c
16 changed files with 170 additions and 38 deletions

View File

@ -144,6 +144,8 @@ const (
CliFlagDecommissionDpLimit = "decommissionDpLimit"
CliFlagDecommissionDiskLimit = "decommissionDiskLimit"
CliFlagTrashInterval = "trashInterval"
CliFlagAccessTimeValidInterval = "accessTimeValidInterval"
CliFlagEnablePersistAccessTime = "enablePersistAccessTime"
// CliFlagSetDataPartitionCount = "count" use dp-count instead
// Shorthand format of resource name

View File

@ -182,7 +182,7 @@ func formatSimpleVolView(svv *proto.SimpleVolView) string {
sb.WriteString(fmt.Sprintf(" DpRepairBlockSize : %v\n", strutil.FormatSize(svv.DpRepairBlockSize)))
sb.WriteString(fmt.Sprintf(" EnableAutoDpMetaRepair : %v\n", svv.EnableAutoDpMetaRepair))
sb.WriteString(fmt.Sprintf(" Quota : %v\n", formatEnabledDisabled(svv.EnableQuota)))
sb.WriteString(fmt.Sprintf(" AccessTimeInterval : %v\n", time.Duration(svv.AccessTimeInterval)*time.Second))
sb.WriteString(fmt.Sprintf(" AccessTimeValidInterval : %v\n", time.Duration(svv.AccessTimeInterval)*time.Second))
sb.WriteString(fmt.Sprintf(" EnablePersistAccessTime : %v\n", svv.EnablePersistAccessTime))
if svv.Forbidden && svv.Status == 1 {
sb.WriteString(fmt.Sprintf(" DeleteDelayTime : %v\n", time.Until(svv.DeleteExecTime)))

View File

@ -294,6 +294,8 @@ func newVolUpdateCmd(client *master.MasterClient) *cobra.Command {
var optEnableQuota string
var optEnableDpAutoMetaRepair string
var optTrashInterval int64
var optAccessTimeValidInterval int64
var optEnablePersistAccessTime string
var confirmString = strings.Builder{}
var vv *proto.SimpleVolView
cmd := &cobra.Command{
@ -590,13 +592,51 @@ func newVolUpdateCmd(client *master.MasterClient) *cobra.Command {
if optTrashInterval >= 0 {
if optTrashInterval != vv.TrashInterval {
isChange = true
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v h -> %v h\n", vv.TrashInterval, optTrashInterval))
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v s -> %v s\n", vv.TrashInterval, optTrashInterval))
vv.TrashInterval = optTrashInterval
} else {
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v h\n", vv.TrashInterval))
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v s\n", vv.TrashInterval))
}
} else {
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v h\n", vv.TrashInterval))
confirmString.WriteString(fmt.Sprintf(" TrashInterval : %v s\n", vv.TrashInterval))
}
if optAccessTimeValidInterval >= 0 {
if optAccessTimeValidInterval < 1800 {
err = fmt.Errorf("AccessTimeValidInterval must greater than or equal to 1800\n")
return
}
if optAccessTimeValidInterval != vv.AccessTimeInterval {
isChange = true
confirmString.WriteString(fmt.Sprintf(" AccessTimeValidInterval : %v s -> %v h\n", vv.AccessTimeInterval, optAccessTimeValidInterval))
vv.AccessTimeInterval = optAccessTimeValidInterval
} else {
confirmString.WriteString(fmt.Sprintf(" AccessTimeValidInterval : %v s\n", vv.AccessTimeInterval))
}
} else {
confirmString.WriteString(fmt.Sprintf(" AccessTimeValidInterval : %v s\n", vv.AccessTimeInterval))
}
if optEnablePersistAccessTime != "" {
enablePersistAccessTime := false
if optEnablePersistAccessTime == "false" {
if vv.EnablePersistAccessTime {
isChange = true
}
}
if optEnablePersistAccessTime == "true" {
if !vv.EnablePersistAccessTime {
isChange = true
}
enablePersistAccessTime = true
}
if isChange {
confirmString.WriteString(fmt.Sprintf(" EnablePersistAccessTime : %v -> %v \n", vv.EnablePersistAccessTime, enablePersistAccessTime))
vv.EnablePersistAccessTime = enablePersistAccessTime
} else {
confirmString.WriteString(fmt.Sprintf(" EnablePersistAccessTime : %v \n", vv.EnablePersistAccessTime))
}
} else {
confirmString.WriteString(fmt.Sprintf(" EnablePersistAccessTime : %v \n", vv.EnablePersistAccessTime))
}
if optEnableDpAutoMetaRepair != "" {
enable := false
@ -675,6 +715,9 @@ func newVolUpdateCmd(client *master.MasterClient) *cobra.Command {
cmd.Flags().StringVar(&optEnableDpAutoMetaRepair, CliFlagAutoDpMetaRepair, "", "Enable or disable dp auto meta repair")
cmd.Flags().Int64Var(&optTrashInterval, CliFlagTrashInterval, -1, "The retention period for files in trash")
cmd.Flags().Int64Var(&optAccessTimeValidInterval, CliFlagAccessTimeValidInterval, -1, "Effective time interval for accesstime, at least 1800 [Unit: second]")
cmd.Flags().StringVar(&optEnablePersistAccessTime, CliFlagEnablePersistAccessTime, "", "true/false to enable/disable persisting access time")
return cmd
}

View File

@ -399,6 +399,8 @@ type updateVolReq struct {
crossZone bool
trashInterval int64
enableAutoDpMetaRepair bool
accessTimeValidInterval int64
enablePersistAccessTime bool
}
func parseColdVolUpdateArgs(r *http.Request, vol *Vol) (args *coldVolArgs, err error) {
@ -534,7 +536,13 @@ func parseVolUpdateReq(r *http.Request, vol *Vol, req *updateVolReq) (err error)
return
}
if req.trashInterval, err = extractInt64WithDefault(r, intervalKey, 0); err != nil {
if req.trashInterval, err = extractInt64WithDefault(r, trashIntervalKey, vol.TrashInterval); err != nil {
return
}
if req.accessTimeValidInterval, err = extractInt64WithDefault(r, accessTimeIntervalKey, vol.AccessTimeValidInterval); err != nil {
return
}
if req.enablePersistAccessTime, err = extractBoolWithDefault(r, enablePersistAccessTimeKey, vol.EnablePersistAccessTime); err != nil {
return
}
if req.enableAutoDpMetaRepair, err = extractBoolWithDefault(r, autoDpMetaRepairKey, vol.EnableAutoMetaRepair.Load()); err != nil {
@ -651,7 +659,7 @@ type coldVolArgs struct {
cacheLowWater int
cacheLRUInterval int
cacheRule string
accessTimeInterval int64
accessTimeValidInterval int64
trashInterval int64
enablePersistAccessTime bool
}
@ -682,6 +690,9 @@ type createVolReq struct {
txConflictRetryInterval int64
qosLimitArgs *qosArgs
clientReqPeriod, clientHitTriggerCnt uint32
trashInterval int64
accessTimeValidInterval int64
enablePersistAccessTime bool
// cold vol args
coldArgs coldVolArgs
}
@ -852,6 +863,15 @@ func parseRequestToCreateVol(r *http.Request, req *createVolReq) (err error) {
return
}
if req.trashInterval, err = extractInt64WithDefault(r, trashIntervalKey, 0); err != nil {
return
}
if req.accessTimeValidInterval, err = extractInt64WithDefault(r, accessTimeIntervalKey, proto.DefaultAccessTimeValidInterval); err != nil {
return
}
if req.enablePersistAccessTime, err = extractBoolWithDefault(r, enablePersistAccessTimeKey, false); err != nil {
return
}
return
}
@ -1047,6 +1067,18 @@ func extractStatus(r *http.Request) (status bool, err error) {
return
}
func extractPersistStatus(r *http.Request) (status bool, err error) {
var value string
if value = r.FormValue(enablePersistAccessTimeKey); value == "" {
err = keyNotFound(enablePersistAccessTimeKey)
return
}
if status, err = strconv.ParseBool(value); err != nil {
return
}
return
}
func extractForbidden(r *http.Request) (forbidden bool, err error) {
var value string
if value = r.FormValue(forbiddenKey); value == "" {
@ -1953,7 +1985,7 @@ func extractInodeId(r *http.Request) (inode uint64, err error) {
return strconv.ParseUint(value, 10, 64)
}
func parseRequestToSetInterval(r *http.Request) (name, authKey string, interval int64, err error) {
func parseRequestToSetTrashInterval(r *http.Request) (name, authKey string, interval int64, err error) {
if err = r.ParseForm(); err != nil {
return
}
@ -1964,12 +1996,13 @@ func parseRequestToSetInterval(r *http.Request) (name, authKey string, interval
if authKey, err = extractAuthKey(r); err != nil {
return
}
if interval, err = extractInt64WithDefault(r, intervalKey, 0); err != nil {
if interval, err = extractInt64WithDefault(r, trashIntervalKey, 0); err != nil {
return
}
return
}
func parseRequestToSetPersist(r *http.Request) (name, authKey string, enable bool, err error) {
func parseRequestToSetAccessTimeInterval(r *http.Request) (name, authKey string, interval int64, err error) {
if err = r.ParseForm(); err != nil {
return
}
@ -1980,7 +2013,24 @@ func parseRequestToSetPersist(r *http.Request) (name, authKey string, enable boo
if authKey, err = extractAuthKey(r); err != nil {
return
}
if enable, err = extractStatus(r); err != nil {
if interval, err = extractInt64WithDefault(r, accessTimeIntervalKey, 0); err != nil {
return
}
return
}
func parseRequestToSetPersistAccessTime(r *http.Request) (name, authKey string, enable bool, err error) {
if err = r.ParseForm(); err != nil {
return
}
if name, err = extractName(r); err != nil {
return
}
if authKey, err = extractAuthKey(r); err != nil {
return
}
if enable, err = extractPersistStatus(r); err != nil {
return
}
return

View File

@ -2333,6 +2333,8 @@ func (m *Server) updateVol(w http.ResponseWriter, r *http.Request) {
newArgs.txOpLimit = req.txOpLimit
newArgs.enableQuota = req.enableQuota
newArgs.trashInterval = req.trashInterval
newArgs.accessTimeValidInterval = req.accessTimeValidInterval
newArgs.enablePersistAccessTime = req.enablePersistAccessTime
if req.coldArgs != nil {
newArgs.coldArgs = req.coldArgs
}
@ -2537,6 +2539,9 @@ func (m *Server) checkCreateReq(req *createVolReq) (err error) {
return fmt.Errorf("dp replicaNum %d can't be large than dataNodeCnt %d", req.dpReplicaNum, m.cluster.dataNodeCount())
}
if req.accessTimeValidInterval < proto.MinAccessTimeValidInterval {
return fmt.Errorf("accessTimeValidInterval must greater than or equal to 1800")
}
req.coldArgs = args
return nil
}
@ -2726,7 +2731,7 @@ func newSimpleView(vol *Vol) (view *proto.SimpleVolView) {
DeleteExecTime: vol.DeleteExecTime,
DpRepairBlockSize: vol.dpRepairBlockSize,
EnableAutoDpMetaRepair: vol.EnableAutoMetaRepair.Load(),
AccessTimeInterval: vol.AccessTimeInterval,
AccessTimeInterval: vol.AccessTimeValidInterval,
EnablePersistAccessTime: vol.EnablePersistAccessTime,
}

View File

@ -3367,8 +3367,11 @@ func (c *Cluster) doCreateVol(req *createVolReq) (vol *Vol, err error) {
FlowRlimit: req.qosLimitArgs.flowRVal,
FlowWlimit: req.qosLimitArgs.flowWVal,
DpReadOnlyWhenVolFull: req.DpReadOnlyWhenVolFull,
EnableAutoMetaRepair: false,
DpReadOnlyWhenVolFull: req.DpReadOnlyWhenVolFull,
EnableAutoMetaRepair: false,
TrashInterval: req.trashInterval,
AccessTimeInterval: req.accessTimeValidInterval,
EnablePersistAccessTime: req.enablePersistAccessTime,
}
log.LogInfof("[doCreateVol] volView, %v", vv)

View File

@ -147,6 +147,9 @@ const (
dpTimeoutKey = "dpTimeout"
ShowAll = "showAll"
intervalKey = "interval"
trashIntervalKey = "trashInterval"
accessTimeIntervalKey = "accessTimeValidInterval"
enablePersistAccessTimeKey = "enablePersistAccessTime"
)
const (

View File

@ -397,7 +397,7 @@ func newVolValue(vol *Vol) (vv *volValue) {
User: vol.user,
DpRepairBlockSize: vol.dpRepairBlockSize,
EnableAutoMetaRepair: vol.EnableAutoMetaRepair.Load(),
AccessTimeInterval: vol.AccessTimeInterval,
AccessTimeInterval: vol.AccessTimeValidInterval,
EnablePersistAccessTime: vol.EnablePersistAccessTime,
}

View File

@ -55,6 +55,7 @@ type VolVarargs struct {
crossZone bool
accessTimeInterval int64
enableAutoDpMetaRepair bool
accessTimeValidInterval int64
enablePersistAccessTime bool
}
@ -138,6 +139,7 @@ type Vol struct {
ReadOnlyForVolFull bool // only if the switch DpReadOnlyWhenVolFull is on, mark vol is readonly when is full
AccessTimeInterval int64
EnablePersistAccessTime bool
AccessTimeValidInterval int64
EnableAutoMetaRepair atomicutil.Bool
TopoSubItem
@ -221,6 +223,10 @@ func newVol(vv volValue) (vol *Vol) {
vol.preloadCapacity = math.MaxUint64 // mark as special value to trigger calculate
vol.dpRepairBlockSize = proto.DefaultDpRepairBlockSize
vol.EnableAutoMetaRepair.Store(defaultEnableDpMetaRepair)
vol.preloadCapacity = math.MaxUint64 //mark as special value to trigger calculate
vol.TrashInterval = vv.TrashInterval
vol.AccessTimeValidInterval = vv.AccessTimeInterval
vol.EnablePersistAccessTime = vv.EnablePersistAccessTime
return
}
@ -253,7 +259,10 @@ func newVolFromVolValue(vv *volValue) (vol *Vol) {
}
vol.EnableAutoMetaRepair.Store(vv.EnableAutoMetaRepair)
vol.EnablePersistAccessTime = vv.EnablePersistAccessTime
vol.AccessTimeInterval = vv.AccessTimeInterval
vol.AccessTimeValidInterval = vv.AccessTimeInterval
if vol.AccessTimeValidInterval == 0 {
vol.AccessTimeValidInterval = proto.DefaultAccessTimeValidInterval
}
return vol
}
@ -1604,6 +1613,7 @@ func setVolFromArgs(args *VolVarargs, vol *Vol) {
vol.dpSelectorName = args.dpSelectorName
vol.dpSelectorParm = args.dpSelectorParm
vol.TrashInterval = args.trashInterval
vol.AccessTimeValidInterval = args.accessTimeValidInterval
vol.AccessTimeInterval = args.accessTimeInterval
vol.EnableAutoMetaRepair.Store(args.enableAutoDpMetaRepair)
vol.EnablePersistAccessTime = args.enablePersistAccessTime
@ -1620,7 +1630,7 @@ func getVolVarargs(vol *Vol) *VolVarargs {
cacheLowWater: vol.CacheLowWater,
cacheLRUInterval: vol.CacheLRUInterval,
cacheRule: vol.CacheRule,
accessTimeInterval: vol.AccessTimeInterval,
accessTimeValidInterval: vol.AccessTimeValidInterval,
trashInterval: vol.TrashInterval,
enablePersistAccessTime: vol.EnablePersistAccessTime,
}
@ -1645,7 +1655,7 @@ func getVolVarargs(vol *Vol) *VolVarargs {
txOpLimit: vol.txOpLimit,
coldArgs: args,
dpReadOnlyWhenVolFull: vol.DpReadOnlyWhenVolFull,
accessTimeInterval: vol.AccessTimeInterval,
accessTimeValidInterval: vol.AccessTimeValidInterval,
trashInterval: vol.TrashInterval,
enablePersistAccessTime: vol.EnablePersistAccessTime,
enableAutoDpMetaRepair: vol.EnableAutoMetaRepair.Load(),

View File

@ -355,7 +355,7 @@ func (m *MetaNode) getInodeHandler(w http.ResponseWriter, r *http.Request) {
}
finalResp := &proto.InodeGetWithPersistAccessTimeResponse{}
finalResp.Info = inodeResp.Info
finalResp.PersistAccessTime = persistAtResp.Info.AccessTime
finalResp.Info.PersistAccessTime = persistAtResp.Info.AccessTime
resp.Data = finalResp
return
}

View File

@ -1735,7 +1735,7 @@ func (mp *metaPartition) GetVolName() (volName string) {
func (mp *metaPartition) GetAccessTimeValidInterval() time.Duration {
interval := atomic.LoadUint64(&mp.accessTimeValidInterval)
if interval == 0 {
return 0
return proto.DefaultAccessTimeValidInterval
}
return time.Duration(interval)
}

View File

@ -89,6 +89,9 @@ func (mp *metaPartition) UpdateVolumeView(dataView *proto.DataPartitionsView, vo
mp.vol.UpdatePartitions(convert(dataView))
mp.vol.volDeleteLockTime = volumeView.DeleteLockTime
mp.enablePersistAccessTime = volumeView.EnablePersistAccessTime
if volumeView.AccessTimeInterval <= proto.MinAccessTimeValidInterval {
volumeView.AccessTimeInterval = proto.MinAccessTimeValidInterval
}
atomic.StoreUint64(&mp.accessTimeValidInterval, uint64(volumeView.AccessTimeInterval))
}

View File

@ -645,9 +645,10 @@ func (mp *metaPartition) persistInodeAccessTime(inode uint64, p *Packet) {
}
ino := item.(*Inode)
ctime := Now.GetCurrentTimeUnix()
if !(ctime > ino.AccessTime && time.Now().Sub(time.Unix(ino.AccessTime, 0)) > mp.GetAccessTimeValidInterval()*time.Second) {
at := time.Unix(ino.AccessTime, 0)
if !(ctime > ino.AccessTime && time.Now().Sub(at) > mp.GetAccessTimeValidInterval()*time.Second) {
log.LogDebugf("%v %v %v", ctime > ino.AccessTime,
time.Now().Sub(time.Unix(ino.AccessTime, 0)) > mp.GetAccessTimeValidInterval(), mp.accessTimeValidInterval)
time.Now().Sub(at) > mp.GetAccessTimeValidInterval(), mp.GetAccessTimeValidInterval())
return
}
var (
@ -658,7 +659,7 @@ func (mp *metaPartition) persistInodeAccessTime(inode uint64, p *Packet) {
)
// always update local AccessTime
ino.AccessTime = ctime
log.LogDebugf("persistInodeAccessTime ino(%v) persist at to %v", ino.Inode, time.Unix(ino.AccessTime, 0))
log.LogDebugf("persistInodeAccessTime ino(%v) persist at to %v", ino.Inode, at)
if leaderAddr, ok := mp.IsLeader(); ok {
// sync AccessTime to followers
val, err = ino.Marshal()
@ -682,12 +683,13 @@ func (mp *metaPartition) persistInodeAccessTime(inode uint64, p *Packet) {
m.connPool.PutConnect(mConn, ForceClosedConnect)
return
}
if err = p.WriteToConn(mConn); err != nil {
packetCopy := p.GetCopy()
if err = packetCopy.WriteToConn(mConn); err != nil {
log.LogWarnf("persistInodeAccessTime ino(%v) write to connect failed %v", ino.Inode, err)
m.connPool.PutConnect(mConn, ForceClosedConnect)
return
}
if err = p.ReadFromConn(mConn, proto.NoReadDeadlineTime); err != nil {
if err = packetCopy.ReadFromConn(mConn, proto.NoReadDeadlineTime); err != nil {
log.LogWarnf("persistInodeAccessTime ino(%v) read from connect failed %v", ino.Inode, err)
m.connPool.PutConnect(mConn, ForceClosedConnect)
return

View File

@ -80,20 +80,21 @@ func IsAncestor(parent, child string) bool {
// InodeInfo defines the inode struct.
type InodeInfo struct {
Inode uint64 `json:"ino"`
Mode uint32 `json:"mode"`
Nlink uint32 `json:"nlink"`
Size uint64 `json:"sz"`
Uid uint32 `json:"uid"`
Gid uint32 `json:"gid"`
Generation uint64 `json:"gen"`
ModifyTime time.Time `json:"mt"`
CreateTime time.Time `json:"ct"`
AccessTime time.Time `json:"at"`
Target []byte `json:"tgt"`
QuotaInfos map[uint32]*MetaQuotaInfo `json:"qifs"`
VerSeq uint64 `json:"seq"`
expiration int64
Inode uint64 `json:"ino"`
Mode uint32 `json:"mode"`
Nlink uint32 `json:"nlink"`
Size uint64 `json:"sz"`
Uid uint32 `json:"uid"`
Gid uint32 `json:"gid"`
Generation uint64 `json:"gen"`
ModifyTime time.Time `json:"mt"`
CreateTime time.Time `json:"ct"`
AccessTime time.Time `json:"at"`
Target []byte `json:"tgt"`
QuotaInfos map[uint32]*MetaQuotaInfo `json:"qifs"`
VerSeq uint64 `json:"seq"`
expiration int64
PersistAccessTime time.Time `json:"pat"`
}
type SimpleExtInfo struct {

View File

@ -38,6 +38,8 @@ const (
MinTxConflictRetryInterval = 10 // ms
DefaultTxDeleteTime = 120
ClearOrphanTxTime = 3600
DefaultAccessTimeValidInterval = 3600 * 24
MinAccessTimeValidInterval = 3600 * 12
MaxBufferSize = 1024 * 1024 * 1024 // 1GB
)

View File

@ -18,6 +18,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"time"
@ -295,6 +296,9 @@ func (api *AdminAPI) UpdateVolume(
request.addParam("autoDpMetaRepair", strconv.FormatBool(vv.EnableAutoDpMetaRepair))
request.addParam("clientIDKey", clientIDKey)
request.addParam("interval", strconv.FormatInt(vv.TrashInterval, 10))
request.addParam("trashInterval", strconv.FormatInt(vv.TrashInterval, 10))
request.addParam("accessTimeValidInterval", strconv.FormatInt(vv.AccessTimeInterval, 10))
request.addParam("enablePersistAccessTime", strconv.FormatBool(vv.EnablePersistAccessTime))
if txMask != "" {
request.addParam("enableTxMask", txMask)
@ -316,6 +320,10 @@ func (api *AdminAPI) UpdateVolume(
return
}
func stdout(format string, a ...interface{}) {
_, _ = fmt.Fprintf(os.Stdout, format, a...)
}
func (api *AdminAPI) PutDataPartitions(volName string, dpsView []byte) (err error) {
return api.mc.request(newRequest(post, proto.AdminPutDataPartitions).
Header(api.h).addParam("name", volName).Body(dpsView))