linker.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package hybridBackup
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "path/filepath"
  7. "strings"
  8. )
  9. /*
  10. Linker.go
  11. This script handle the linking file operations
  12. */
  13. type LinkFileMap struct {
  14. UnchangedFile map[string]string
  15. DeletedFiles map[string]string
  16. }
  17. //Generate and write link file to disk
  18. func generateLinkFile(snapshotFolder string, lf LinkFileMap) error {
  19. js, err := json.MarshalIndent(lf, "", "\t")
  20. if err != nil {
  21. return err
  22. }
  23. return ioutil.WriteFile(filepath.Join(snapshotFolder, "snapshot.datalink"), js, 0755)
  24. }
  25. //Read link file and parse it into link file map
  26. func readLinkFile(snapshotFolder string) (*LinkFileMap, error) {
  27. result := LinkFileMap{
  28. UnchangedFile: map[string]string{},
  29. DeletedFiles: map[string]string{},
  30. }
  31. //Check if the link file exists
  32. expectedLinkFilePath := filepath.Join(snapshotFolder, "snapshot.datalink")
  33. if fileExists(expectedLinkFilePath) {
  34. //Read the content of the link file
  35. content, err := ioutil.ReadFile(expectedLinkFilePath)
  36. if err == nil {
  37. //No error. Read and parse the content
  38. lfContent := LinkFileMap{}
  39. err := json.Unmarshal(content, &lfContent)
  40. if err == nil {
  41. return &lfContent, nil
  42. }
  43. }
  44. } else {
  45. return &result, errors.New("Linker file not exists")
  46. }
  47. return &result, nil
  48. }
  49. //Update the linker by given a snapshot name to a new one
  50. func updateLinkerPointer(snapshotFolder string, oldSnapshotLink string, newSnapshotLink string) error {
  51. oldSnapshotLink = strings.TrimSpace(oldSnapshotLink)
  52. newSnapshotLink = strings.TrimSpace(newSnapshotLink)
  53. //Load the old linker file
  54. oldlinkMap, err := readLinkFile(snapshotFolder)
  55. if err != nil {
  56. return err
  57. }
  58. //Iterate and replace all link that is pointing to the same snapshot
  59. newLinkMap := LinkFileMap{
  60. UnchangedFile: map[string]string{},
  61. DeletedFiles: map[string]string{},
  62. }
  63. for rel, link := range oldlinkMap.UnchangedFile {
  64. if link == oldSnapshotLink {
  65. link = newSnapshotLink
  66. }
  67. newLinkMap.UnchangedFile[rel] = link
  68. }
  69. for rel, ts := range oldlinkMap.DeletedFiles {
  70. newLinkMap.DeletedFiles[rel] = ts
  71. }
  72. //Write it back to file
  73. return generateLinkFile(snapshotFolder, newLinkMap)
  74. }
  75. //Check if a file exists in a linkFileMap. return boolean and its linked to snapshot name
  76. func (lfm *LinkFileMap) fileExists(fileRelPath string) (bool, string) {
  77. val, ok := lfm.UnchangedFile[filepath.ToSlash(fileRelPath)]
  78. if !ok {
  79. return false, ""
  80. } else {
  81. return true, val
  82. }
  83. }