mirror of
https://github.com/Luzifer/cloudbox.git
synced 2024-12-22 18:51:21 +00:00
Add sync logic and execution
This commit is contained in:
parent
bf10539e34
commit
b14ed6052f
5 changed files with 132 additions and 3 deletions
12
sync/db.go
12
sync/db.go
|
@ -29,6 +29,16 @@ func (s *Sync) initSchema() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Sync) deleteDBFileInfo(side, relativeName string) error {
|
||||||
|
stmt, err := s.db.Prepare(fmt.Sprintf(`DELETE FROM %s_state WHERE relative_name = ?`, side))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to prepare query")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = stmt.Exec(relativeName)
|
||||||
|
return errors.Wrap(err, "Unable to delete file info")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Sync) getDBFileInfo(side, relativeName string) (providers.FileInfo, error) {
|
func (s *Sync) getDBFileInfo(side, relativeName string) (providers.FileInfo, error) {
|
||||||
info := providers.FileInfo{}
|
info := providers.FileInfo{}
|
||||||
|
|
||||||
|
@ -48,7 +58,7 @@ func (s *Sync) getDBFileInfo(side, relativeName string) (providers.FileInfo, err
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sync) setDBFileInfo(side, info providers.FileInfo) error {
|
func (s *Sync) setDBFileInfo(side string, info providers.FileInfo) error {
|
||||||
stmt, err := s.db.Prepare(fmt.Sprintf(
|
stmt, err := s.db.Prepare(fmt.Sprintf(
|
||||||
`INSERT INTO %s_state VALUES(?, ?, ?, ?)
|
`INSERT INTO %s_state VALUES(?, ?, ?, ?)
|
||||||
ON CONFLICT(relative_name) DO UPDATE SET
|
ON CONFLICT(relative_name) DO UPDATE SET
|
||||||
|
|
45
sync/execute.go
Normal file
45
sync/execute.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/Luzifer/cloudbox/providers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Sync) deleteFile(on providers.CloudProvider, fileName string) error {
|
||||||
|
if err := on.DeleteFile(fileName); err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to delete file")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.deleteDBFileInfo(sideLocal, fileName); err != nil {
|
||||||
|
return errors.Wrap(err, "Umable to delete local file info")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.deleteDBFileInfo(sideRemote, fileName); err != nil {
|
||||||
|
return errors.Wrap(err, "Umable to delete remote file info")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sync) transferFile(from, to providers.CloudProvider, sideFrom, sideTo, fileName string) error {
|
||||||
|
file, err := from.GetFile(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to retrieve file")
|
||||||
|
}
|
||||||
|
|
||||||
|
newFile, err := to.PutFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to put file")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.setDBFileInfo(sideTo, newFile.Info()); err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to update DB info for target file")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.setDBFileInfo(sideFrom, file.Info()); err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to update DB info for source file")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
61
sync/logic.go
Normal file
61
sync/logic.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package sync
|
||||||
|
|
||||||
|
import log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
func (s *Sync) decideAction(syncState *state, fileName string) error {
|
||||||
|
var (
|
||||||
|
change = syncState.GetChangeFor(fileName)
|
||||||
|
logger = log.WithField("filename", fileName)
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case !change.Changed():
|
||||||
|
// No changes at all: Get out of here
|
||||||
|
logger.Debug("File in sync")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case change.HasAll(ChangeLocalUpdate, ChangeRemoteUpdate):
|
||||||
|
// We do have local and remote changes: Check both are now the same or leave this to manual resolve
|
||||||
|
logger.Warn("File has local and remote updates, sync not possible")
|
||||||
|
|
||||||
|
case change.HasAll(ChangeLocalAdd, ChangeRemoteAdd):
|
||||||
|
// Special case: Both are added, check thet are the same file or break
|
||||||
|
logger.Debug("File added locally as well as remotely")
|
||||||
|
// TODO: Handle special case
|
||||||
|
|
||||||
|
case change.HasAll(ChangeLocalDelete, ChangeRemoteDelete):
|
||||||
|
// Special case: Both vanished, we just need to clean up the sync cache
|
||||||
|
logger.Debug("File deleted locally as well as remotely")
|
||||||
|
// TODO: Handle special case
|
||||||
|
|
||||||
|
case change.Is(ChangeLocalAdd) || change.Is(ChangeLocalUpdate):
|
||||||
|
logger.Debug("File added or changed locally, uploading...")
|
||||||
|
if err := s.transferFile(s.local, s.remote, sideLocal, sideRemote, fileName); err != nil {
|
||||||
|
logger.WithError(err).Error("Unable to upload file")
|
||||||
|
}
|
||||||
|
|
||||||
|
case change.Is(ChangeLocalDelete):
|
||||||
|
logger.Debug("File deleted locally, removing from remote...")
|
||||||
|
if err := s.deleteFile(s.remote, fileName); err != nil {
|
||||||
|
logger.WithError(err).Error("Unable to delete file from remote")
|
||||||
|
}
|
||||||
|
|
||||||
|
case change.Is(ChangeRemoteAdd) || change.Is(ChangeRemoteUpdate):
|
||||||
|
logger.Debug("File added or changed remotely, downloading...")
|
||||||
|
if err := s.transferFile(s.remote, s.local, sideRemote, sideLocal, fileName); err != nil {
|
||||||
|
logger.WithError(err).Error("Unable to download file")
|
||||||
|
}
|
||||||
|
|
||||||
|
case change.Is(ChangeRemoteDelete):
|
||||||
|
logger.Debug("File deleted remotely, removing from local...")
|
||||||
|
if err := s.deleteFile(s.local, fileName); err != nil {
|
||||||
|
logger.WithError(err).Error("Unable to delete file from local")
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unhandled case
|
||||||
|
logger.WithField("change", change).Warn("Unhandled change case")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -27,6 +27,16 @@ func (c *Change) Register(add Change) {
|
||||||
*c = *c | add
|
*c = *c | add
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Change) HasAll(test ...Change) bool {
|
||||||
|
for _, t := range test {
|
||||||
|
if c&t == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (c Change) HasOne(test ...Change) bool {
|
func (c Change) HasOne(test ...Change) bool {
|
||||||
for _, t := range test {
|
for _, t := range test {
|
||||||
if c&t != 0 {
|
if c&t != 0 {
|
||||||
|
|
|
@ -103,8 +103,11 @@ func (s *Sync) runSync() error {
|
||||||
return errors.Wrap(err, "Unable to load remote files")
|
return errors.Wrap(err, "Unable to load remote files")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Do something with sync database
|
for _, fileName := range syncState.GetRelativeNames() {
|
||||||
s.log.Printf("%#v", syncState)
|
if err := s.decideAction(syncState, fileName); err != nil {
|
||||||
|
return errors.Wrap(err, "Could not execute sync")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue