Skip to content

Commit

Permalink
Merge pull request ByteStorage#302 from ByteStorage/backup
Browse files Browse the repository at this point in the history
Data Backup
  • Loading branch information
qishenonly authored Jan 23, 2024
2 parents 38d7ec4 + 2a7c016 commit 32fb125
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
10 changes: 10 additions & 0 deletions db/engine/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/ByteStorage/FlyDB/config"
data2 "github.com/ByteStorage/FlyDB/db/data"
"github.com/ByteStorage/FlyDB/db/index"
"github.com/ByteStorage/FlyDB/lib/backup"
"github.com/ByteStorage/FlyDB/lib/const"
"go.uber.org/zap"
"io"
Expand Down Expand Up @@ -544,6 +545,15 @@ func (db *DB) loadIndexFromDataFiles() error {
return nil
}

// Backup the database to the specified directory
func (db *DB) Backup(dir string) error {
db.lock.RLock()
defer db.lock.RUnlock()

// Create a backup directory
return backup.CopyDir(db.options.DirPath, dir)
}

// Clean the DB data directory after the test is complete
func (db *DB) Clean() {
if db != nil {
Expand Down
27 changes: 27 additions & 0 deletions db/engine/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,30 @@ func TestDB_Sync(t *testing.T) {
err = db.Sync()
assert.Nil(t, err)
}

func TestDB_Backup(t *testing.T) {
opts := config.DefaultOptions
dir, _ := os.MkdirTemp("", "flydb-backup")
opts.DirPath = dir
opts.DataFileSize = 64 * 1024 * 1024
db, err := NewDB(opts)
defer destroyDB(db)
assert.Nil(t, err)
assert.NotNil(t, db)

for i := 1; i < 1000000; i++ {
err = db.Put(randkv.GetTestKey(i), randkv.RandomValue(128))
assert.Nil(t, err)
}

backupDir, _ := os.MkdirTemp("", "flydb-backup-test")
err = db.Backup(backupDir)
assert.Nil(t, err)

opts1 := config.DefaultOptions
opts1.DirPath = backupDir
db1, err := NewDB(opts1)
defer destroyDB(db1)
assert.Nil(t, err)
assert.NotNil(t, db1)
}
87 changes: 87 additions & 0 deletions lib/backup/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package backup

import (
"io"
"os"
"path/filepath"
)

// CopyFile copies a file from src to dest.
func copyFile(src, dest string, mode os.FileMode) error {
// Open the source file
srcFile, err := os.OpenFile(src, os.O_RDONLY, mode)
if err != nil {
return err
}
defer func(srcFile *os.File) {
err = srcFile.Close()
if err != nil {
panic(err)
}
}(srcFile)

// Create or open the destination file
destFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
if err != nil {
// Close the source file if opening destination file fails
err = srcFile.Close()
if err != nil {
return err
}
return err
}
defer func(destFile *os.File) {
err = destFile.Close()
if err != nil {
panic(err)
}
}(destFile)

// Copy the contents of the source file to the destination file
if _, err = io.Copy(destFile, srcFile); err != nil {
return err
}

// Set permissions on destination files
return os.Chmod(dest, 0644)
}

// CopyDir copies a directory from src to dest.
func CopyDir(src, dest string) error {
// Get the source directory information
srcInfo, err := os.Stat(src)
if err != nil {
return err
}

// Create the destination directory
if err = os.MkdirAll(dest, srcInfo.Mode()); err != nil {
return err
}

// Get the contents of the source directory
entries, err := os.ReadDir(src)
if err != nil {
return err
}

// Copy the contents of the source directory to the destination directory
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
destPath := filepath.Join(dest, entry.Name())

if entry.IsDir() {
// If it is a subdirectory, call CopyDir recursively
if err = CopyDir(srcPath, destPath); err != nil {
return err
}
} else {
// If it is a file, call copyFile to copy the file content
if err = copyFile(srcPath, destPath, entry.Type()); err != nil {
return err
}
}
}

return nil
}

0 comments on commit 32fb125

Please sign in to comment.