Improve object nodes performance #1169

Merged
dstepanov-yadro merged 1 commit from dstepanov-yadro/frostfs-node:feat/improve_object_nodes_perf into master 2024-06-11 08:04:28 +00:00

View file

@ -33,7 +33,10 @@ const (
verifyPresenceAllFlag = "verify-presence-all"
)
var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint")
var (
errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint")
errMalformedComplexObject = errors.New("object consists of EC and non EC parts")
)
type phyObject struct {
containerID cid.ID
@ -180,30 +183,66 @@ func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli
func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, members []oid.ID, prmHead internalclient.HeadObjectPrm) []phyObject {
result := make([]phyObject, 0, len(members))
var resultGuard sync.Mutex
if len(members) == 0 {
return result
}
prmHead.SetRawFlag(true) // to get an error instead of whole object
first := members[0]
var addrObj oid.Address
addrObj.SetContainer(cnrID)
prmHead.SetRawFlag(true) // to get an error instead of whole object
for _, partObjID := range members {
addrObj.SetObject(partObjID)
prmHead.SetAddress(addrObj)
addrObj.SetObject(first)
prmHead.SetAddress(addrObj)
_, err := internalclient.HeadObject(cmd.Context(), prmHead)
var ecInfoError *objectSDK.ECInfoError
if errors.As(err, &ecInfoError) {
chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError)
result = append(result, chunks...)
continue
} else if err == nil { // not EC object, so all members must be phy objects
for _, member := range members {
result = append(result, phyObject{
containerID: cnrID,
objectID: member,
})
}
break
_, err := internalclient.HeadObject(cmd.Context(), prmHead)
var ecInfoError *objectSDK.ECInfoError
if errors.As(err, &ecInfoError) {
chunks := getECObjectChunks(cmd, cnrID, first, ecInfoError)
result = append(result, chunks...)
} else if err == nil { // not EC object, so all members must be phy objects
for _, member := range members {
result = append(result, phyObject{
containerID: cnrID,
objectID: member,
})
}
commonCmd.ExitOnErr(cmd, "failed to read EC chunk of complex object: %w", err)
return result
} else {
commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", err)
}
eg, egCtx := errgroup.WithContext(cmd.Context())
for idx := 1; idx < len(members); idx++ {
partObjID := members[idx]
eg.Go(func() error {
partHeadPrm := prmHead
var partAddr oid.Address
partAddr.SetContainer(cnrID)
partAddr.SetObject(partObjID)
partHeadPrm.SetAddress(partAddr)
_, err := internalclient.HeadObject(egCtx, partHeadPrm)
var ecInfoError *objectSDK.ECInfoError
if errors.As(err, &ecInfoError) {
chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError)
resultGuard.Lock()
defer resultGuard.Unlock()
result = append(result, chunks...)
return nil
} else if err == nil {
return errMalformedComplexObject
}
return err
})
}
commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", eg.Wait())
return result
}