mirror of
https://github.com/rclone/rclone.git
synced 2024-12-23 15:38:57 +01:00
swift: reserve segments of dynamic large object when delete objects in container what was enabled versioning.
add code handle move object when moving the object is contained by the container what was enabled versioning with "X-History-Location".
This commit is contained in:
parent
f5443ac939
commit
2fe8285f89
@ -530,10 +530,10 @@ type listFn func(remote string, object *swift.Object, isDirectory bool) error
|
|||||||
//
|
//
|
||||||
// Set recurse to read sub directories
|
// Set recurse to read sub directories
|
||||||
func (f *Fs) listContainerRoot(container, directory, prefix string, addContainer bool, recurse bool, fn listFn) error {
|
func (f *Fs) listContainerRoot(container, directory, prefix string, addContainer bool, recurse bool, fn listFn) error {
|
||||||
if prefix != "" {
|
if prefix != "" && !strings.HasSuffix(prefix, "/") {
|
||||||
prefix += "/"
|
prefix += "/"
|
||||||
}
|
}
|
||||||
if directory != "" {
|
if directory != "" && !strings.HasSuffix(directory, "/") {
|
||||||
directory += "/"
|
directory += "/"
|
||||||
}
|
}
|
||||||
// Options for ObjectsWalk
|
// Options for ObjectsWalk
|
||||||
@ -952,6 +952,18 @@ func (o *Object) isStaticLargeObject() (bool, error) {
|
|||||||
return o.hasHeader("X-Static-Large-Object")
|
return o.hasHeader("X-Static-Large-Object")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Object) isInContainerVersioning() (bool, error) {
|
||||||
|
_, headers, err := o.fs.c.Container(o.fs.root)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
xHistoryLocation := headers["X-History-Location"]
|
||||||
|
if len(xHistoryLocation) > 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Size returns the size of an object in bytes
|
// Size returns the size of an object in bytes
|
||||||
func (o *Object) Size() int64 {
|
func (o *Object) Size() int64 {
|
||||||
return o.size
|
return o.size
|
||||||
@ -1083,9 +1095,8 @@ func min(x, y int64) int64 {
|
|||||||
//
|
//
|
||||||
// if except is passed in then segments with that prefix won't be deleted
|
// if except is passed in then segments with that prefix won't be deleted
|
||||||
func (o *Object) removeSegments(except string) error {
|
func (o *Object) removeSegments(except string) error {
|
||||||
container, containerPath := o.split()
|
segmentsContainer, prefix, err := o.getSegmentsDlo()
|
||||||
segmentsContainer := container + "_segments"
|
err = o.fs.listContainerRoot(segmentsContainer, prefix, "", false, true, func(remote string, object *swift.Object, isDirectory bool) error {
|
||||||
err := o.fs.listContainerRoot(segmentsContainer, containerPath, "", false, true, func(remote string, object *swift.Object, isDirectory bool) error {
|
|
||||||
if isDirectory {
|
if isDirectory {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1114,6 +1125,19 @@ func (o *Object) removeSegments(except string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Object) getSegmentsDlo() (segmentsContainer string, prefix string, err error) {
|
||||||
|
if err = o.readMetaData(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dirManifest := o.headers["X-Object-Manifest"]
|
||||||
|
delimiter := strings.Index(dirManifest, "/")
|
||||||
|
if len(dirManifest) == 0 || delimiter < 0 {
|
||||||
|
err = errors.New("Missing or wrong structure of manifest of Dynamic large object")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return dirManifest[:delimiter], dirManifest[delimiter+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
// urlEncode encodes a string so that it is a valid URL
|
// urlEncode encodes a string so that it is a valid URL
|
||||||
//
|
//
|
||||||
// We don't use any of Go's standard methods as we need `/` not
|
// We don't use any of Go's standard methods as we need `/` not
|
||||||
@ -1300,12 +1324,9 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove an object
|
// Remove an object
|
||||||
func (o *Object) Remove(ctx context.Context) error {
|
func (o *Object) Remove(ctx context.Context) (err error) {
|
||||||
container, containerPath := o.split()
|
container, containerPath := o.split()
|
||||||
isDynamicLargeObject, err := o.isDynamicLargeObject()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Remove file/manifest first
|
// Remove file/manifest first
|
||||||
err = o.fs.pacer.Call(func() (bool, error) {
|
err = o.fs.pacer.Call(func() (bool, error) {
|
||||||
err = o.fs.c.ObjectDelete(container, containerPath)
|
err = o.fs.c.ObjectDelete(container, containerPath)
|
||||||
@ -1314,13 +1335,23 @@ func (o *Object) Remove(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
isDynamicLargeObject, err := o.isDynamicLargeObject()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// ...then segments if required
|
// ...then segments if required
|
||||||
if isDynamicLargeObject {
|
if isDynamicLargeObject {
|
||||||
|
isInContainerVersioning, err := o.isInContainerVersioning()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !isInContainerVersioning {
|
||||||
err = o.removeSegments("")
|
err = o.removeSegments("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user