jottacloud: refactor SetModTime function
Now using the utility function for deduplication that was newly implemented to fix an issue with server-side copy. This function uses the original, and generic, "jfs" api (and its "cphash" feature), instead of the newer "allocate" api dedicated for uploads. Both apis support similar deduplication functionaly that we rely on for the SetModTime operation. One advantage of using the jfs variant is that the allocate api is specialized for uploads, an initial request performs modtime-only changes and deduplication if possible but if not possible it creates an incomplete file revision and returns a special url to be used with a following request to upload missing content. In the SetModTime function we only sent the first request, using metadata from existing remote file but different timestamps, which lead to a modtime-only change. If, for some reason, this should fail it would leave the incomplete revision behind. Probably not a problem, but the jfs implementation used with this commit is simpler and a more "standalone" request which either succeeds or fails without expecting additional requests.
This commit is contained in:
parent
2b67ad17aa
commit
cc8dde402f
1 changed files with 9 additions and 30 deletions
|
@ -1599,40 +1599,19 @@ func (o *Object) SetModTime(ctx context.Context, modTime time.Time) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// prepare allocate request with existing metadata but changed timestamps
|
||||
var resp *http.Response
|
||||
var options []fs.OpenOption
|
||||
opts := rest.Opts{
|
||||
Method: "POST",
|
||||
Path: "files/v1/allocate",
|
||||
Options: options,
|
||||
ExtraHeaders: make(map[string]string),
|
||||
}
|
||||
fileDate := api.Time(modTime).APIString()
|
||||
var request = api.AllocateFileRequest{
|
||||
Bytes: o.size,
|
||||
Created: fileDate,
|
||||
Modified: fileDate,
|
||||
Md5: o.md5,
|
||||
Path: path.Join(o.fs.opt.Mountpoint, o.fs.opt.Enc.FromStandardPath(path.Join(o.fs.root, o.remote))),
|
||||
}
|
||||
|
||||
// send it
|
||||
var response api.AllocateFileResponse
|
||||
err = o.fs.pacer.Call(func() (bool, error) {
|
||||
resp, err = o.fs.apiSrv.CallJSON(ctx, &opts, &request, &response)
|
||||
return shouldRetry(ctx, resp, err)
|
||||
})
|
||||
// request check/update with existing metadata and new modtime
|
||||
// (note that if size/md5 does not match, the file content will
|
||||
// also be modified if deduplication is possible, i.e. it is
|
||||
// important to use correct/latest values)
|
||||
_, err = o.fs.createOrUpdate(ctx, o.remote, modTime, o.size, o.md5)
|
||||
if err != nil {
|
||||
if err == fs.ErrorObjectNotFound {
|
||||
// file was modified (size/md5 changed) between readMetaData and createOrUpdate?
|
||||
return errors.New("metadata did not match")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// check response
|
||||
if response.State != "COMPLETED" {
|
||||
// could be the file was modified (size/md5 changed) between readMetaData and the allocate request
|
||||
return errors.New("metadata did not match")
|
||||
}
|
||||
|
||||
// update local metadata
|
||||
o.modTime = modTime
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue