Skip to content

Commit 09f0838

Browse files
authored
fix: inc backup and recover (openGemini#815)
Signed-off-by: xiangyu5632 <xiangyu5632@126.com>
1 parent 7f7e298 commit 09f0838

File tree

3 files changed

+249
-18
lines changed

3 files changed

+249
-18
lines changed

app/ts-recover/recover/recover.go

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,14 @@ func recoverWithFullAndInc(tsRecover *config.TsRecover, rc *RecoverConfig) error
9191
if err := os.RemoveAll(dataPath); err != nil {
9292
return err
9393
}
94+
// recover full_backup
9495
fullBackupDataPath := filepath.Join(rc.FullBackupDataPath, backup.DataBackupDir, dataPath)
9596
if err := traversalBackupLogFile(rc, fullBackupDataPath, copyWithFullAndInc, true); err != nil {
9697
return err
9798
}
99+
// recover inc_backup
98100
incBackupDataPath := filepath.Join(rc.IncBackupDataPath, backup.DataBackupDir, dataPath)
99-
if err := traversalIndexFile(rc, incBackupDataPath); err != nil {
101+
if err := traversalIncBackupLogFile(rc, incBackupDataPath); err != nil {
100102
return err
101103
}
102104
return nil
@@ -195,7 +197,7 @@ func traversalBackupLogFile(rc *RecoverConfig, path string, fn RecoverFunc, isIn
195197
return nil
196198
}
197199

198-
func traversalIndexFile(rc *RecoverConfig, path string) error {
200+
func traversalIncBackupLogFile(rc *RecoverConfig, path string) error {
199201
var err error
200202
var fds []fs.FileInfo
201203

@@ -217,9 +219,20 @@ func traversalIndexFile(rc *RecoverConfig, path string) error {
217219
}
218220
continue
219221
}
220-
if err = traversalIndexFile(rc, srcfp); err != nil {
222+
if err = traversalIncBackupLogFile(rc, srcfp); err != nil {
221223
return err
222224
}
225+
} else {
226+
if fd.Name() == backup.IncBackupLog {
227+
if err := copyWithInc(rc, srcfp); err != nil {
228+
return err
229+
}
230+
// recover log file
231+
outPath := strings.Replace(srcfp, filepath.Join(rc.IncBackupDataPath, backup.DataBackupDir), "", -1)
232+
if err := backup.FileMove(srcfp, outPath); err != nil {
233+
return err
234+
}
235+
}
223236
}
224237
}
225238
return nil
@@ -274,21 +287,51 @@ func copyWithFullAndInc(rc *RecoverConfig, fullPath string) error {
274287
return err
275288
}
276289

277-
err = mergeFileList(rc, backupLog.OrderFileListMap, incBackupLog.AddOrderFileListMap, incBackupLog.DelOrderFileListMap)
290+
err = mergeFileList(rc, backupLog.OrderFileListMap, incBackupLog.DelOrderFileListMap)
278291
if err != nil {
279292
return err
280293
}
281-
err = mergeFileList(rc, backupLog.OutOfOrderFileListMap, incBackupLog.AddOutOfOrderFileListMap, incBackupLog.DelOutOfOrderFileListMap)
294+
err = mergeFileList(rc, backupLog.OutOfOrderFileListMap, incBackupLog.DelOutOfOrderFileListMap)
282295
if err != nil {
283296
return err
284297
}
285298

286299
return nil
287300
}
288301

289-
func mergeFileList(rc *RecoverConfig, listMap, addListMap, delListMap map[string][][]string) error {
302+
func copyWithInc(rc *RecoverConfig, incPath string) error {
303+
backupLog := &backup.IncBackupLogInfo{}
304+
if err := backup.ReadBackupLogFile(incPath, backupLog); err != nil {
305+
return err
306+
}
307+
308+
basicPath := filepath.Join(rc.IncBackupDataPath, backup.DataBackupDir)
309+
for _, fileList := range backupLog.AddOrderFileListMap {
310+
for _, files := range fileList {
311+
srcPath := filepath.Join(basicPath, files[0])
312+
for _, f := range files {
313+
if err := backup.FileMove(srcPath, f); err != nil {
314+
return err
315+
}
316+
}
317+
}
318+
}
319+
320+
for _, fileList := range backupLog.AddOutOfOrderFileListMap {
321+
for _, files := range fileList {
322+
srcPath := filepath.Join(basicPath, files[0])
323+
for _, f := range files {
324+
if err := backup.FileMove(srcPath, f); err != nil {
325+
return err
326+
}
327+
}
328+
}
329+
}
330+
return nil
331+
}
332+
333+
func mergeFileList(rc *RecoverConfig, listMap, delListMap map[string][][]string) error {
290334
fullBasicPath := filepath.Join(rc.FullBackupDataPath, backup.DataBackupDir)
291-
incBasicPath := filepath.Join(rc.IncBackupDataPath, backup.DataBackupDir)
292335
for name, fileList := range listMap {
293336
dListSeen := make(map[string]bool)
294337
if dLists, ok := delListMap[name]; ok {
@@ -310,15 +353,5 @@ func mergeFileList(rc *RecoverConfig, listMap, addListMap, delListMap map[string
310353
}
311354

312355
}
313-
for _, aLists := range addListMap {
314-
for _, files := range aLists {
315-
srcPath := filepath.Join(incBasicPath, files[0])
316-
for _, f := range files {
317-
if err := backup.FileMove(srcPath, f); err != nil {
318-
return err
319-
}
320-
}
321-
}
322-
}
323356
return nil
324357
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
Copyright 2024 Huawei Cloud Computing Technologies Co., Ltd.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package recover
18+
19+
import (
20+
"os"
21+
"path/filepath"
22+
"testing"
23+
24+
"github.com/openGemini/openGemini/lib/config"
25+
"github.com/openGemini/openGemini/lib/fileops"
26+
"github.com/stretchr/testify/assert"
27+
)
28+
29+
func TestRunBackupRecoverConfig(t *testing.T) {
30+
t.Run("1", func(t *testing.T) {
31+
rcConifg := &RecoverConfig{}
32+
err := BackupRecover(rcConifg, nil)
33+
if err == nil {
34+
t.Fail()
35+
}
36+
})
37+
t.Run("2", func(t *testing.T) {
38+
rcConifg := &RecoverConfig{
39+
FullBackupDataPath: "/",
40+
RecoverMode: FullAndIncRecoverMode,
41+
}
42+
err := BackupRecover(rcConifg, nil)
43+
if err == nil {
44+
t.Fail()
45+
}
46+
})
47+
t.Run("3", func(t *testing.T) {
48+
rcConifg := &RecoverConfig{
49+
FullBackupDataPath: "/",
50+
RecoverMode: "3",
51+
}
52+
err := BackupRecover(rcConifg, nil)
53+
if err == nil {
54+
t.Fail()
55+
}
56+
})
57+
}
58+
59+
func TestRecoverMeta(t *testing.T) {
60+
tmpDir := t.TempDir()
61+
62+
fullBackupPath := filepath.Join(tmpDir, "openGemini/backup_dir/backup")
63+
incBackupPath := filepath.Join(tmpDir, "openGemini/backup_dir/backup_inc")
64+
recoverConfig := &RecoverConfig{
65+
RecoverMode: "2",
66+
FullBackupDataPath: fullBackupPath,
67+
IncBackupDataPath: incBackupPath,
68+
}
69+
tsRecover := &config.TsRecover{
70+
Data: config.Store{
71+
DataDir: filepath.Join(tmpDir, "openGemini/backup_dir/data"),
72+
MetaDir: filepath.Join(tmpDir, "openGemini/backup_dir/meta"),
73+
},
74+
}
75+
76+
t.Run("isInc=true", func(t *testing.T) {
77+
content := `{"metaIds":["1"],"isNode":true}`
78+
CreateFile(filepath.Join(tmpDir, "openGemini/backup_dir/backup_inc/meta_backup/backup_log/meta_backup_log.json"), content)
79+
recoverMeta(tsRecover, recoverConfig, true)
80+
})
81+
82+
t.Run("isInc=false", func(t *testing.T) {
83+
content := `{"metaIds":["1","2"],"isNode":false}`
84+
CreateFile(filepath.Join(tmpDir, "openGemini/backup_dir/backup/meta_backup/backup_log/meta_backup_log.json"), content)
85+
recoverMeta(tsRecover, recoverConfig, false)
86+
})
87+
88+
os.RemoveAll(filepath.Join(tmpDir, "openGemini/backup_dir"))
89+
}
90+
91+
func TestRecoverError(t *testing.T) {
92+
fullBackupPath := "/tmp/openGemini/backup_dir/backup"
93+
incBackupPath := "/tmp/openGemini/backup_dir/backup_inc"
94+
95+
recoverConfig := &RecoverConfig{
96+
RecoverMode: "2",
97+
FullBackupDataPath: fullBackupPath,
98+
IncBackupDataPath: incBackupPath,
99+
}
100+
tsRecover := &config.TsRecover{
101+
Data: config.Store{
102+
DataDir: "/tmp/openGemini/backup_dir/data",
103+
MetaDir: "/tmp/openGemini/backup_dir/meta",
104+
},
105+
}
106+
107+
t.Run("1", func(t *testing.T) {
108+
err := recoverWithFull(tsRecover, recoverConfig)
109+
if err == nil {
110+
t.Fail()
111+
}
112+
})
113+
114+
t.Run("2", func(t *testing.T) {
115+
err := recoverWithFullAndInc(tsRecover, recoverConfig)
116+
if err == nil {
117+
t.Fail()
118+
}
119+
})
120+
}
121+
122+
func Test_TraversalBackupLogFile_Error(t *testing.T) {
123+
fullBackupPath := "/tmp/openGemini/backup_dir/backup"
124+
incBackupPath := "/tmp/openGemini/backup_dir/backup_inc"
125+
126+
recoverConfig := &RecoverConfig{
127+
RecoverMode: "2",
128+
FullBackupDataPath: fullBackupPath,
129+
IncBackupDataPath: incBackupPath,
130+
}
131+
132+
err := traversalBackupLogFile(recoverConfig, fullBackupPath, copyWithFull, false)
133+
134+
if err == nil {
135+
t.Fatal()
136+
}
137+
}
138+
139+
func Test_traversalIncBackupLogFile_Error(t *testing.T) {
140+
fullBackupPath := "/tmp/openGemini/backup_dir/backup"
141+
incBackupPath := "/tmp/openGemini/backup_dir/backup_inc"
142+
143+
recoverConfig := &RecoverConfig{
144+
RecoverMode: "1",
145+
FullBackupDataPath: fullBackupPath,
146+
IncBackupDataPath: incBackupPath,
147+
}
148+
149+
err := traversalIncBackupLogFile(recoverConfig, incBackupPath)
150+
151+
if err == nil {
152+
t.Fatal()
153+
}
154+
}
155+
156+
func Test_MergeFileList(t *testing.T) {
157+
fullBackupPath := "/tmp/openGemini/backup_dir/backup"
158+
incBackupPath := "/tmp/openGemini/backup_dir/backup_inc"
159+
160+
recoverConfig := &RecoverConfig{
161+
RecoverMode: "2",
162+
FullBackupDataPath: fullBackupPath,
163+
IncBackupDataPath: incBackupPath,
164+
}
165+
166+
t.Run("1", func(t *testing.T) {
167+
listMap := map[string][][]string{"name1": [][]string{[]string{"/tmp/openGemini/backup_dir/path1.file"}, []string{"/tmp/openGemini/backup_dir/path2.file"}}}
168+
deleteListMap := map[string][][]string{"name1": [][]string{[]string{"/tmp/openGemini/backup_dir/path2.file"}}}
169+
170+
CreateFile("/tmp/openGemini/backup_dir/backup/data_backup/tmp/openGemini/backup_dir/path1.file", "1")
171+
CreateFile("/tmp/openGemini/backup_dir/backup/data_backup/tmp/openGemini/backup_dir/path2.file", "2")
172+
CreateFile("/tmp/openGemini/backup_dir/backup_inc/data_backup/tmp/openGemini/backup_dir/path3.file", "3")
173+
174+
err := mergeFileList(recoverConfig, listMap, deleteListMap)
175+
assert.NoError(t, err)
176+
177+
os.RemoveAll("/tmp/openGemini/backup_dir")
178+
})
179+
180+
t.Run("2", func(t *testing.T) {
181+
listMap := map[string][][]string{"name1": [][]string{[]string{"/tmp/openGemini/backup_dir/path1.file"}, []string{"/tmp/openGemini/backup_dir/path2.file"}}}
182+
deleteListMap := map[string][][]string{"name1": [][]string{[]string{"/tmp/openGemini/backup_dir/path2.file"}}}
183+
184+
err := mergeFileList(recoverConfig, listMap, deleteListMap)
185+
if err == nil {
186+
t.Fatal(err)
187+
}
188+
})
189+
190+
}
191+
192+
func CreateFile(path, content string) {
193+
p, _ := filepath.Split(path)
194+
_ = os.MkdirAll(p, 0750)
195+
fd, _ := fileops.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0640)
196+
fd.Write([]byte(content))
197+
fd.Close()
198+
}

engine/backup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (s *Backup) BackupPt(dbName string, ptId uint32) error {
8484
if s.IsInc {
8585
s.BackupLogInfo = &backup.BackupLogInfo{}
8686
if err := backup.ReadBackupLogFile(filepath.Join(sh.GetDataPath(), backup.BackupLogPath, backup.FullBackupLog), s.BackupLogInfo); err != nil {
87-
return err
87+
log.Info("backupLog file not exist", zap.Error(err))
8888
}
8989
if err := s.IncBackup(sh, backupPath, p.path, peersPtIDMap); err != nil {
9090
return err

0 commit comments

Comments
 (0)