Skip to content

Commit

Permalink
keep correct mtimes
Browse files Browse the repository at this point in the history
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
  • Loading branch information
butonic committed Nov 18, 2022
1 parent 786d0b3 commit 4ad9016
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 34 deletions.
6 changes: 2 additions & 4 deletions pkg/storage/utils/decomposedfs/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ func (fs *Decomposedfs) SetArbitraryMetadata(ctx context.Context, ref *provider.
if md.Metadata != nil {
if val, ok := md.Metadata["mtime"]; ok {
delete(md.Metadata, "mtime")
err := n.SetMtime(ctx, val)
if err != nil {
if err := n.SetMtimeString(val); err != nil {
errs = append(errs, errors.Wrap(err, "could not set mtime"))
}
}
Expand All @@ -85,8 +84,7 @@ func (fs *Decomposedfs) SetArbitraryMetadata(ctx context.Context, ref *provider.
// TODO unset when folder is updated or add timestamp to etag?
if val, ok := md.Metadata["etag"]; ok {
delete(md.Metadata, "etag")
err := n.SetEtag(ctx, val)
if err != nil {
if err := n.SetEtag(ctx, val); err != nil {
errs = append(errs, errors.Wrap(err, "could not set etag"))
}
}
Expand Down
31 changes: 13 additions & 18 deletions pkg/storage/utils/decomposedfs/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,25 +495,20 @@ func calculateEtag(nodeID string, tmTime time.Time) (string, error) {
return fmt.Sprintf(`"%x"`, h.Sum(nil)), nil
}

// SetMtime sets the mtime and atime of a node
func (n *Node) SetMtime(ctx context.Context, mtime string) error {
sublog := appctx.GetLogger(ctx).With().Interface("node", n).Logger()
if mt, err := parseMTime(mtime); err == nil {
nodePath := n.InternalPath()
// updating mtime also updates atime
if err := os.Chtimes(nodePath, mt, mt); err != nil {
sublog.Error().Err(err).
Time("mtime", mt).
Msg("could not set mtime")
return errors.Wrap(err, "could not set mtime")
}
} else {
sublog.Error().Err(err).
Str("mtime", mtime).
Msg("could not parse mtime")
return errors.Wrap(err, "could not parse mtime")
// SetMtimeString sets the mtime and atime of a node to the unixtime parsed from the given string
func (n *Node) SetMtimeString(mtime string) error {
mt, err := parseMTime(mtime)
if err != nil {
return err
}
return nil
return n.SetMtime(mt)
}

// SetMtime sets the mtime and atime of a node
func (n *Node) SetMtime(mtime time.Time) error {
nodePath := n.InternalPath()
// updating mtime also updates atime
return os.Chtimes(nodePath, mtime, mtime)
}

// SetEtag sets the temporary etag of a node if it differs from the current etag
Expand Down
48 changes: 36 additions & 12 deletions pkg/storage/utils/decomposedfs/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) {
defer releaseLock()

// check if match header again as safeguard
var oldMtime time.Time
versionsPath := ""
if fi, err = os.Stat(targetPath); err == nil {
// When the if-match header was set we need to check if the
Expand All @@ -763,6 +764,9 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) {
// FIXME move versioning to blobs ... no need to copy all the metadata! well ... it does if we want to version metadata...
// versions are stored alongside the actual file, so a rename can be efficient and does not cross storage / partition boundaries
versionsPath = upload.fs.lu.InternalPath(spaceID, n.ID+node.RevisionIDDelimiter+fi.ModTime().UTC().Format(time.RFC3339Nano))

// remember mtime of existing file so we can apply it to the version
oldMtime = fi.ModTime()
}

// read metadata
Expand All @@ -780,16 +784,24 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) {

// create version node with current metadata

var newMtime time.Time
// if file already exists
if versionsPath != "" {
// touch version node
file, err := os.Create(versionsPath)
if err != nil {
discardBlob()
sublog.Err(err).Str("version", versionsPath).Msg("could not create version")
return errtypes.InternalError("could not create version")
sublog.Err(err).Str("version", versionsPath).Msg("could not create version node")
return errtypes.InternalError("could not create version node")
}
file.Close()
fi, err := file.Stat()
if err != nil {
discardBlob()
sublog.Err(err).Str("version", versionsPath).Msg("could not stat version node")
return errtypes.InternalError("could not stat version node")
}
newMtime = fi.ModTime()

// copy grant and arbitrary metadata to version node
// FIXME ... now restoring an older revision might bring back a grant that was removed!
Expand All @@ -809,21 +821,27 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) {
return errtypes.InternalError("failed to copy xattrs to version node")
}

// keep mtime from previous version
if err := os.Chtimes(versionsPath, oldMtime, oldMtime); err != nil {
discardBlob()
sublog.Err(err).Str("version", versionsPath).Msg("failed to change mtime of version node")
return errtypes.InternalError("failed to change mtime of version node")
}

// we MUST bypass any cache here as we have to calculate the size diff atomically
oldSize, err = node.ReadBlobSizeAttr(targetPath)
if err != nil {
discardBlob()
sublog.Err(err).Str("version", versionsPath).Msg("failed to copy xattrs to version node")
return errtypes.InternalError("failed to copy xattrs to version node")
sublog.Err(err).Str("version", versionsPath).Msg("failed to read old blobsize")
return errtypes.InternalError("failed to read old blobsize")
}

} else {
// touch metadata node
file, err := os.Create(targetPath)
if err != nil {
discardBlob()
sublog.Err(err).Msg("could not create metadata node")
return errtypes.InternalError("could not create version")
sublog.Err(err).Msg("could not create node")
return errtypes.InternalError("could not create node")
}
file.Close()

Expand All @@ -840,11 +858,17 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) {
return errors.Wrap(err, "Decomposedfs: could not write metadata")
}

// use set arbitrary metadata?
if upload.info.MetaData["mtime"] != "" {
err := n.SetMtime(ctx, upload.info.MetaData["mtime"])
if err != nil {
sublog.Err(err).Interface("info", upload.info).Msg("Decomposedfs: could not set mtime metadata")
// update mtime
switch {
case upload.info.MetaData["mtime"] != "":
if err := n.SetMtimeString(upload.info.MetaData["mtime"]); err != nil {
sublog.Err(err).Interface("info", upload.info).Msg("Decomposedfs: could not apply mtime from metadata")
return err
}
case oldMtime != time.Time{}:
// we are creating a version
if err := n.SetMtime(oldMtime); err != nil {
sublog.Err(err).Interface("info", upload.info).Msg("Decomposedfs: could not change mtime of node")
return err
}
}
Expand Down

0 comments on commit 4ad9016

Please sign in to comment.