mirror of
https://github.com/minio/minio.git
synced 2025-02-13 06:38:09 -05:00
Renaming a part from tmp namespace needs to be handled different from… (#1944)
* Renaming a part from tmp namespace needs to be handled different from renaming of an object * Made argument passing in xl.rename and xl.undoRename explicit
This commit is contained in:
parent
6143c87c3a
commit
393c504de0
@ -372,7 +372,7 @@ func (xl xlObjects) putObjectPart(bucket string, object string, uploadID string,
|
|||||||
|
|
||||||
// Rename temporary part file to its final location.
|
// Rename temporary part file to its final location.
|
||||||
partPath := path.Join(uploadIDPath, partSuffix)
|
partPath := path.Join(uploadIDPath, partSuffix)
|
||||||
err = xl.renameObject(minioMetaBucket, tmpPartPath, minioMetaBucket, partPath)
|
err = xl.renamePart(minioMetaBucket, tmpPartPath, minioMetaBucket, partPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", toObjectErr(err, minioMetaBucket, partPath)
|
return "", toObjectErr(err, minioMetaBucket, partPath)
|
||||||
}
|
}
|
||||||
|
@ -154,10 +154,16 @@ func (xl xlObjects) getObjectInfo(bucket, object string) (objInfo ObjectInfo, er
|
|||||||
return objInfo, nil
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// undoRenameObject - renames back the partially successful rename operations.
|
func (xl xlObjects) undoRename(srcBucket, srcEntry, dstBucket, dstEntry string, isPart bool, errs []error) {
|
||||||
func (xl xlObjects) undoRenameObject(srcBucket, srcObject, dstBucket, dstObject string, errs []error) {
|
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
// Undo rename object on disks where RenameFile succeeded.
|
// Undo rename object on disks where RenameFile succeeded.
|
||||||
|
|
||||||
|
// If srcEntry/dstEntry are objects then add a trailing slash to copy
|
||||||
|
// over all the parts inside the object directory
|
||||||
|
if !isPart {
|
||||||
|
srcEntry = retainSlash(srcEntry)
|
||||||
|
dstEntry = retainSlash(dstEntry)
|
||||||
|
}
|
||||||
for index, disk := range xl.storageDisks {
|
for index, disk := range xl.storageDisks {
|
||||||
if disk == nil {
|
if disk == nil {
|
||||||
continue
|
continue
|
||||||
@ -169,36 +175,48 @@ func (xl xlObjects) undoRenameObject(srcBucket, srcObject, dstBucket, dstObject
|
|||||||
if errs[index] != nil {
|
if errs[index] != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = disk.RenameFile(dstBucket, retainSlash(dstObject), srcBucket, retainSlash(srcObject))
|
_ = disk.RenameFile(dstBucket, dstEntry, srcBucket, srcEntry)
|
||||||
}(index, disk)
|
}(index, disk)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// renameObject - renames all source objects to destination object
|
// undoRenameObject - renames back the partially successful rename operations.
|
||||||
// across all disks in parallel. Additionally if we have errors and do
|
func (xl xlObjects) undoRenameObject(srcBucket, srcObject, dstBucket, dstObject string, errs []error) {
|
||||||
// not have a readQuorum partially renamed files are renamed back to
|
isPart := false
|
||||||
// its proper location.
|
xl.undoRename(srcBucket, srcObject, dstBucket, dstObject, isPart, errs)
|
||||||
func (xl xlObjects) renameObject(srcBucket, srcObject, dstBucket, dstObject string) error {
|
}
|
||||||
|
|
||||||
|
// undoRenamePart - renames back the partially successful rename operation.
|
||||||
|
func (xl xlObjects) undoRenamePart(srcBucket, srcPart, dstBucket, dstPart string, errs []error) {
|
||||||
|
isPart := true
|
||||||
|
xl.undoRename(srcBucket, srcPart, dstBucket, dstPart, isPart, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rename - common function that renamePart and renameObject use to rename
|
||||||
|
// the respective underlying storage layer representations.
|
||||||
|
func (xl xlObjects) rename(srcBucket, srcEntry, dstBucket, dstEntry string, isPart bool) error {
|
||||||
// Initialize sync waitgroup.
|
// Initialize sync waitgroup.
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
|
|
||||||
// Initialize list of errors.
|
// Initialize list of errors.
|
||||||
var errs = make([]error, len(xl.storageDisks))
|
var errs = make([]error, len(xl.storageDisks))
|
||||||
|
|
||||||
|
if !isPart {
|
||||||
|
dstEntry = retainSlash(dstEntry)
|
||||||
|
srcEntry = retainSlash(srcEntry)
|
||||||
|
}
|
||||||
|
|
||||||
// Rename file on all underlying storage disks.
|
// Rename file on all underlying storage disks.
|
||||||
for index, disk := range xl.storageDisks {
|
for index, disk := range xl.storageDisks {
|
||||||
if disk == nil {
|
if disk == nil {
|
||||||
errs[index] = errDiskNotFound
|
errs[index] = errDiskNotFound
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Append "/" as srcObject and dstObject are either leaf-dirs or non-leaf-dris.
|
|
||||||
// If srcObject is an object instead of prefix we just rename the leaf-dir and
|
|
||||||
// not rename the part and metadata files separately.
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(index int, disk StorageAPI) {
|
go func(index int, disk StorageAPI) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := disk.RenameFile(srcBucket, retainSlash(srcObject), dstBucket, retainSlash(dstObject))
|
err := disk.RenameFile(srcBucket, srcEntry, dstBucket, dstEntry)
|
||||||
if err != nil && err != errFileNotFound {
|
if err != nil && err != errFileNotFound {
|
||||||
errs[index] = err
|
errs[index] = err
|
||||||
}
|
}
|
||||||
@ -216,20 +234,38 @@ func (xl xlObjects) renameObject(srcBucket, srcObject, dstBucket, dstObject stri
|
|||||||
return nil // Return success.
|
return nil // Return success.
|
||||||
} // else - failed to acquire read quorum.
|
} // else - failed to acquire read quorum.
|
||||||
// Undo all the partial rename operations.
|
// Undo all the partial rename operations.
|
||||||
xl.undoRenameObject(srcBucket, srcObject, dstBucket, dstObject, errs)
|
xl.undoRename(srcBucket, srcEntry, dstBucket, dstEntry, isPart, errs)
|
||||||
return errXLWriteQuorum
|
return errXLWriteQuorum
|
||||||
}
|
}
|
||||||
// Return on first error, also undo any partially successful rename operations.
|
// Return on first error, also undo any partially successful rename operations.
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
if err != nil && err != errDiskNotFound {
|
if err != nil && err != errDiskNotFound {
|
||||||
// Undo all the partial rename operations.
|
// Undo all the partial rename operations.
|
||||||
xl.undoRenameObject(srcBucket, srcObject, dstBucket, dstObject, errs)
|
xl.undoRename(srcBucket, srcEntry, dstBucket, dstEntry, isPart, errs)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renamePart - renames a part of the source object to the destination
|
||||||
|
// across all disks in parallel. Additionally if we have errors and do
|
||||||
|
// not have a readQuorum partially renamed files are renamed back to
|
||||||
|
// its proper location.
|
||||||
|
func (xl xlObjects) renamePart(srcBucket, srcObject, dstBucket, dstObject string) error {
|
||||||
|
isPart := true
|
||||||
|
return xl.rename(srcBucket, srcObject, dstBucket, dstObject, isPart)
|
||||||
|
}
|
||||||
|
|
||||||
|
// renameObject - renames all source objects to destination object
|
||||||
|
// across all disks in parallel. Additionally if we have errors and do
|
||||||
|
// not have a readQuorum partially renamed files are renamed back to
|
||||||
|
// its proper location.
|
||||||
|
func (xl xlObjects) renameObject(srcBucket, srcObject, dstBucket, dstObject string) error {
|
||||||
|
isPart := false
|
||||||
|
return xl.rename(srcBucket, srcObject, dstBucket, dstObject, isPart)
|
||||||
|
}
|
||||||
|
|
||||||
// PutObject - creates an object upon reading from the input stream
|
// PutObject - creates an object upon reading from the input stream
|
||||||
// until EOF, erasure codes the data across all disk and additionally
|
// until EOF, erasure codes the data across all disk and additionally
|
||||||
// writes `xl.json` which carries the necessary metadata for future
|
// writes `xl.json` which carries the necessary metadata for future
|
||||||
|
Loading…
x
Reference in New Issue
Block a user