Skip to content

Commit

Permalink
Add basic structure for boltDB local storage
Browse files Browse the repository at this point in the history
See #9
  • Loading branch information
rafaeljusto committed Apr 13, 2017
1 parent 806e362 commit 50f8d51
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Send report with the scheduler actions periodically
- Output to a log file using logrus library
- Log verbosity defined in configuration
- BoltDB storage for tracking backups locally

### Fixed
- Add sample configuration file to deb and txz packages
Expand Down
120 changes: 120 additions & 0 deletions internal/storage/boltdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package storage

import (
"encoding/json"

"github.com/boltdb/bolt"
"github.com/pkg/errors"
"github.com/rafaeljusto/toglacier/internal/cloud"
"github.com/rafaeljusto/toglacier/internal/log"
)

var boltDBBucket = []byte("toglacier")

const boltDBFileMode = 0600

type BoltDB struct {
logger log.Logger
Filename string
}

func NewBoltDB(filename string, logger log.Logger) *BoltDB {
return &BoltDB{
logger: logger,
Filename: filename,
}
}

func (b *BoltDB) Save(backup cloud.Backup) error {
db, err := bolt.Open(b.Filename, boltDBFileMode, nil)
if err != nil {
return errors.WithStack(newError(ErrorCodeOpeningFile, err))
}
defer db.Close()

encoded, err := json.Marshal(b)
if err != nil {
return errors.WithStack(newError(ErrorCodeEncodingBackup, err))
}

err = db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(boltDBBucket)
if bucket == nil {
return errors.WithStack(newError(ErrorCodeDatabaseNotFound, nil))
}

if err := bucket.Put([]byte(backup.ID), encoded); err != nil {
return errors.WithStack(newError(ErrorCodeSave, err))
}

return nil
})

if err != nil {
return errors.WithStack(newError(ErrorCodeWritingFile, err))
}

return nil
}

func (b BoltDB) List() ([]cloud.Backup, error) {
db, err := bolt.Open(b.Filename, boltDBFileMode, nil)
if err != nil {
return nil, errors.WithStack(newError(ErrorCodeOpeningFile, err))
}
defer db.Close()

var backups []cloud.Backup

db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(boltDBBucket)
if bucket == nil {
// no backup stored yet
return nil
}

err := bucket.ForEach(func(k, v []byte) error {
var backup cloud.Backup
if err := json.Unmarshal(v, &backup); err != nil {
return errors.WithStack(newError(ErrorCodeDecodingBackup, err))
}
backups = append(backups, backup)
return nil
})

if err != nil {
return errors.WithStack(newError(ErrorCodeListing, err))
}

return nil
})

return backups, nil
}

func (b BoltDB) Remove(id string) error {
db, err := bolt.Open(b.Filename, boltDBFileMode, nil)
if err != nil {
return errors.WithStack(newError(ErrorCodeOpeningFile, err))
}
defer db.Close()

err = db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(boltDBBucket)
if bucket == nil {
return errors.WithStack(newError(ErrorCodeDatabaseNotFound, nil))
}

if err := bucket.Delete([]byte(id)); err != nil {
return errors.WithStack(newError(ErrorCodeDelete, err))
}

return nil
})

if err != nil {
return errors.WithStack(newError(ErrorCodeWritingFile, err))
}

return nil
}
31 changes: 31 additions & 0 deletions internal/storage/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ const (

// ErrorCodeDateFormat strange date format found in the local storage file.
ErrorCodeDateFormat ErrorCode = "date-format"

// ErrorCodeEncodingBackup failed to encode the backup to a storage
// representation.
ErrorCodeEncodingBackup ErrorCode = "encoding-backup"

// ErrorCodeDecodingBackup failed to decode the backup to the original format.
ErrorCodeDecodingBackup ErrorCode = "decoding-backup"

// ErrorCodeDatabaseNotFound database wasn't found.
ErrorCodeDatabaseNotFound ErrorCode = "database-not-found"

// ErrorCodeListing failed to list the backups from the database.
ErrorCodeListing ErrorCode = "listing"

// ErrorCodeSave failed to save the item in the database.
ErrorCodeSave ErrorCode = "save"

// ErrorCodeDelete failed to remove the item from the database.
ErrorCodeDelete ErrorCode = "delete"
)

// ErrorCode stores the error type that occurred while managing the local
Expand All @@ -50,6 +69,18 @@ func (e ErrorCode) String() string {
return "unexpected storage file format"
case ErrorCodeDateFormat:
return "invalid date format"
case ErrorCodeEncodingBackup:
return "failed to encode backup to a storage representation"
case ErrorCodeDecodingBackup:
return "failed to decode backup to the original representation"
case ErrorCodeDatabaseNotFound:
return "database not found"
case ErrorCodeListing:
return "failed to list backups in the database"
case ErrorCodeSave:
return "failed to save the item in the database"
case ErrorCodeDelete:
return "failed to remove the item from the database"
}

return "unknown error code"
Expand Down

0 comments on commit 50f8d51

Please sign in to comment.