Skip to content
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

[Move Object] Add rename file method in dir layer #2841

Merged
merged 8 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions internal/fs/inode/base_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ func (d *baseDirInode) ShouldInvalidateKernelListCache(ttl time.Duration) bool {
// List operation is not supported for baseDirInode.
func (d *baseDirInode) InvalidateKernelListCache() {}

func (d *baseDirInode) RenameFile(ctx context.Context, o *gcs.MinObject, destinationFileName string) (*gcs.Object, error) {
Tulsishah marked this conversation as resolved.
Show resolved Hide resolved
err := fuse.ENOSYS
return nil, err
}

func (d *baseDirInode) RenameFolder(ctx context.Context, folderName string, destinationFolderId string) (op *gcs.Folder, err error) {
err = fuse.ENOSYS
return
Expand Down
24 changes: 24 additions & 0 deletions internal/fs/inode/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ type DirInode interface {
// true.
LookUpChild(ctx context.Context, name string) (*Core, error)

// Rename the file.
RenameFile(ctx context.Context, oldObject *gcs.MinObject, destinationFileName string) (*gcs.Object, error)
Tulsishah marked this conversation as resolved.
Show resolved Hide resolved

// Rename the directiory/folder.
RenameFolder(ctx context.Context, folderName string, destinationFolderId string) (*gcs.Folder, error)

Expand Down Expand Up @@ -1038,6 +1041,27 @@ func (d *dirInode) ShouldInvalidateKernelListCache(ttl time.Duration) bool {
return cachedDuration >= ttl
}

func (d *dirInode) RenameFile(ctx context.Context, oldObject *gcs.MinObject, destinationFileName string) (*gcs.Object, error) {
Tulsishah marked this conversation as resolved.
Show resolved Hide resolved
req := &gcs.MoveObjectRequest{
SrcName: oldObject.Name,
DstName: destinationFileName,
SrcGeneration: oldObject.Generation,
SrcMetaGenerationPrecondition: &oldObject.MetaGeneration,
}

o, err := d.bucket.MoveObject(ctx, req)

// Invalidate the cache entry for the old object name.
d.cache.Erase(oldObject.Name)

// If the move was successful, add a cache entry for the new object name.
if err == nil {
d.cache.Insert(d.cacheClock.Now(), o.Name, metadata.RegularFileType)
}

return o, err
}

func (d *dirInode) RenameFolder(ctx context.Context, folderName string, destinationFolderName string) (*gcs.Folder, error) {
folder, err := d.bucket.RenameFolder(ctx, folderName, destinationFolderName)
if err != nil {
Expand Down
56 changes: 56 additions & 0 deletions internal/fs/inode/hns_dir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,61 @@ func (t *HNSDirTest) TestRenameFolderWithNonExistentSourceFolder() {
assert.Nil(t.T(), f)
}

func (t *HNSDirTest) TestRenameFileWithGivenName() {
const (
fileName = "qux"
renameFileName = "rename"
)
oldObjName := path.Join(dirInodeName, fileName)
newObjName := path.Join(dirInodeName, renameFileName)
var metaGeneration int64 = 0
moveObjectReq := gcs.MoveObjectRequest{
SrcName: oldObjName,
DstName: newObjName,
SrcGeneration: 0,
SrcMetaGenerationPrecondition: &metaGeneration,
}
oldObj := gcs.MinObject{Name: oldObjName}
newObj := gcs.Object{Name: newObjName}

Tulsishah marked this conversation as resolved.
Show resolved Hide resolved
t.mockBucket.On("MoveObject", t.ctx, &moveObjectReq).Return(&newObj, nil)

// Attempt to rename the file.
f, err := t.in.RenameFile(t.ctx, &oldObj, path.Join(dirInodeName, renameFileName))

t.mockBucket.AssertExpectations(t.T())
// Verify the renamed file exists.
assert.NoError(t.T(), err)
assert.Equal(t.T(), newObjName, f.Name)
}

func (t *HNSDirTest) TestRenameFileWithNonExistentSourceFile() {
const (
fileName = "qux"
renameFileName = "rename"
)
oldObjName := path.Join(dirInodeName, fileName)
newObjName := path.Join(dirInodeName, renameFileName)
var metaGeneration int64 = 0
moveObjectReq := gcs.MoveObjectRequest{
SrcName: oldObjName,
DstName: newObjName,
SrcGeneration: 0,
SrcMetaGenerationPrecondition: &metaGeneration,
}
oldObj := gcs.MinObject{Name: oldObjName}
var notFoundErr *gcs.NotFoundError

Tulsishah marked this conversation as resolved.
Show resolved Hide resolved
t.mockBucket.On("MoveObject", t.ctx, &moveObjectReq).Return(nil, &gcs.NotFoundError{})

// Attempt to rename the file.
f, err := t.in.RenameFile(t.ctx, &oldObj, newObjName)

t.mockBucket.AssertExpectations(t.T())
assert.True(t.T(), errors.As(err, &notFoundErr))
assert.Nil(t.T(), f)
}

func (t *HNSDirTest) TestDeleteChildDir_WhenImplicitDirFlagTrueOnNonHNSBucket() {
const folderName = "folder"
dirName := path.Join(dirInodeName, folderName) + "/"
Expand Down Expand Up @@ -350,6 +405,7 @@ func (t *HNSDirTest) TestDeleteChildDir_WhenImplicitDirFlagFalseAndNonHNSBucket_
assert.Equal(t.T(), metadata.Type(0), t.typeCache.Get(t.fixedTime.Now(), dirName))
assert.False(t.T(), dirIn.IsUnlinked())
}

func (t *HNSDirTest) TestDeleteChildDir_WithImplicitDirFlagFalseAndNonHNSBucket_DeleteObjectThrowAnError() {
const name = "folder"
dirName := path.Join(dirInodeName, name) + "/"
Expand Down
5 changes: 4 additions & 1 deletion internal/storage/mock/testify_mock_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ func (m *TestifyMockBucket) DeleteObject(ctx context.Context, req *gcs.DeleteObj

func (m *TestifyMockBucket) MoveObject(ctx context.Context, req *gcs.MoveObjectRequest) (*gcs.Object, error) {
args := m.Called(ctx, req)
return args.Get(0).(*gcs.Object), args.Error(1)
if args.Get(0) != nil {
return args.Get(0).(*gcs.Object), nil
}
return nil, args.Error(1)
}

func (m *TestifyMockBucket) DeleteFolder(ctx context.Context, folderName string) error {
Expand Down
Loading