forked from RedBird96/b7s
/
sync.go
114 lines (90 loc) · 3.14 KB
/
sync.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package fstore
import (
"fmt"
"os"
"path/filepath"
)
// Sync will verify that the function identified by `cid` is still found on the local filesystem.
// If the function archive of function files are missing, they will be recreated.
func (h *FStore) Sync(cid string) error {
h.log.Debug().Str("cid", cid).Msg("checking function installation")
// Read the function directly from storage - we don't want to update the timestamp
// since this is a 'maintenance' access.
var fn functionRecord
err := h.store.GetRecord(cid, &fn)
if err != nil {
return fmt.Errorf("could not get function record: %w", err)
}
h.log.Debug().
Str("cid", cid).
Str("archive", fn.Archive).
Str("files", fn.Files).
Msg("checking function installation")
haveArchive, haveFiles, err := h.checkFunctionFiles(fn)
if err != nil {
return fmt.Errorf("could not verify function cache: %w", err)
}
// If both archive and files are there - we're done.
if haveArchive && haveFiles {
h.log.Debug().Str("cid", cid).Msg("function files found, done")
return nil
}
h.log.Debug().
Bool("have_archive", haveArchive).
Bool("have_files", haveFiles).
Str("cid", cid).
Msg("function installation missing files")
// If we don't have the archive - redownload it.
if !haveArchive {
path, err := h.download(cid, fn.Manifest)
if err != nil {
return fmt.Errorf("could not download the function archive (cid: %v): %w", cid, err)
}
// Update path in case it changed.
fn.Archive = h.cleanPath(path)
}
// If we don't have the files OR if we redownloaded the archive - recreate the files.
if !haveFiles || !haveArchive {
archivePath := filepath.Join(h.workdir, fn.Archive)
files := filepath.Join(h.workdir, fn.CID)
h.log.Info().
Str("archive", archivePath).
Str("fn_archive", fn.Archive).
Msg("archive path to use")
err = h.unpackArchive(archivePath, files)
if err != nil {
return fmt.Errorf("could not unpack gzip archive (cid: %v, file: %s): %w", cid, fn.Archive, err)
}
fn.Files = files
}
// Save the updated function record.
err = h.saveFunction(fn)
if err != nil {
return fmt.Errorf("could not save function (cid: %v): %w", cid, err)
}
return nil
}
// checkFunctionFiles checks if the files required by the function are found on local storage.
// It returns two booleans indicating presence of the archive file, the unpacked files, and a potential error.
func (h *FStore) checkFunctionFiles(fn functionRecord) (bool, bool, error) {
// Check if the archive is found.
archiveFound := true
apath := filepath.Join(h.workdir, fn.Archive)
_, err := os.Stat(apath)
if err != nil && os.IsNotExist(err) {
archiveFound = false
} else if err != nil {
return false, false, fmt.Errorf("could not stat function archive: %w", err)
}
// NOTE: We could check that it's a regular file (plus cheksum), but lets not go overboard for now.
// Check if the files are found.
filesFound := true
fpath := filepath.Join(h.workdir, fn.Files)
_, err = os.Stat(fpath)
if err != nil && os.IsNotExist(err) {
filesFound = false
} else if err != nil {
return false, false, fmt.Errorf("could not stat function files: %w", err)
}
return archiveFound, filesFound, nil
}