Skip to content
Draft
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
4 changes: 2 additions & 2 deletions internal/fs/handle/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func createFileInode(
Size: uint64(len(content)),
Generation: 1,
MetaGeneration: 1,
Updated: clock.Now(),
Updated: gcs.TimeToNS(clock.Now()),
}

// Create object in the fake bucket to simulate existing GCS object
Expand Down Expand Up @@ -1277,7 +1277,7 @@ func (t *fileTest) Test_ReadWithReadManager_FullReadSuccessWithBufferedRead() {
func (t *fileTest) Test_ShouldSkipSizeChecks() {
const objectSize = 100
unfinalizedObject := &gcs.MinObject{Name: "unfinalized", Size: objectSize}
finalizedObject := &gcs.MinObject{Name: "finalized", Size: objectSize, Finalized: time.Now()}
finalizedObject := &gcs.MinObject{Name: "finalized", Size: objectSize, Finalized: gcs.TimeToNS(time.Now())}
directIOReadMode := util.NewOpenMode(util.ReadOnly, util.O_DIRECT)
readOnlyMode := util.NewOpenMode(util.ReadOnly, 0)

Expand Down
2 changes: 1 addition & 1 deletion internal/fs/inode/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func (f *FileInode) Attributes(
ctx context.Context, clobberedCheck bool) (attrs fuseops.InodeAttributes, err error) {
attrs = f.attrs
// Obtain default information from the source object.
attrs.Mtime = f.src.Updated
attrs.Mtime = f.src.UpdatedTime()
attrs.Size = f.src.Size

// If the source object has an mtime metadata key, use that instead of its
Expand Down
6 changes: 3 additions & 3 deletions internal/fs/inode/file_mock_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ func (t *FileMockBucketTest) TestAttributes_NoChangeInAttributes() {
Size: initialSize,
Generation: initialGeneration,
MetaGeneration: initialMetaGeneration,
Updated: initialTime,
Updated: gcs.TimeToNS(initialTime),
}
f := t.createGCSBackedFileInode(backingObj)
defer f.Unlock()
Expand All @@ -334,7 +334,7 @@ func (t *FileMockBucketTest) TestAttributes_NoChangeInAttributes() {
Generation: initialGeneration,
MetaGeneration: initialMetaGeneration,
Size: initialSize, // Size is not greater
Updated: t.clock.Now(),
Updated: gcs.TimeToNS(t.clock.Now()),
}
statReq := &gcs.StatObjectRequest{Name: fileName, ForceFetchFromGcs: false, ReturnExtendedObjectAttributes: false}
t.bucket.On("StatObject", t.ctx, statReq).Return(updatedMinObject, &gcs.ExtendedObjectAttributes{}, nil).Once()
Expand All @@ -347,7 +347,7 @@ func (t *FileMockBucketTest) TestAttributes_NoChangeInAttributes() {
assert.Equal(t.T(), initialSize, attrs.Size)
assert.Equal(t.T(), initialTime, attrs.Mtime)
assert.Equal(t.T(), initialSize, f.Source().Size)
assert.Equal(t.T(), initialTime, f.Source().Updated)
assert.Equal(t.T(), initialTime, f.Source().UpdatedTime())
}

func (t *FileMockBucketTest) TestInitBufferedWriteHandlerIfEligible_ZonalBucket_DoesNotFetchMetadataFromGCS_ForAppends() {
Expand Down
6 changes: 3 additions & 3 deletions internal/fs/inode/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,9 @@ func (t *FileTest) TestInitialAttributes() {
assert.Equal(t.T(), uint32(uid), attrs.Uid)
assert.Equal(t.T(), uint32(gid), attrs.Gid)
assert.Equal(t.T(), fileMode, attrs.Mode)
assert.Equal(t.T(), attrs.Atime, t.backingObj.Updated)
assert.Equal(t.T(), attrs.Ctime, t.backingObj.Updated)
assert.Equal(t.T(), attrs.Mtime, t.backingObj.Updated)
assert.Equal(t.T(), attrs.Atime, t.backingObj.UpdatedTime())
assert.Equal(t.T(), attrs.Ctime, t.backingObj.UpdatedTime())
assert.Equal(t.T(), attrs.Mtime, t.backingObj.UpdatedTime())
}

func (t *FileTest) TestInitialAttributes_MtimeFromObjectMetadata_Gcsfuse() {
Expand Down
8 changes: 4 additions & 4 deletions internal/fs/inode/symlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ func NewSymlinkInode(
Uid: attrs.Uid,
Gid: attrs.Gid,
Mode: attrs.Mode,
Atime: m.Updated,
Ctime: m.Updated,
Mtime: m.Updated,
Atime: m.UpdatedTime(),
Ctime: m.UpdatedTime(),
Mtime: m.UpdatedTime(),
},
metadata: m.Metadata,
}
Expand Down Expand Up @@ -265,6 +265,6 @@ func (s *SymlinkInode) Source() *gcs.MinObject {
MetaGeneration: s.sourceGeneration.Metadata,
Size: s.sourceGeneration.Size,
Metadata: s.metadata,
Updated: s.attrs.Mtime,
Updated: gcs.TimeToNS(s.attrs.Mtime),
}
}
4 changes: 2 additions & 2 deletions internal/fs/inode/symlink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (t *SymlinkTest) TestSource() {
AssertEq(nil, err)
m := storageutil.ConvertObjToMinObject(obj)
m.Metadata = map[string]string{inode.StandardSymlinkMetadataKey: "true"}
m.Updated = time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) // Explicitly set Updated time for consistent testing.
m.Updated = time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano() // Explicitly set Updated time for consistent testing.
attrs := fuseops.InodeAttributes{}
name := inode.NewFileName(inode.NewRootName("some-bucket"), m.Name)
s, err := inode.NewSymlinkInode(context.Background(), fuseops.InodeID(42), name, t.bucket, m, attrs)
Expand All @@ -185,5 +185,5 @@ func (t *SymlinkTest) TestSource() {
AssertEq(m.MetaGeneration, source.MetaGeneration)
AssertEq(m.Size, source.Size)
AssertEq(m.Metadata, source.Metadata)
AssertEq(0, m.Updated.Compare(source.Updated))
AssertEq(m.Updated, source.Updated)
}
2 changes: 1 addition & 1 deletion internal/fs/local_modifications_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,7 @@ func validateObjectAttributes(extendedAttr1, extendedAttr2 *gcs.ExtendedObjectAt
ExpectEq(0, minObject1.Size)
ExpectEq(FileContentsSize, minObject2.Size)
ExpectNe(minObject1.Generation, minObject2.Generation)
ExpectTrue(minObject1.Updated.Before(minObject2.Updated))
ExpectTrue(minObject1.Updated < minObject2.Updated)
attr1MTime, _ := time.Parse(time.RFC3339Nano, minObject1.Metadata[gcs.MtimeMetadataKey])
attr2MTime, _ := time.Parse(time.RFC3339Nano, minObject2.Metadata[gcs.MtimeMetadataKey])
ExpectTrue(attr1MTime.Before(attr2MTime))
Expand Down
2 changes: 1 addition & 1 deletion internal/gcsx/file_cache_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (t *fileCacheReaderTest) SetupTest() {
Name: testObject,
Size: 17,
Generation: 1234,
Finalized: time.Date(2025, time.June, 27, 07, 22, 30, 0, time.UTC),
Finalized: gcs.TimeToNS(time.Date(2025, time.June, 27, 07, 22, 30, 0, time.UTC)),
}
t.unfinalized_object = &gcs.MinObject{
Name: testObject_unfinalized,
Expand Down
2 changes: 1 addition & 1 deletion internal/gcsx/garbage_collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func garbageCollectOnce(
group.Go(func() (err error) {
defer close(staleNames)
for o := range minObjects {
if now.Sub(o.Updated) < stalenessThreshold {
if now.Sub(o.UpdatedTime()) < stalenessThreshold {
continue
}

Expand Down
4 changes: 2 additions & 2 deletions internal/storage/fake/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,8 @@ func copyMinObject(o *gcs.Object) *gcs.MinObject {
copy.Size = o.Size
copy.Generation = o.Generation
copy.MetaGeneration = o.MetaGeneration
copy.Updated = o.Updated
copy.Finalized = o.Finalized
copy.Updated = gcs.TimeToNS(o.Updated)
copy.Finalized = gcs.TimeToNS(o.Finalized)
copy.Metadata = copyMetadata(o.Metadata)
copy.ContentEncoding = o.ContentEncoding
copy.CRC32C = o.CRC32C
Expand Down
16 changes: 8 additions & 8 deletions internal/storage/fake/testing/bucket_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,8 @@ func (t *bucketTest) assertOnObjectAttributes(expectedMinObj *gcs.MinObject, exp
ExpectThat(expectedMinObj.Size, Equals(o.Size))
ExpectThat(expectedMinObj.Generation, Equals(o.Generation))
ExpectThat(expectedMinObj.MetaGeneration, Equals(o.MetaGeneration))
ExpectThat(expectedMinObj.Updated, DeepEquals(o.Updated))
ExpectThat(expectedMinObj.Finalized, DeepEquals(o.Finalized))
ExpectThat(expectedMinObj.UpdatedTime(), DeepEquals(o.Updated))
ExpectThat(expectedMinObj.FinalizedTime(), DeepEquals(o.Finalized))
ExpectThat(expectedMinObj.Metadata, DeepEquals(o.Metadata))
ExpectThat(expectedMinObj.ContentEncoding, Equals(o.ContentEncoding))
ExpectThat(expectedMinObj.CRC32C, Equals(o.CRC32C))
Expand Down Expand Up @@ -3490,8 +3490,8 @@ func (t *statTest) StatAfterCreating() {
ExpectEq(orig.Generation, m.Generation)
ExpectEq(len("taco"), m.Size)
ExpectThat(e.Deleted, timeutil.TimeEq(time.Time{}))
ExpectThat(m.Updated, timeutil.TimeEq(orig.Updated))
ExpectThat(m.Finalized, timeutil.TimeEq(time.Time{}))
ExpectThat(m.UpdatedTime(), timeutil.TimeEq(orig.Updated))
ExpectThat(m.FinalizedTime(), timeutil.TimeEq(time.Time{}))
}

func (t *statTest) StatAfterOverwriting() {
Expand Down Expand Up @@ -3527,8 +3527,8 @@ func (t *statTest) StatAfterOverwriting() {
ExpectEq(o2.Generation, m.Generation)
ExpectEq(len("burrito"), m.Size)
ExpectThat(e.Deleted, timeutil.TimeEq(time.Time{}))
ExpectThat(m.Updated, timeutil.TimeEq(o2.Updated))
ExpectThat(m.Finalized, timeutil.TimeEq(time.Time{}))
ExpectThat(m.UpdatedTime(), timeutil.TimeEq(o2.Updated))
ExpectThat(m.FinalizedTime(), timeutil.TimeEq(time.Time{}))
}

func (t *statTest) StatAfterUpdating() {
Expand Down Expand Up @@ -3581,8 +3581,8 @@ func (t *statTest) StatAfterUpdating() {
ExpectEq(o2.MetaGeneration, m.MetaGeneration)
ExpectEq(len("taco"), m.Size)
ExpectThat(e.Deleted, timeutil.TimeEq(time.Time{}))
ExpectThat(m.Updated, timeutil.TimeEq(o2.Updated))
ExpectThat(m.Finalized, timeutil.TimeEq(time.Time{}))
ExpectThat(m.UpdatedTime(), timeutil.TimeEq(o2.Updated))
ExpectThat(m.FinalizedTime(), timeutil.TimeEq(time.Time{}))
}

////////////////////////////////////////////////////////////////////////
Expand Down
33 changes: 30 additions & 3 deletions internal/storage/gcs/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ type MinObject struct {
Size uint64
Generation int64
MetaGeneration int64
Updated time.Time
Finalized time.Time
Updated int64 // Unix nanoseconds, 0 if zero
Finalized int64 // Unix nanoseconds, 0 if zero
Metadata map[string]string
ContentEncoding string
CRC32C *uint32 // Missing for CMEK buckets
Expand Down Expand Up @@ -119,5 +119,32 @@ func (mo MinObject) HasContentEncodingGzip() bool {
}

func (mo MinObject) IsUnfinalized() bool {
return mo.Finalized.IsZero()
return mo.Finalized == 0
}

// UpdatedTime returns the time.Time representation of the Updated timestamp.
func (mo MinObject) UpdatedTime() time.Time {
return NSToTime(mo.Updated)
}

// FinalizedTime returns the time.Time representation of the Finalized timestamp.
func (mo MinObject) FinalizedTime() time.Time {
return NSToTime(mo.Finalized)
}

// TimeToNS converts a time.Time to Unix nanoseconds, returning 0 if the time is zero.
// This avoids panics when calling UnixNano() on a zero time.Time.
func TimeToNS(t time.Time) int64 {
if t.IsZero() {
return 0
}
return t.UnixNano()
}

// NSToTime converts Unix nanoseconds to time.Time, returning a zero time.Time if ns is 0.
func NSToTime(ns int64) time.Time {
if ns == 0 {
return time.Time{}
}
return time.Unix(0, ns)
}
2 changes: 1 addition & 1 deletion internal/storage/gcs/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestHasContentEncodingGzipNegative(t *testing.T) {
}

func TestIsFinalized(t *testing.T) {
mo := MinObject{Finalized: time.Date(2025, time.June, 19, 18, 23, 30, 0, time.UTC)}
mo := MinObject{Finalized: TimeToNS(time.Date(2025, time.June, 19, 18, 23, 30, 0, time.UTC))}

assert.False(t, mo.IsUnfinalized())
}
Expand Down
16 changes: 8 additions & 8 deletions internal/storage/storageutil/object_attrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ func ObjectAttrsToMinObject(attrs *storage.ObjectAttrs) *gcs.MinObject {
Metadata: attrs.Metadata,
Generation: attrs.Generation,
MetaGeneration: attrs.Metageneration,
Updated: attrs.Updated,
Finalized: attrs.Finalized,
Updated: gcs.TimeToNS(attrs.Updated),
Finalized: gcs.TimeToNS(attrs.Finalized),
}
}

Expand Down Expand Up @@ -170,11 +170,11 @@ func ConvertObjToMinObject(o *gcs.Object) *gcs.MinObject {
Size: o.Size,
Generation: o.Generation,
MetaGeneration: o.MetaGeneration,
Updated: o.Updated,
Updated: gcs.TimeToNS(o.Updated),
Metadata: o.Metadata,
ContentEncoding: o.ContentEncoding,
CRC32C: o.CRC32C,
Finalized: o.Finalized,
Finalized: gcs.TimeToNS(o.Finalized),
}
}

Expand Down Expand Up @@ -211,8 +211,8 @@ func ConvertMinObjectAndExtendedObjectAttributesToObject(m *gcs.MinObject,
Size: m.Size,
Generation: m.Generation,
MetaGeneration: m.MetaGeneration,
Updated: m.Updated,
Finalized: m.Finalized,
Updated: m.UpdatedTime(),
Finalized: m.FinalizedTime(),
Metadata: m.Metadata,
ContentEncoding: m.ContentEncoding,
ContentType: e.ContentType,
Expand Down Expand Up @@ -242,10 +242,10 @@ func ConvertMinObjectToObject(m *gcs.MinObject) *gcs.Object {
Size: m.Size,
Generation: m.Generation,
MetaGeneration: m.MetaGeneration,
Updated: m.Updated,
Updated: m.UpdatedTime(),
Metadata: m.Metadata,
ContentEncoding: m.ContentEncoding,
CRC32C: m.CRC32C,
Finalized: m.Finalized,
Finalized: m.FinalizedTime(),
}
}
20 changes: 10 additions & 10 deletions internal/storage/storageutil/object_attrs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ func Test_ConvertObjToMinObject_WithValidObject(t *testing.T) {
assert.Equal(t, size, gcsMinObject.Size)
assert.Equal(t, generation, gcsMinObject.Generation)
assert.Equal(t, metaGeneration, gcsMinObject.MetaGeneration)
assert.True(t, currentTime.Equal(gcsMinObject.Updated))
assert.True(t, currentTime.Equal(gcsMinObject.Finalized))
assert.True(t, currentTime.Equal(gcsMinObject.UpdatedTime()))
assert.True(t, currentTime.Equal(gcsMinObject.FinalizedTime()))
assert.Equal(t, contentEncode, gcsMinObject.ContentEncoding)
assert.Equal(t, metadata, gcsMinObject.Metadata)
assert.Equal(t, crc32C, *gcsMinObject.CRC32C)
Expand Down Expand Up @@ -342,8 +342,8 @@ func Test_ConvertObjToExtendedObjectAttributes_WithNonNilMinObjectAndNonNilAttri
Size: uint64(36),
Generation: int64(444),
MetaGeneration: int64(555),
Updated: timeAttr,
Finalized: timeAttr,
Updated: gcs.TimeToNS(timeAttr),
Finalized: gcs.TimeToNS(timeAttr),
Metadata: map[string]string{"test_key": "test_value"},
ContentEncoding: "test_encoding",
}
Expand All @@ -370,8 +370,8 @@ func Test_ConvertObjToExtendedObjectAttributes_WithNonNilMinObjectAndNonNilAttri
assert.Equal(t, minObject.Size, gcsObject.Size)
assert.Equal(t, minObject.Generation, gcsObject.Generation)
assert.Equal(t, minObject.MetaGeneration, gcsObject.MetaGeneration)
assert.Equal(t, 0, gcsObject.Updated.Compare(minObject.Updated))
assert.Equal(t, 0, gcsObject.Finalized.Compare(minObject.Finalized))
assert.Equal(t, 0, gcsObject.Updated.Compare(minObject.UpdatedTime()))
assert.Equal(t, 0, gcsObject.Finalized.Compare(minObject.FinalizedTime()))
assert.Equal(t, minObject.Metadata, gcsObject.Metadata)
assert.Equal(t, minObject.ContentEncoding, gcsObject.ContentEncoding)
assert.Equal(t, extendedObjAttr.ContentType, gcsObject.ContentType)
Expand Down Expand Up @@ -406,8 +406,8 @@ func Test_ConvertMinObjectToObject_WithNonNilMinObject(t *testing.T) {
Size: uint64(36),
Generation: int64(444),
MetaGeneration: int64(555),
Updated: timeAttr,
Finalized: timeAttr,
Updated: gcs.TimeToNS(timeAttr),
Finalized: gcs.TimeToNS(timeAttr),
Metadata: map[string]string{"test_key": "test_value"},
ContentEncoding: "test_encoding",
CRC32C: &crc32C,
Expand All @@ -420,8 +420,8 @@ func Test_ConvertMinObjectToObject_WithNonNilMinObject(t *testing.T) {
assert.Equal(t, minObject.Size, gcsObject.Size)
assert.Equal(t, minObject.Generation, gcsObject.Generation)
assert.Equal(t, minObject.MetaGeneration, gcsObject.MetaGeneration)
assert.Equal(t, 0, gcsObject.Updated.Compare(minObject.Updated))
assert.Equal(t, 0, gcsObject.Finalized.Compare(minObject.Finalized))
assert.Equal(t, 0, gcsObject.Updated.Compare(minObject.UpdatedTime()))
assert.Equal(t, 0, gcsObject.Finalized.Compare(minObject.FinalizedTime()))
assert.Equal(t, minObject.Metadata, gcsObject.Metadata)
assert.Equal(t, minObject.ContentEncoding, gcsObject.ContentEncoding)
assert.Equal(t, "", gcsObject.ContentType)
Expand Down
2 changes: 1 addition & 1 deletion internal/util/sizeof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func TestNestedSizeOfGcsMinObject(t *testing.T) {
Metadata: customMetadataFields,
Generation: generation,
MetaGeneration: metaGeneration,
Updated: updated,
Updated: gcs.TimeToNS(updated),
CRC32C: &crc32,
}

Expand Down
Loading