diff --git a/api/layer/layer.go b/api/layer/layer.go index 05116c26..f7df6176 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -774,7 +774,6 @@ func (n *layer) GetIDForVersioningContainer(ctx context.Context, p *ShortInfoPar filters = make(object.SearchFilters, 0, 3) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, s3headers.AttributeDeleteMarker, } @@ -820,29 +819,18 @@ func (n *layer) GetIDForVersioningContainer(ctx context.Context, p *ShortInfoPar } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return oid.ID{}, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) + return oid.ID{}, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) - if err != nil { - return oid.ID{}, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) - } - } - - psr.IsDeleteMarker = item.Attributes[3] != "" + psr.IsDeleteMarker = item.Attributes[2] != "" searchResults = append(searchResults, psr) } sortFunc := func(a, b versioningContainerIDSearchResult) int { - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c } diff --git a/api/layer/neofs_mock.go b/api/layer/neofs_mock.go index 0a9c5c00..220499bc 100644 --- a/api/layer/neofs_mock.go +++ b/api/layer/neofs_mock.go @@ -40,6 +40,7 @@ type TestNeoFS struct { containers map[string]*container.Container eaclTables map[string]*eacl.Table currentEpoch uint64 + currentTime int64 signer neofscrypto.Signer } @@ -54,10 +55,11 @@ const ( func NewTestNeoFS(signer neofscrypto.Signer) *TestNeoFS { return &TestNeoFS{ - objects: make(map[string]*object.Object), - containers: make(map[string]*container.Container), - eaclTables: make(map[string]*eacl.Table), - signer: signer, + objects: make(map[string]*object.Object), + containers: make(map[string]*container.Container), + eaclTables: make(map[string]*eacl.Table), + currentTime: time.Now().Unix(), + signer: signer, } } @@ -273,14 +275,14 @@ func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID id := oid.NewFromObjectHeaderBinary(b) attrs := make([]object.Attribute, 0) - creationTime := prm.CreationTime - if creationTime.IsZero() { - creationTime = time.Now() - } + // Deliberately ignore `prm.CreationTime` here, it's based on time.Now() + // which leads to duplicate timestamps in different object versions and + // this breaks many tests. var a *object.Attribute - a = object.NewAttribute(object.AttributeTimestamp, strconv.FormatInt(creationTime.Unix(), 10)) + a = object.NewAttribute(object.AttributeTimestamp, strconv.FormatInt(t.currentTime, 10)) attrs = append(attrs, *a) + t.currentTime++ if prm.Filepath != "" { a = object.NewAttribute(object.AttributeFilePath, prm.Filepath) diff --git a/api/layer/object.go b/api/layer/object.go index 8dd98c81..b46cdbc8 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -79,7 +79,6 @@ type ( prefixSearchResult struct { ID oid.ID FilePath string - CreationEpoch uint64 CreationTimestamp int64 IsDeleteMarker bool DecryptedSize int64 @@ -90,7 +89,6 @@ type ( versioningContainerIDSearchResult struct { ID oid.ID FilePath string - CreationEpoch uint64 CreationTimestamp int64 IsDeleteMarker bool } @@ -98,7 +96,6 @@ type ( allVersionsSearchResult struct { ID oid.ID FilePath string - CreationEpoch uint64 CreationTimestamp int64 PayloadSize int64 IsDeleteMarker bool @@ -107,21 +104,12 @@ type ( baseSearchResult struct { ID oid.ID - CreationEpoch uint64 CreationTimestamp int64 } ) func (a prefixSearchResult) isNewerThan(b prefixSearchResult) bool { - if a.CreationEpoch > b.CreationEpoch { - return true - } - - if a.CreationTimestamp > b.CreationTimestamp { - return true - } - - return false + return a.CreationTimestamp > b.CreationTimestamp } // objectHead returns all object's headers. @@ -419,7 +407,6 @@ func (n *layer) searchAllVersionsInNeoFS(ctx context.Context, bkt *data.BucketIn filters = make(object.SearchFilters, 0, 6) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, s3headers.AttributeVersioningState, object.FilterPayloadSize, @@ -472,38 +459,27 @@ func (n *layer) searchAllVersionsInNeoFS(ctx context.Context, bkt *data.BucketIn } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) - } - } - - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) + return nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } - psr.IsVersioned = item.Attributes[3] == data.VersioningEnabled + psr.IsVersioned = item.Attributes[2] == data.VersioningEnabled - if item.Attributes[4] != "" { - psr.PayloadSize, err = strconv.ParseInt(item.Attributes[4], 10, 64) + if item.Attributes[3] != "" { + psr.PayloadSize, err = strconv.ParseInt(item.Attributes[3], 10, 64) if err != nil { - return nil, fmt.Errorf("invalid payload size %s: %w", item.Attributes[4], err) + return nil, fmt.Errorf("invalid payload size %s: %w", item.Attributes[3], err) } } - psr.IsDeleteMarker = item.Attributes[5] != "" + psr.IsDeleteMarker = item.Attributes[4] != "" searchResults = append(searchResults, psr) } sortFunc := func(a, b allVersionsSearchResult) int { - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c } @@ -522,7 +498,6 @@ func (n *layer) comprehensiveSearchAllVersionsInNeoFS(ctx context.Context, bkt * filters = make(object.SearchFilters, 0, 7) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, s3headers.AttributeVersioningState, object.FilterPayloadSize, @@ -577,20 +552,13 @@ func (n *layer) comprehensiveSearchAllVersionsInNeoFS(ctx context.Context, bkt * } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return nil, false, false, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) + return nil, false, false, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) - if err != nil { - return nil, false, false, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) - } - } - - switch item.Attributes[6] { + switch item.Attributes[5] { case s3headers.TypeTags: hasTags = true continue @@ -600,25 +568,21 @@ func (n *layer) comprehensiveSearchAllVersionsInNeoFS(ctx context.Context, bkt * default: } - psr.IsVersioned = item.Attributes[3] == data.VersioningEnabled + psr.IsVersioned = item.Attributes[2] == data.VersioningEnabled - if item.Attributes[4] != "" { - psr.PayloadSize, err = strconv.ParseInt(item.Attributes[4], 10, 64) + if item.Attributes[3] != "" { + psr.PayloadSize, err = strconv.ParseInt(item.Attributes[3], 10, 64) if err != nil { - return nil, false, false, fmt.Errorf("invalid payload size %s: %w", item.Attributes[4], err) + return nil, false, false, fmt.Errorf("invalid payload size %s: %w", item.Attributes[3], err) } } - psr.IsDeleteMarker = item.Attributes[5] != "" + psr.IsDeleteMarker = item.Attributes[4] != "" searchResults = append(searchResults, psr) } sortFunc := func(a, b allVersionsSearchResult) int { - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c } @@ -706,7 +670,6 @@ func (n *layer) searchAllVersionsInNeoFSByPrefix(ctx context.Context, bkt *data. filters = make(object.SearchFilters, 0, 3) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, s3headers.AttributeDeleteMarker, s3headers.AttributeDecryptedSize, @@ -757,32 +720,25 @@ func (n *layer) searchAllVersionsInNeoFSByPrefix(ctx context.Context, bkt *data. } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return nil, "", fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) + return nil, "", fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) - if err != nil { - return nil, "", fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) - } - } - - psr.IsDeleteMarker = item.Attributes[3] != "" + psr.IsDeleteMarker = item.Attributes[2] != "" - if item.Attributes[4] != "" { - psr.DecryptedSize, err = strconv.ParseInt(item.Attributes[4], 10, 64) + if item.Attributes[3] != "" { + psr.DecryptedSize, err = strconv.ParseInt(item.Attributes[3], 10, 64) if err != nil { - return nil, "", fmt.Errorf("invalid decrypted size %s: %w", item.Attributes[4], err) + return nil, "", fmt.Errorf("invalid decrypted size %s: %w", item.Attributes[3], err) } } - if item.Attributes[5] != "" { - psr.PayloadSize, err = strconv.ParseInt(item.Attributes[5], 10, 64) + if item.Attributes[4] != "" { + psr.PayloadSize, err = strconv.ParseInt(item.Attributes[4], 10, 64) if err != nil { - return nil, "", fmt.Errorf("invalid payload size %s: %w", item.Attributes[5], err) + return nil, "", fmt.Errorf("invalid payload size %s: %w", item.Attributes[4], err) } } @@ -790,7 +746,7 @@ func (n *layer) searchAllVersionsInNeoFSByPrefix(ctx context.Context, bkt *data. psr.PayloadSize = psr.DecryptedSize } - psr.PayloadChecksum = item.Attributes[6] + psr.PayloadChecksum = item.Attributes[5] searchResults = append(searchResults, psr) } @@ -800,10 +756,6 @@ func (n *layer) searchAllVersionsInNeoFSByPrefix(ctx context.Context, bkt *data. return c } - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c } @@ -1316,7 +1268,6 @@ func (n *layer) searchBucketMetaObjects(ctx context.Context, bktInfo *data.Bucke filters = make(object.SearchFilters, 0, 2) returningAttributes = []string{ s3headers.MetaType, - object.FilterCreationEpoch, object.AttributeTimestamp, } ) @@ -1353,16 +1304,9 @@ func (n *layer) searchBucketMetaObjects(ctx context.Context, bktInfo *data.Bucke } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) - if err != nil { - return oid.ID{}, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) - } - } - - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return oid.ID{}, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) + return oid.ID{}, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } @@ -1370,10 +1314,6 @@ func (n *layer) searchBucketMetaObjects(ctx context.Context, bktInfo *data.Bucke } sortFunc := func(a, b baseSearchResult) int { - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c } diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 4bc437c1..301c2102 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -30,7 +30,6 @@ type PutLockInfoParams struct { type locksSearchResult struct { ID oid.ID FilePath string - CreationEpoch uint64 CreationTimestamp int64 ExpirationEpoch uint64 IsComplianceMode bool @@ -107,7 +106,6 @@ func (n *layer) getLockDataFromObjects(ctx context.Context, bkt *data.BucketInfo filters = make(object.SearchFilters, 0, 3) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, object.AttributeExpirationEpoch, s3headers.AttributeComplianceMode, @@ -154,30 +152,23 @@ func (n *layer) getLockDataFromObjects(ctx context.Context, bkt *data.BucketInfo } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return nil, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) + return nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) + psr.ExpirationEpoch, err = strconv.ParseUint(item.Attributes[2], 10, 64) if err != nil { - return nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) + return nil, fmt.Errorf("invalid expiration epoch %s: %w", item.Attributes[2], err) } } - if item.Attributes[3] != "" { - psr.ExpirationEpoch, err = strconv.ParseUint(item.Attributes[3], 10, 64) - if err != nil { - return nil, fmt.Errorf("invalid expiration epoch %s: %w", item.Attributes[3], err) - } - } - - psr.IsComplianceMode = item.Attributes[4] == "true" + psr.IsComplianceMode = item.Attributes[3] == "true" - if item.Attributes[5] != "" { - psr.RetentionUntilMode, err = time.Parse(time.RFC3339, item.Attributes[5]) + if item.Attributes[4] != "" { + psr.RetentionUntilMode, err = time.Parse(time.RFC3339, item.Attributes[4]) if err != nil { return nil, fmt.Errorf("parse retention until attribute: %w", err) } @@ -187,10 +178,6 @@ func (n *layer) getLockDataFromObjects(ctx context.Context, bkt *data.BucketInfo } sortFunc := func(a, b locksSearchResult) int { - if c := cmp.Compare(a.CreationEpoch, b.CreationEpoch); c != 0 { // direct order. - return c - } - if c := cmp.Compare(a.CreationTimestamp, b.CreationTimestamp); c != 0 { // direct order. return c } diff --git a/api/layer/tagging.go b/api/layer/tagging.go index afbdca1a..fd898b4a 100644 --- a/api/layer/tagging.go +++ b/api/layer/tagging.go @@ -34,7 +34,6 @@ type PutObjectTaggingParams struct { type taggingSearchResult struct { ID oid.ID FilePath string - CreationEpoch uint64 CreationTimestamp int64 } @@ -85,7 +84,6 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *GetObjectTaggingParams) filters = make(object.SearchFilters, 0, 4) returningAttributes = []string{ object.AttributeFilePath, - object.FilterCreationEpoch, object.AttributeTimestamp, } @@ -129,16 +127,9 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *GetObjectTaggingParams) } if item.Attributes[1] != "" { - psr.CreationEpoch, err = strconv.ParseUint(item.Attributes[1], 10, 64) + psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[1], 10, 64) if err != nil { - return "", nil, fmt.Errorf("invalid creation epoch %s: %w", item.Attributes[1], err) - } - } - - if item.Attributes[2] != "" { - psr.CreationTimestamp, err = strconv.ParseInt(item.Attributes[2], 10, 64) - if err != nil { - return "", nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[2], err) + return "", nil, fmt.Errorf("invalid creation timestamp %s: %w", item.Attributes[1], err) } } @@ -146,10 +137,6 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *GetObjectTaggingParams) } sortFunc := func(a, b taggingSearchResult) int { - if c := cmp.Compare(b.CreationEpoch, a.CreationEpoch); c != 0 { // reverse order. - return c - } - if c := cmp.Compare(b.CreationTimestamp, a.CreationTimestamp); c != 0 { // reverse order. return c }