mirror of
https://github.com/pgsty/minio.git
synced 2026-10-06 17:55:59 +03:00
[feat] use rename instead of recursive deletes (#11641)
most of the delete calls today spend time in a blocking operation where multiple calls need to be recursively sent to delete the objects, instead we can use rename operation to atomically move the objects from the namespace to `tmp/.trash` we can schedule deletion of objects at this location once in 15, 30mins and we can also add wait times between each delete operation. this allows us to make delete's faster as well less chattier on the drives, each server runs locally a groutine which would clean this up regularly.
This commit is contained in:
+16
-51
@@ -940,7 +940,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
|
||||
if !isXL2V1Format(buf) {
|
||||
// Delete the meta file, if there are no more versions the
|
||||
// top level parent is automatically removed.
|
||||
return deleteFile(volumeDir, pathJoin(volumeDir, path), true)
|
||||
return s.deleteFile(volumeDir, pathJoin(volumeDir, path), true)
|
||||
}
|
||||
|
||||
var xlMeta xlMetaV2
|
||||
@@ -967,7 +967,8 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
|
||||
return err
|
||||
}
|
||||
|
||||
if err = removeAll(filePath); err != nil {
|
||||
tmpuuid := mustGetUUID()
|
||||
if err = renameAll(filePath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, tmpuuid)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -985,7 +986,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
|
||||
return err
|
||||
}
|
||||
|
||||
return deleteFile(volumeDir, filePath, false)
|
||||
return s.deleteFile(volumeDir, filePath, false)
|
||||
}
|
||||
|
||||
// WriteMetadata - writes FileInfo metadata for path at `xl.meta`
|
||||
@@ -1828,7 +1829,7 @@ func (s *xlStorage) CheckFile(ctx context.Context, volume string, path string) e
|
||||
// move up the tree, deleting empty parent directories until it finds one
|
||||
// with files in it. Returns nil for a non-empty directory even when
|
||||
// recursive is set to false.
|
||||
func deleteFile(basePath, deletePath string, recursive bool) error {
|
||||
func (s *xlStorage) deleteFile(basePath, deletePath string, recursive bool) error {
|
||||
if basePath == "" || deletePath == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -1841,7 +1842,8 @@ func deleteFile(basePath, deletePath string, recursive bool) error {
|
||||
|
||||
var err error
|
||||
if recursive {
|
||||
err = os.RemoveAll(deletePath)
|
||||
tmpuuid := mustGetUUID()
|
||||
err = renameAll(deletePath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, tmpuuid))
|
||||
} else {
|
||||
err = os.Remove(deletePath)
|
||||
}
|
||||
@@ -1872,7 +1874,7 @@ func deleteFile(basePath, deletePath string, recursive bool) error {
|
||||
|
||||
// Delete parent directory obviously not recursively. Errors for
|
||||
// parent directories shouldn't trickle down.
|
||||
deleteFile(basePath, deletePath, false)
|
||||
s.deleteFile(basePath, deletePath, false)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1910,46 +1912,7 @@ func (s *xlStorage) Delete(ctx context.Context, volume string, path string, recu
|
||||
}
|
||||
|
||||
// Delete file and delete parent directory as well if it's empty.
|
||||
return deleteFile(volumeDir, filePath, recursive)
|
||||
}
|
||||
|
||||
func (s *xlStorage) 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.Lstat(volumeDir)
|
||||
if err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return nil, errVolumeNotFound
|
||||
} else if osIsPermission(err) {
|
||||
return nil, errVolumeAccessDenied
|
||||
} else if isSysErrIO(err) {
|
||||
return nil, errFaultyDisk
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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 {
|
||||
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, false)
|
||||
}
|
||||
return
|
||||
return s.deleteFile(volumeDir, filePath, recursive)
|
||||
}
|
||||
|
||||
// RenameData - rename source path to destination path atomically, metadata and data directory.
|
||||
@@ -2180,8 +2143,10 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath, dataDir,
|
||||
|
||||
// Commit data
|
||||
if srcDataPath != "" {
|
||||
removeAll(oldDstDataPath)
|
||||
removeAll(dstDataPath)
|
||||
tmpuuid := mustGetUUID()
|
||||
renameAll(oldDstDataPath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, tmpuuid))
|
||||
tmpuuid = mustGetUUID()
|
||||
renameAll(dstDataPath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, tmpuuid))
|
||||
if err = renameAll(srcDataPath, dstDataPath); err != nil {
|
||||
return osErrToFileErr(err)
|
||||
}
|
||||
@@ -2194,12 +2159,12 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath, dataDir,
|
||||
|
||||
// Remove parent dir of the source file if empty
|
||||
if parentDir := pathutil.Dir(srcFilePath); isDirEmpty(parentDir) {
|
||||
deleteFile(srcVolumeDir, parentDir, false)
|
||||
s.deleteFile(srcVolumeDir, parentDir, false)
|
||||
}
|
||||
|
||||
if srcDataPath != "" {
|
||||
if parentDir := pathutil.Dir(srcDataPath); isDirEmpty(parentDir) {
|
||||
deleteFile(srcVolumeDir, parentDir, false)
|
||||
s.deleteFile(srcVolumeDir, parentDir, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2286,7 +2251,7 @@ func (s *xlStorage) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolum
|
||||
|
||||
// Remove parent dir of the source file if empty
|
||||
if parentDir := pathutil.Dir(srcFilePath); isDirEmpty(parentDir) {
|
||||
deleteFile(srcVolumeDir, parentDir, false)
|
||||
s.deleteFile(srcVolumeDir, parentDir, false)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user