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:
Nguyễn Hữu Luân 2019-11-18 23:26:10 +07:00 committed by Nick Craig-Wood
parent f5443ac939
commit 2fe8285f89

View File

@ -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
} }