Skip to content

Commit a807031

Browse files
authored
Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971)
* Fix storage Iterate bug and Add storage doctor to delete garbage attachments * Close object when used
1 parent 82da380 commit a807031

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

cmd/doctor.go

-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ func runRecreateTable(ctx *cli.Context) error {
124124
}
125125

126126
func runDoctor(ctx *cli.Context) error {
127-
128127
// Silence the default loggers
129128
log.DelNamedLogger("console")
130129
log.DelNamedLogger(log.DEFAULT)

models/attachment.go

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ func GetAttachmentByUUID(uuid string) (*Attachment, error) {
144144
return getAttachmentByUUID(x, uuid)
145145
}
146146

147+
// ExistAttachmentsByUUID returns true if attachment is exist by given UUID
148+
func ExistAttachmentsByUUID(uuid string) (bool, error) {
149+
return x.Where("`uuid`=?", uuid).Exist(new(Attachment))
150+
}
151+
147152
// GetAttachmentByReleaseIDFileName returns attachment by given releaseId and fileName.
148153
func GetAttachmentByReleaseIDFileName(releaseID int64, fileName string) (*Attachment, error) {
149154
return getAttachmentByReleaseIDFileName(x, releaseID, fileName)

modules/doctor/storage.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package doctor
6+
7+
import (
8+
"code.gitea.io/gitea/models"
9+
"code.gitea.io/gitea/modules/log"
10+
"code.gitea.io/gitea/modules/storage"
11+
)
12+
13+
func checkAttachmentStorageFiles(logger log.Logger, autofix bool) error {
14+
var total, garbageNum int
15+
var deletePaths []string
16+
if err := storage.Attachments.IterateObjects(func(p string, obj storage.Object) error {
17+
defer obj.Close()
18+
19+
total++
20+
stat, err := obj.Stat()
21+
if err != nil {
22+
return err
23+
}
24+
exist, err := models.ExistAttachmentsByUUID(stat.Name())
25+
if err != nil {
26+
return err
27+
}
28+
if !exist {
29+
garbageNum++
30+
if autofix {
31+
deletePaths = append(deletePaths, p)
32+
}
33+
}
34+
return nil
35+
}); err != nil {
36+
logger.Error("storage.Attachments.IterateObjects failed: %v", err)
37+
return err
38+
}
39+
40+
if garbageNum > 0 {
41+
if autofix {
42+
var deletedNum int
43+
for _, p := range deletePaths {
44+
if err := storage.Attachments.Delete(p); err != nil {
45+
log.Error("Delete attachment %s failed: %v", p, err)
46+
} else {
47+
deletedNum++
48+
}
49+
}
50+
logger.Info("%d missed information attachment detected, %d deleted.", garbageNum, deletedNum)
51+
} else {
52+
logger.Warn("Checked %d attachment, %d missed information.", total, garbageNum)
53+
}
54+
}
55+
return nil
56+
}
57+
58+
func checkStorageFiles(logger log.Logger, autofix bool) error {
59+
if err := storage.Init(); err != nil {
60+
logger.Error("storage.Init failed: %v", err)
61+
return err
62+
}
63+
return checkAttachmentStorageFiles(logger, autofix)
64+
}
65+
66+
func init() {
67+
Register(&Check{
68+
Title: "Check if there is garbage storage files",
69+
Name: "storages",
70+
IsDefault: false,
71+
Run: checkStorageFiles,
72+
AbortIfFailed: false,
73+
SkipDatabaseInitialization: false,
74+
Priority: 1,
75+
})
76+
}

modules/storage/minio.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ type minioFileInfo struct {
151151
}
152152

153153
func (m minioFileInfo) Name() string {
154-
return m.ObjectInfo.Key
154+
return path.Base(m.ObjectInfo.Key)
155155
}
156156

157157
func (m minioFileInfo) Size() int64 {
@@ -219,7 +219,7 @@ func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) er
219219
}
220220
if err := func(object *minio.Object, fn func(path string, obj Object) error) error {
221221
defer object.Close()
222-
return fn(strings.TrimPrefix(m.basePath, mObjInfo.Key), &minioObject{object})
222+
return fn(strings.TrimPrefix(mObjInfo.Key, m.basePath), &minioObject{object})
223223
}(object, fn); err != nil {
224224
return convertMinioErr(err)
225225
}

0 commit comments

Comments
 (0)