mirror of
https://git.sr.ht/~sircmpwn/tokidoki
synced 2025-12-12 06:07:22 +01:00
storage: streamline ETag calculation
This commit introduces some helpers so that ETags can be calculated at the same time that files get read or written. Besides looking nicer, it should also help reduce lock contention around file access, as files do not need to be opened twice anymore.
This commit is contained in:
parent
fe0a0d0d00
commit
665b206709
4 changed files with 89 additions and 54 deletions
|
|
@ -68,21 +68,21 @@ func vcardPropFilter(card vcard.Card, props []string) vcard.Card {
|
|||
return result
|
||||
}
|
||||
|
||||
func vcardFromFile(path string, propFilter []string) (vcard.Card, error) {
|
||||
|
||||
func vcardAndEtagFromFile(path string, propFilter []string) (vcard.Card, string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
dec := vcard.NewDecoder(f)
|
||||
src := NewETagReader(f)
|
||||
dec := vcard.NewDecoder(src)
|
||||
card, err := dec.Decode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return vcardPropFilter(card, propFilter), nil
|
||||
return vcardPropFilter(card, propFilter), src.ETag(), nil
|
||||
}
|
||||
|
||||
func (b *filesystemBackend) loadAllAddressObjects(ctx context.Context, urlPath string, propFilter []string) ([]carddav.AddressObject, error) {
|
||||
|
|
@ -104,16 +104,10 @@ func (b *filesystemBackend) loadAllAddressObjects(ctx context.Context, urlPath s
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO use single file read for data & etag
|
||||
b.RLock(filename)
|
||||
defer b.RUnlock(filename)
|
||||
|
||||
card, err := vcardFromFile(filename, propFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etag, err := etagForFile(filename)
|
||||
card, etag, err := vcardAndEtagFromFile(filename, propFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -127,6 +121,7 @@ func (b *filesystemBackend) loadAllAddressObjects(ctx context.Context, urlPath s
|
|||
ETag: etag,
|
||||
Card: card,
|
||||
}
|
||||
log.Debug().Str("path", obj.Path).Str("etag", etag).Int64("size", info.Size()).Msg("address object loaded")
|
||||
result = append(result, obj)
|
||||
return nil
|
||||
})
|
||||
|
|
@ -335,17 +330,12 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, objPath string
|
|||
propFilter = req.Props
|
||||
}
|
||||
|
||||
card, err := vcardFromFile(localPath, propFilter)
|
||||
card, etag, err := vcardAndEtagFromFile(localPath, propFilter)
|
||||
if err != nil {
|
||||
log.Debug().Str("path", localPath).Err(err).Msg("error reading calendar")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
etag, err := etagForFile(localPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj := carddav.AddressObject{
|
||||
Path: objPath,
|
||||
ModTime: info.ModTime(),
|
||||
|
|
@ -353,6 +343,7 @@ func (b *filesystemBackend) GetAddressObject(ctx context.Context, objPath string
|
|||
ETag: etag,
|
||||
Card: card,
|
||||
}
|
||||
log.Debug().Str("path", objPath).Str("etag", etag).Int64("size", info.Size()).Msg("returning address object")
|
||||
return &obj, nil
|
||||
}
|
||||
|
||||
|
|
@ -435,15 +426,12 @@ func (b *filesystemBackend) PutAddressObject(ctx context.Context, objPath string
|
|||
}
|
||||
defer f.Close()
|
||||
|
||||
enc := vcard.NewEncoder(f)
|
||||
out := NewETagWriter(f)
|
||||
enc := vcard.NewEncoder(out)
|
||||
if err := enc.Encode(card); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
etag, err := etagForFile(localPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -453,9 +441,10 @@ func (b *filesystemBackend) PutAddressObject(ctx context.Context, objPath string
|
|||
Path: objPath,
|
||||
ModTime: info.ModTime(),
|
||||
ContentLength: info.Size(),
|
||||
ETag: etag,
|
||||
ETag: out.ETag(),
|
||||
Card: card,
|
||||
}
|
||||
log.Debug().Str("path", r.Path).Str("etag", r.ETag).Int64("size", info.Size()).Msg("address object updated")
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue