Skip to content

Commit

Permalink
(list-objects, scrub): version-changed, version-removed
Browse files Browse the repository at this point in the history
* scenarios: with and without `--cached`, `--check-versions`
* scrub to ask for version; drop atime
* core: `lom.CheckRemoteMD` will now always return remote meta
  - including version and custom
* x-lso:
  - lso entry: add head-fail flag; refactor
  - wanted-lso: do not override remote custom
  - when checking remote version:
   - use custom and version from lom.CheckRemoteMD (above)
   - but only if err nil

Signed-off-by: Alex Aizman <[email protected]>
  • Loading branch information
alex-aizman committed Jan 15, 2025
1 parent 476399d commit 939d7a6
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 55 deletions.
6 changes: 4 additions & 2 deletions api/apc/lsmsg.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Package apc: API control messages and constants
/*
* Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
*/
package apc

Expand Down Expand Up @@ -91,7 +91,7 @@ const (
)

const (
// Status
// location _status_
LocOK = iota
LocMisplacedNode
LocMisplacedMountpath
Expand All @@ -105,6 +105,8 @@ const (
EntryIsArchive = 1 << (EntryStatusBits + 4)
EntryVerChanged = 1 << (EntryStatusBits + 5) // see also: QparamLatestVer, et al.
EntryVerRemoved = 1 << (EntryStatusBits + 6) // ditto
// added v3.26
EntryHeadFail = 1 << (EntryStatusBits + 7)
)

// ObjEntry.Flags field
Expand Down
2 changes: 1 addition & 1 deletion cmd/cli/cli/scrub.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func (ctx *scrCtx) ls(bck cmn.Bck) (*scrBp, error) {
}
)
scr.Cname = bck.Cname("")
propNames := []string{apc.GetPropsName, apc.GetPropsSize, apc.GetPropsAtime, apc.GetPropsCopies, apc.GetPropsLocation, apc.GetPropsCustom}
propNames := []string{apc.GetPropsName, apc.GetPropsSize, apc.GetPropsVersion, apc.GetPropsCopies, apc.GetPropsLocation, apc.GetPropsCustom}
if bck.IsRemote() {
lsmsg.Flags |= apc.LsVerChanged
lsmsg.AddProps(propNames...)
Expand Down
4 changes: 2 additions & 2 deletions cmd/cli/teb/scrub.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ const (
colMissingCp = "MISSING-CP"
colSmallSz = "SMALL"
colLargeSz = "LARGE"
colVchanged = "VERSION-CHANGED"
colVremoved = "VERSION-REMOVED"
colVchanged = "VER-CHANGED"
colVremoved = "VER-REMOVED"
)

const (
Expand Down
7 changes: 5 additions & 2 deletions cmn/objattrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,11 @@ func (oa *ObjAttrs) FromHeader(hdr http.Header) (cksum *cos.Cksum) {
// b) the same remote "source" and at least one matching checksum, or c) two matching checksums.
// (See also note below.)
//
// Note that mismatch in any given checksum type immediately renders inequality and return
// from the function.
// Note that ETag, checksum, or version mismatch leads to immediate return with error
// specifying the exact cause.
//
// Note version comparison may fail even when the objects are identical, content-wise:
// same size, ETag, and checksums may still "co-exist" with different versions.
//
// TODO: count == 1 with matching checksum being xxhash - must be configurable :NOTE
func (oa *ObjAttrs) CheckEq(rem cos.OAH) error {
Expand Down
9 changes: 3 additions & 6 deletions cmn/objlist_utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Package cmn provides common constants, types, and utilities for AIS clients
// and AIStore.
/*
* Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
*/
package cmn

Expand Down Expand Up @@ -67,11 +67,8 @@ func appSorted(entries LsoEntries, ne *LsoEnt) LsoEntries {
func (be *LsoEnt) IsPresent() bool { return be.Flags&apc.EntryIsCached != 0 }
func (be *LsoEnt) SetPresent() { be.Flags |= apc.EntryIsCached }

// see also: "latest-ver", QparamLatestVer, et al.
func (be *LsoEnt) SetVerChanged() { be.Flags |= apc.EntryVerChanged }
func (be *LsoEnt) IsVerChanged() bool { return be.Flags&apc.EntryVerChanged != 0 }
func (be *LsoEnt) SetVerRemoved() { be.Flags |= apc.EntryVerRemoved }
func (be *LsoEnt) IsVerRemoved() bool { return be.Flags&apc.EntryVerRemoved != 0 }
func (be *LsoEnt) SetFlag(fl uint16) { be.Flags |= fl }
func (be *LsoEnt) IsAnyFlagSet(fl uint16) bool { return be.Flags&fl != 0 }

func (be *LsoEnt) IsStatusOK() bool { return be.Status() == 0 }
func (be *LsoEnt) Status() uint16 { return be.Flags & apc.EntryStatusMask }
Expand Down
6 changes: 3 additions & 3 deletions core/ldp.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Package core provides core metadata and in-cluster API
/*
* Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
*/
package core

Expand Down Expand Up @@ -143,7 +143,7 @@ func (lom *LOM) CheckRemoteMD(locked, sync bool, origReq *http.Request) (res CRM

if !locked {
// return info (neq and, possibly, not-found), and be done
return CRMD{ErrCode: ecode, Err: err}
return CRMD{ObjAttrs: oa, ErrCode: ecode, Err: err}
}

// rm remotely-deleted
Expand All @@ -160,7 +160,7 @@ func (lom *LOM) CheckRemoteMD(locked, sync bool, origReq *http.Request) (res CRM
}

lom.Uncache()
return CRMD{ErrCode: ecode, Err: err}
return CRMD{ObjAttrs: oa, ErrCode: ecode, Err: err}
}

// NOTE: Sync is false (ie., not deleting)
Expand Down
14 changes: 7 additions & 7 deletions xact/xs/nextpage.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Package xs is a collection of eXtended actions (xactions), including multi-object
// operations, list-objects, (cluster) rebalance and (target) resilver, ETL, and more.
/*
* Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
*/
package xs

Expand Down Expand Up @@ -112,19 +112,19 @@ func (npg *npgCtx) nextPageR(nentries cmn.LsoEntries, inclStatusLocalMD bool) (l

func (npg *npgCtx) populate(lst *cmn.LsoRes) error {
post := npg.wi.lomVisitedCb
for _, obj := range lst.Entries {
if obj.IsDir() {
for _, en := range lst.Entries {
if en.IsDir() {
// collecting virtual dir-s when apc.LsNoRecursion is on - skipping here
continue
}
si, err := npg.wi.smap.HrwName2T(npg.bck.MakeUname(obj.Name))
si, err := npg.wi.smap.HrwName2T(npg.bck.MakeUname(en.Name))
if err != nil {
return err
}
if si.ID() != core.T.SID() {
continue
}
lom := core.AllocLOM(obj.Name)
lom := core.AllocLOM(en.Name)
if err := lom.InitBck(npg.bck.Bucket()); err != nil {
core.FreeLOM(lom)
if cmn.IsErrBucketNought(err) {
Expand All @@ -137,8 +137,8 @@ func (npg *npgCtx) populate(lst *cmn.LsoRes) error {
continue
}

npg.wi.setWanted(obj, lom)
obj.SetPresent()
npg.wi.setWanted(en, lom)
en.SetPresent()

if post != nil {
post(lom)
Expand Down
53 changes: 33 additions & 20 deletions xact/xs/wanted_lso.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Package xs contains most of the supported eXtended actions (xactions) with some
// exceptions that include certain storage services (mirror, EC) and extensions (downloader, lru).
/*
* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2022-2025, NVIDIA CORPORATION. All rights reserved.
*/
package xs

Expand Down Expand Up @@ -35,7 +35,10 @@ func wanted(msg *apc.LsoMsg) (flags cos.BitFlags) {
return
}

func (wi *walkInfo) setWanted(e *cmn.LsoEnt, lom *core.LOM) {
func (wi *walkInfo) setWanted(en *cmn.LsoEnt, lom *core.LOM) {
var (
checkVchanged = wi.msg.IsFlagSet(apc.LsVerChanged)
)
for name, fl := range allmap {
if !wi.wanted.IsSet(fl) {
continue
Expand All @@ -46,41 +49,51 @@ func (wi *walkInfo) setWanted(e *cmn.LsoEnt, lom *core.LOM) {
case apc.GetPropsCached: // via obj.SetPresent()

case apc.GetPropsSize:
if e.Size > 0 && lom.Lsize() != e.Size {
e.SetVerChanged()
if en.Size > 0 && lom.Lsize() != en.Size {
en.SetFlag(apc.EntryVerChanged)
}
e.Size = lom.Lsize()
en.Size = lom.Lsize()
case apc.GetPropsVersion:
e.Version = lom.Version()
// remote VersionObjMD takes precedence over ais incremental numbering
if en.Version == "" {
en.Version = lom.Version()
}
case apc.GetPropsChecksum:
e.Checksum = lom.Checksum().Value()
en.Checksum = lom.Checksum().Value()
case apc.GetPropsAtime:
e.Atime = cos.FormatNanoTime(lom.AtimeUnix(), wi.msg.TimeFormat)
// atime vs remote LastModified
en.Atime = cos.FormatNanoTime(lom.AtimeUnix(), wi.msg.TimeFormat)
case apc.GetPropsLocation:
e.Location = lom.Location()
en.Location = lom.Location()
case apc.GetPropsCopies:
e.Copies = int16(lom.NumCopies())
en.Copies = int16(lom.NumCopies())

case apc.GetPropsEC:
// TODO?: risk of significant slow-down loading EC metafiles
// TODO at the risk of significant slow-down

case apc.GetPropsCustom:
if md := lom.GetCustomMD(); len(md) > 0 {
e.Custom = cmn.CustomMD2S(md)
// en.Custom is set via one of the two alternative flows:
// - checkRemoteMD => HEAD(obj)
// - backend.List* api call
if en.Custom == "" {
if md := lom.GetCustomMD(); len(md) > 0 {
en.Custom = cmn.CustomMD2S(md)
checkVchanged = false
}
}
default:
debug.Assert(false, name)
}
}
if wi.msg.IsFlagSet(apc.LsVerChanged) && !e.IsVerChanged() {
//
// slow path: extensive 'version-changed' check
//
cmn.S2CustomMD(wi.custom, e.Custom, e.Version)

// slow path: extensive 'version-changed' check
if checkVchanged && !en.IsAnyFlagSet(apc.EntryVerChanged|apc.EntryVerRemoved) {
cmn.S2CustomMD(wi.custom, en.Custom, en.Version)
if len(wi.custom) > 0 {
oa := cmn.ObjAttrs{Size: e.Size, CustomMD: wi.custom}
oa := cmn.ObjAttrs{Size: en.Size, CustomMD: wi.custom}
if lom.CheckEq(&oa) != nil {
e.SetVerChanged()
// lom.CheckEq returned err contains the cause
en.SetFlag(apc.EntryVerChanged)
}
clear(wi.custom)
}
Expand Down
37 changes: 25 additions & 12 deletions xact/xs/wi_lso.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,53 +88,66 @@ func (wi *walkInfo) match(objName string) bool {
}

// new entry to be added to the listed page (note: slow path)
func (wi *walkInfo) ls(lom *core.LOM, status uint16) (e *cmn.LsoEnt) {
e = &cmn.LsoEnt{Name: lom.ObjName, Flags: status | apc.EntryIsCached}
func (wi *walkInfo) ls(lom *core.LOM, status uint16) (en *cmn.LsoEnt) {
en = &cmn.LsoEnt{Name: lom.ObjName, Flags: status | apc.EntryIsCached}

if lom.IsFntl() {
orig := lom.OrigFntl()
if orig != nil {
saved := lom.PushFntl(orig)
if wi.msg.IsFlagSet(apc.LsVerChanged) {
checkRemoteMD(lom, e)
checkRemoteMD(lom, en)
}
lom.PopFntl(saved)
e.Name = orig[1]
en.Name = orig[1]
}
} else if wi.msg.IsFlagSet(apc.LsVerChanged) {
checkRemoteMD(lom, e)
// may set en.custom and en.version
checkRemoteMD(lom, en)
}
if wi.msg.IsFlagSet(apc.LsNameOnly) {
return
}
wi.setWanted(e, lom)

// fill out even more of `en`
wi.setWanted(en, lom)

wi.lomVisitedCb(lom)
return
}

// NOTE: slow path if lom.Bck is remote
func checkRemoteMD(lom *core.LOM, e *cmn.LsoEnt) {
func checkRemoteMD(lom *core.LOM, en *cmn.LsoEnt) {
res := lom.CheckRemoteMD(false /*locked*/, false /*sync*/, nil /*origReq*/)

switch {
case res.Eq:
debug.AssertNoErr(res.Err)
case cos.IsNotExist(res.Err, res.ErrCode):
e.SetVerRemoved()
en.SetFlag(apc.EntryVerRemoved)
case res.Err == nil:
en.SetFlag(apc.EntryVerChanged)

// expecting custom and version set
debug.Assert(len(res.ObjAttrs.CustomMD) > 0)
en.Custom = cmn.CustomMD2S(res.ObjAttrs.CustomMD)
debug.Assert(res.ObjAttrs.Ver != nil)
en.Version = *res.ObjAttrs.Ver
default:
e.SetVerChanged()
en.SetFlag(apc.EntryHeadFail)
}
}

// Performs a number of syscalls to load object metadata.
func (wi *walkInfo) callback(fqn string, de fs.DirEntry) (entry *cmn.LsoEnt, err error) {
func (wi *walkInfo) callback(fqn string, de fs.DirEntry) (en *cmn.LsoEnt, err error) {
if de.IsDir() {
return
}

lom := core.AllocLOM("")
entry, err = wi._cb(lom, fqn)
en, err = wi._cb(lom, fqn)
core.FreeLOM(lom)
return entry, err
return en, err
}

func (wi *walkInfo) _cb(lom *core.LOM, fqn string) (*cmn.LsoEnt, error) {
Expand Down

0 comments on commit 939d7a6

Please sign in to comment.