Skip to content

Do not use epoch for sorting #1163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions api/layer/layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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
}
Expand Down
20 changes: 11 additions & 9 deletions api/layer/neofs_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type TestNeoFS struct {
containers map[string]*container.Container
eaclTables map[string]*eacl.Table
currentEpoch uint64
currentTime int64
signer neofscrypto.Signer
}

Expand All @@ -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,
}
}

Expand Down Expand Up @@ -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)
Expand Down
116 changes: 28 additions & 88 deletions api/layer/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ type (
prefixSearchResult struct {
ID oid.ID
FilePath string
CreationEpoch uint64
CreationTimestamp int64
IsDeleteMarker bool
DecryptedSize int64
Expand All @@ -90,15 +89,13 @@ type (
versioningContainerIDSearchResult struct {
ID oid.ID
FilePath string
CreationEpoch uint64
CreationTimestamp int64
IsDeleteMarker bool
}

allVersionsSearchResult struct {
ID oid.ID
FilePath string
CreationEpoch uint64
CreationTimestamp int64
PayloadSize int64
IsDeleteMarker bool
Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -757,40 +720,33 @@ 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)
}
}

if psr.DecryptedSize > 0 {
psr.PayloadSize = psr.DecryptedSize
}

psr.PayloadChecksum = item.Attributes[6]
psr.PayloadChecksum = item.Attributes[5]

searchResults = append(searchResults, psr)
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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,
}
)
Expand Down Expand Up @@ -1353,27 +1304,16 @@ 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)
}
}

searchResults = append(searchResults, psr)
}

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
}
Expand Down
Loading
Loading