mirror of
https://github.com/minio/minio.git
synced 2025-03-30 17:23:42 -04:00
Improve delete performance by reducing the number of calls (#9092)
- Remove the requirement to honor storage class for deletes - Improve `posix.DeleteFileBulk` code to Stat the volumeDir only once per call, rather than for all object paths.
This commit is contained in:
parent
23a0415eb7
commit
88ae0f1196
33
cmd/posix.go
33
cmd/posix.go
@ -1340,9 +1340,40 @@ func (s *posix) DeleteFile(volume, path string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *posix) DeleteFileBulk(volume string, paths []string) (errs []error, err error) {
|
func (s *posix) DeleteFileBulk(volume string, paths []string) (errs []error, err error) {
|
||||||
|
atomic.AddInt32(&s.activeIOCount, 1)
|
||||||
|
defer func() {
|
||||||
|
atomic.AddInt32(&s.activeIOCount, -1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
volumeDir, err := s.getVolDir(volume)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat a volume entry.
|
||||||
|
_, err = os.Stat(volumeDir)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, errVolumeNotFound
|
||||||
|
} else if os.IsPermission(err) {
|
||||||
|
return nil, errVolumeAccessDenied
|
||||||
|
} else if isSysErrIO(err) {
|
||||||
|
return nil, errFaultyDisk
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
errs = make([]error, len(paths))
|
errs = make([]error, len(paths))
|
||||||
|
// Following code is needed so that we retain SlashSeparator
|
||||||
|
// suffix if any in path argument.
|
||||||
for idx, path := range paths {
|
for idx, path := range paths {
|
||||||
errs[idx] = s.DeleteFile(volume, path)
|
filePath := pathJoin(volumeDir, path)
|
||||||
|
errs[idx] = checkPathLength(filePath)
|
||||||
|
if errs[idx] != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Delete file and delete parent directory as well if its empty.
|
||||||
|
errs[idx] = deleteFile(volumeDir, filePath)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -747,32 +747,37 @@ func (xl xlObjects) deleteObject(ctx context.Context, bucket, object string, wri
|
|||||||
// object.
|
// object.
|
||||||
func (xl xlObjects) doDeleteObjects(ctx context.Context, bucket string, objects []string, errs []error, writeQuorums []int, isDirs []bool) ([]error, error) {
|
func (xl xlObjects) doDeleteObjects(ctx context.Context, bucket string, objects []string, errs []error, writeQuorums []int, isDirs []bool) ([]error, error) {
|
||||||
var tmpObjs = make([]string, len(objects))
|
var tmpObjs = make([]string, len(objects))
|
||||||
disks := xl.getDisks()
|
|
||||||
if bucket == minioMetaTmpBucket {
|
if bucket == minioMetaTmpBucket {
|
||||||
copy(tmpObjs, objects)
|
copy(tmpObjs, objects)
|
||||||
} else {
|
} else {
|
||||||
for i, object := range objects {
|
for idx := range objects {
|
||||||
if errs[i] != nil {
|
if errs[idx] != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
tmpObjs[idx] = mustGetUUID()
|
||||||
var err error
|
var err error
|
||||||
tmpObjs[i] = mustGetUUID()
|
// Rename the current object while requiring
|
||||||
// Rename the current object while requiring write quorum, but also consider
|
// write quorum, but also consider that a non
|
||||||
// that a non found object in a given disk as a success since it already
|
// found object in a given disk as a success
|
||||||
// confirms that the object doesn't have a part in that disk (already removed)
|
// since it already confirms that the object
|
||||||
if isDirs[i] {
|
// doesn't have a part in that disk (already removed)
|
||||||
disks, err = rename(ctx, disks, bucket, object, minioMetaTmpBucket, tmpObjs[i], true, writeQuorums[i],
|
if isDirs[idx] {
|
||||||
|
_, err = rename(ctx, xl.getDisks(), bucket, objects[idx],
|
||||||
|
minioMetaTmpBucket, tmpObjs[idx], true, writeQuorums[idx],
|
||||||
[]error{errFileNotFound, errFileAccessDenied})
|
[]error{errFileNotFound, errFileAccessDenied})
|
||||||
} else {
|
} else {
|
||||||
disks, err = rename(ctx, disks, bucket, object, minioMetaTmpBucket, tmpObjs[i], true, writeQuorums[i],
|
_, err = rename(ctx, xl.getDisks(), bucket, objects[idx],
|
||||||
|
minioMetaTmpBucket, tmpObjs[idx], true, writeQuorums[idx],
|
||||||
[]error{errFileNotFound})
|
[]error{errFileNotFound})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs[i] = err
|
errs[idx] = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disks := xl.getDisks()
|
||||||
|
|
||||||
// Initialize list of errors.
|
// Initialize list of errors.
|
||||||
var opErrs = make([]error, len(disks))
|
var opErrs = make([]error, len(disks))
|
||||||
var delObjErrs = make([][]error, len(disks))
|
var delObjErrs = make([][]error, len(disks))
|
||||||
@ -840,23 +845,17 @@ func (xl xlObjects) deleteObjects(ctx context.Context, bucket string, objects []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, object := range objects {
|
for i := range objects {
|
||||||
if errs[i] != nil {
|
if errs[i] != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if isObjectDirs[i] {
|
// Assume (N/2 + 1) quorums for all objects
|
||||||
writeQuorums[i] = len(xl.getDisks())/2 + 1
|
// this is a theoretical assumption such that
|
||||||
} else {
|
// for delete's we do not need to honor storage
|
||||||
var err error
|
// class for objects which have reduced quorum
|
||||||
// Read metadata associated with the object from all disks.
|
// storage class only needs to be honored for
|
||||||
partsMetadata, readXLErrs := readAllXLMetadata(ctx, xl.getDisks(), bucket, object)
|
// Read() requests alone which we already do.
|
||||||
// get Quorum for this object
|
writeQuorums[i] = len(xl.getDisks())/2 + 1
|
||||||
_, writeQuorums[i], err = objectQuorumFromMeta(ctx, xl, partsMetadata, readXLErrs)
|
|
||||||
if err != nil {
|
|
||||||
errs[i] = toObjectErr(err, bucket, object)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xl.doDeleteObjects(ctx, bucket, objects, errs, writeQuorums, isObjectDirs)
|
return xl.doDeleteObjects(ctx, bucket, objects, errs, writeQuorums, isObjectDirs)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user