Merge pull request #3477 from creack/fix_tar_leaks
Make CopyFileWithTar use a pipe instead of a buffer. Save more than 1Gb of ram for a 500Mb file.
This commit is contained in:
commit
fca83b4cfb
1 changed files with 34 additions and 21 deletions
|
@ -3,8 +3,8 @@ package archive
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
|
||||||
"compress/bzip2"
|
"compress/bzip2"
|
||||||
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
|
@ -299,7 +299,7 @@ func CopyWithTar(src, dst string) error {
|
||||||
//
|
//
|
||||||
// If `dst` ends with a trailing slash '/', the final destination path
|
// If `dst` ends with a trailing slash '/', the final destination path
|
||||||
// will be `dst/base(src)`.
|
// will be `dst/base(src)`.
|
||||||
func CopyFileWithTar(src, dst string) error {
|
func CopyFileWithTar(src, dst string) (err error) {
|
||||||
utils.Debugf("CopyFileWithTar(%s, %s)", src, dst)
|
utils.Debugf("CopyFileWithTar(%s, %s)", src, dst)
|
||||||
srcSt, err := os.Stat(src)
|
srcSt, err := os.Stat(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -316,25 +316,38 @@ func CopyFileWithTar(src, dst string) error {
|
||||||
if err := os.MkdirAll(filepath.Dir(dst), 0700); err != nil && !os.IsExist(err) {
|
if err := os.MkdirAll(filepath.Dir(dst), 0700); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
tw := tar.NewWriter(buf)
|
r, w := io.Pipe()
|
||||||
hdr, err := tar.FileInfoHeader(srcSt, "")
|
errC := utils.Go(func() error {
|
||||||
if err != nil {
|
defer w.Close()
|
||||||
return err
|
|
||||||
}
|
srcF, err := os.Open(src)
|
||||||
hdr.Name = filepath.Base(dst)
|
if err != nil {
|
||||||
if err := tw.WriteHeader(hdr); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
defer srcF.Close()
|
||||||
srcF, err := os.Open(src)
|
|
||||||
if err != nil {
|
tw := tar.NewWriter(w)
|
||||||
return err
|
hdr, err := tar.FileInfoHeader(srcSt, "")
|
||||||
}
|
if err != nil {
|
||||||
if _, err := io.Copy(tw, srcF); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
hdr.Name = filepath.Base(dst)
|
||||||
tw.Close()
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
return Untar(buf, filepath.Dir(dst), nil)
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(tw, srcF); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tw.Close()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
defer func() {
|
||||||
|
if er := <-errC; err != nil {
|
||||||
|
err = er
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return Untar(r, filepath.Dir(dst), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdStream executes a command, and returns its stdout as a stream.
|
// CmdStream executes a command, and returns its stdout as a stream.
|
||||||
|
|
Loading…
Reference in a new issue