22
type CacheOnReadFs struct {
25
cacheTime time.Duration
28
func NewCacheOnReadFs(base Fs, layer Fs, cacheTime time.Duration) Fs {
29
return &CacheOnReadFs{base: base, layer: layer, cacheTime: cacheTime}
36
cacheMiss cacheState = iota
48
func (u *CacheOnReadFs) cacheStatus(name string) (state cacheState, fi os.FileInfo, err error) {
49
var lfi, bfi os.FileInfo
50
lfi, err = u.layer.Stat(name)
53
return cacheHit, lfi, nil
55
if lfi.ModTime().Add(u.cacheTime).Before(time.Now()) {
56
bfi, err = u.base.Stat(name)
58
return cacheLocal, lfi, nil
60
if bfi.ModTime().After(lfi.ModTime()) {
61
return cacheStale, bfi, nil
64
return cacheHit, lfi, nil
67
if err == syscall.ENOENT || os.IsNotExist(err) {
68
return cacheMiss, nil, nil
71
return cacheMiss, nil, err
74
func (u *CacheOnReadFs) copyToLayer(name string) error {
75
return copyToLayer(u.base, u.layer, name)
78
func (u *CacheOnReadFs) copyFileToLayer(name string, flag int, perm os.FileMode) error {
79
return copyFileToLayer(u.base, u.layer, name, flag, perm)
82
func (u *CacheOnReadFs) Chtimes(name string, atime, mtime time.Time) error {
83
st, _, err := u.cacheStatus(name)
90
err = u.base.Chtimes(name, atime, mtime)
91
case cacheStale, cacheMiss:
92
if err := u.copyToLayer(name); err != nil {
95
err = u.base.Chtimes(name, atime, mtime)
100
return u.layer.Chtimes(name, atime, mtime)
103
func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error {
104
st, _, err := u.cacheStatus(name)
111
err = u.base.Chmod(name, mode)
112
case cacheStale, cacheMiss:
113
if err := u.copyToLayer(name); err != nil {
116
err = u.base.Chmod(name, mode)
121
return u.layer.Chmod(name, mode)
124
func (u *CacheOnReadFs) Chown(name string, uid, gid int) error {
125
st, _, err := u.cacheStatus(name)
132
err = u.base.Chown(name, uid, gid)
133
case cacheStale, cacheMiss:
134
if err := u.copyToLayer(name); err != nil {
137
err = u.base.Chown(name, uid, gid)
142
return u.layer.Chown(name, uid, gid)
145
func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) {
146
st, fi, err := u.cacheStatus(name)
152
return u.base.Stat(name)
158
func (u *CacheOnReadFs) Rename(oldname, newname string) error {
159
st, _, err := u.cacheStatus(oldname)
166
err = u.base.Rename(oldname, newname)
167
case cacheStale, cacheMiss:
168
if err := u.copyToLayer(oldname); err != nil {
171
err = u.base.Rename(oldname, newname)
176
return u.layer.Rename(oldname, newname)
179
func (u *CacheOnReadFs) Remove(name string) error {
180
st, _, err := u.cacheStatus(name)
186
case cacheHit, cacheStale, cacheMiss:
187
err = u.base.Remove(name)
192
return u.layer.Remove(name)
195
func (u *CacheOnReadFs) RemoveAll(name string) error {
196
st, _, err := u.cacheStatus(name)
202
case cacheHit, cacheStale, cacheMiss:
203
err = u.base.RemoveAll(name)
208
return u.layer.RemoveAll(name)
211
func (u *CacheOnReadFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
212
st, _, err := u.cacheStatus(name)
217
case cacheLocal, cacheHit:
219
if err := u.copyFileToLayer(name, flag, perm); err != nil {
223
if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
224
bfi, err := u.base.OpenFile(name, flag, perm)
228
lfi, err := u.layer.OpenFile(name, flag, perm)
233
return &UnionFile{Base: bfi, Layer: lfi}, nil
235
return u.layer.OpenFile(name, flag, perm)
238
func (u *CacheOnReadFs) Open(name string) (File, error) {
239
st, fi, err := u.cacheStatus(name)
246
return u.layer.Open(name)
249
bfi, err := u.base.Stat(name)
254
return u.base.Open(name)
256
if err := u.copyToLayer(name); err != nil {
259
return u.layer.Open(name)
263
if err := u.copyToLayer(name); err != nil {
266
return u.layer.Open(name)
270
return u.layer.Open(name)
274
bfile, _ := u.base.Open(name)
275
lfile, err := u.layer.Open(name)
276
if err != nil && bfile == nil {
279
return &UnionFile{Base: bfile, Layer: lfile}, nil
282
func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error {
283
err := u.base.Mkdir(name, perm)
287
return u.layer.MkdirAll(name, perm)
290
func (u *CacheOnReadFs) Name() string {
291
return "CacheOnReadFs"
294
func (u *CacheOnReadFs) MkdirAll(name string, perm os.FileMode) error {
295
err := u.base.MkdirAll(name, perm)
299
return u.layer.MkdirAll(name, perm)
302
func (u *CacheOnReadFs) Create(name string) (File, error) {
303
bfh, err := u.base.Create(name)
307
lfh, err := u.layer.Create(name)
314
return &UnionFile{Base: bfh, Layer: lfh}, nil