Browse Source

graph: isolate the (dis)assembly logic

with the current duplication of code in the grap.go split-up, this puts
all assembly/disassembly logic into isolated functions

Signed-off-by: Vincent Batts <vbatts@redhat.com>
Vincent Batts 10 năm trước cách đây
mục cha
commit
22347fdb63
3 tập tin đã thay đổi với 85 bổ sung137 xóa
  1. 79 0
      graph/graph.go
  2. 3 68
      graph/graph_unix.go
  3. 3 69
      graph/graph_windows.go

+ 79 - 0
graph/graph.go

@@ -28,6 +28,8 @@ import (
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/truncindex"
 	"github.com/docker/docker/runconfig"
+	"github.com/vbatts/tar-split/tar/asm"
+	"github.com/vbatts/tar-split/tar/storage"
 )
 
 // The type is used to protect pulling or building related image
@@ -530,3 +532,80 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) {
 func jsonPath(root string) string {
 	return filepath.Join(root, jsonFileName)
 }
+
+func (graph *Graph) disassembleAndApplyTarLayer(img *image.Image, layerData archive.ArchiveReader, root string) error {
+	// this is saving the tar-split metadata
+	mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
+	if err != nil {
+		return err
+	}
+	mfz := gzip.NewWriter(mf)
+	metaPacker := storage.NewJSONPacker(mfz)
+	defer mf.Close()
+	defer mfz.Close()
+
+	inflatedLayerData, err := archive.DecompressStream(layerData)
+	if err != nil {
+		return err
+	}
+
+	// we're passing nil here for the file putter, because the ApplyDiff will
+	// handle the extraction of the archive
+	rdr, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
+	if err != nil {
+		return err
+	}
+
+	if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(rdr)); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (graph *Graph) assembleTarLayer(img *image.Image) (archive.Archive, error) {
+	root := graph.imageRoot(img.ID)
+	mFileName := filepath.Join(root, tarDataFileName)
+	mf, err := os.Open(mFileName)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			logrus.Errorf("failed to open %q: %s", mFileName, err)
+		}
+		return nil, err
+	}
+	pR, pW := io.Pipe()
+	// this will need to be in a goroutine, as we are returning the stream of a
+	// tar archive, but can not close the metadata reader early (when this
+	// function returns)...
+	go func() {
+		defer mf.Close()
+		// let's reassemble!
+		logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
+		mfz, err := gzip.NewReader(mf)
+		if err != nil {
+			pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
+			return
+		}
+		defer mfz.Close()
+
+		// get our relative path to the container
+		fsLayer, err := graph.driver.Get(img.ID, "")
+		if err != nil {
+			pW.CloseWithError(err)
+			return
+		}
+		defer graph.driver.Put(img.ID)
+
+		metaUnpacker := storage.NewJSONUnpacker(mfz)
+		fileGetter := storage.NewPathFileGetter(fsLayer)
+		logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
+		ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
+		defer ots.Close()
+		if _, err := io.Copy(pW, ots); err != nil {
+			pW.CloseWithError(err)
+			return
+		}
+		pW.Close()
+	}()
+	return pR, nil
+}

+ 3 - 68
graph/graph_unix.go

@@ -3,10 +3,8 @@
 package graph
 
 import (
-	"compress/gzip"
 	"encoding/json"
 	"fmt"
-	"io"
 	"os"
 	"path/filepath"
 	"strings"
@@ -16,8 +14,6 @@ import (
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/system"
-	"github.com/vbatts/tar-split/tar/asm"
-	"github.com/vbatts/tar-split/tar/storage"
 )
 
 // setupInitLayer populates a directory with mountpoints suitable
@@ -95,29 +91,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
 func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
 	// Store the layer. If layerData is not nil, unpack it into the new layer
 	if layerData != nil {
-		// this is saving the tar-split metadata
-		mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
-		if err != nil {
-			return err
-		}
-		defer mf.Close()
-		mfz := gzip.NewWriter(mf)
-		defer mfz.Close()
-		metaPacker := storage.NewJSONPacker(mfz)
-
-		inflatedLayerData, err := archive.DecompressStream(layerData)
-		if err != nil {
-			return err
-		}
-
-		// we're passing nil here for the file putter, because the ApplyDiff will
-		// handle the extraction of the archive
-		its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
-		if err != nil {
-			return err
-		}
-
-		if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
+		if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
 			return err
 		}
 	}
@@ -138,49 +112,10 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
 
 // TarLayer returns a tar archive of the image's filesystem layer.
 func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
-	root := graph.imageRoot(img.ID)
-	mFileName := filepath.Join(root, tarDataFileName)
-	mf, err := os.Open(mFileName)
+	rdr, err := graph.assembleTarLayer(img)
 	if err != nil {
-		if !os.IsNotExist(err) {
-			logrus.Errorf("failed to open %q: %s", mFileName, err)
-		}
 		logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
 		return graph.driver.Diff(img.ID, img.Parent)
 	}
-	pR, pW := io.Pipe()
-	// this will need to be in a goroutine, as we are returning the stream of a
-	// tar archive, but can not close the metadata reader early (when this
-	// function returns)...
-	go func() {
-		defer mf.Close()
-		// let's reassemble!
-		logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
-		mfz, err := gzip.NewReader(mf)
-		if err != nil {
-			pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
-			return
-		}
-		defer mfz.Close()
-
-		// get our relative path to the container
-		fsLayer, err := graph.driver.Get(img.ID, "")
-		if err != nil {
-			pW.CloseWithError(err)
-			return
-		}
-		defer graph.driver.Put(img.ID)
-
-		metaUnpacker := storage.NewJSONUnpacker(mfz)
-		fileGetter := storage.NewPathFileGetter(fsLayer)
-		logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
-		ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
-		defer ots.Close()
-		if _, err := io.Copy(pW, ots); err != nil {
-			pW.CloseWithError(err)
-			return
-		}
-		pW.Close()
-	}()
-	return pR, nil
+	return rdr, nil
 }

+ 3 - 69
graph/graph_windows.go

@@ -3,19 +3,14 @@
 package graph
 
 import (
-	"compress/gzip"
 	"encoding/json"
 	"fmt"
-	"io"
 	"os"
-	"path/filepath"
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/graphdriver/windows"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/archive"
-	"github.com/vbatts/tar-split/tar/asm"
-	"github.com/vbatts/tar-split/tar/storage"
 )
 
 // setupInitLayer populates a directory with mountpoints suitable
@@ -120,29 +115,7 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
 
 		// Store the layer. If layerData is not nil, unpack it into the new layer
 		if layerData != nil {
-			// this is saving the tar-split metadata
-			mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
-			if err != nil {
-				return err
-			}
-			defer mf.Close()
-			mfz := gzip.NewWriter(mf)
-			defer mfz.Close()
-			metaPacker := storage.NewJSONPacker(mfz)
-
-			inflatedLayerData, err := archive.DecompressStream(layerData)
-			if err != nil {
-				return err
-			}
-
-			// we're passing nil here for the file putter, because the ApplyDiff will
-			// handle the extraction of the archive
-			its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
-			if err != nil {
-				return err
-			}
-
-			if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
+			if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
 				return err
 			}
 		}
@@ -183,50 +156,11 @@ func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error)
 		// We keep this functionality here so that we can still work with the VFS
 		// driver during development. VFS is not supported (and just will not work)
 		// for Windows containers.
-		root := graph.imageRoot(img.ID)
-		mFileName := filepath.Join(root, tarDataFileName)
-		mf, err := os.Open(mFileName)
+		rdr, err := graph.assembleTarLayer(img)
 		if err != nil {
-			if !os.IsNotExist(err) {
-				logrus.Errorf("failed to open %q: %s", mFileName, err)
-			}
 			logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
 			return graph.driver.Diff(img.ID, img.Parent)
 		}
-		pR, pW := io.Pipe()
-		// this will need to be in a goroutine, as we are returning the stream of a
-		// tar archive, but can not close the metadata reader early (when this
-		// function returns)...
-		go func() {
-			defer mf.Close()
-			// let's reassemble!
-			logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
-			mfz, err := gzip.NewReader(mf)
-			if err != nil {
-				pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
-				return
-			}
-			defer mfz.Close()
-
-			// get our relative path to the container
-			fsLayer, err := graph.driver.Get(img.ID, "")
-			if err != nil {
-				pW.CloseWithError(err)
-				return
-			}
-			defer graph.driver.Put(img.ID)
-
-			metaUnpacker := storage.NewJSONUnpacker(mfz)
-			fileGetter := storage.NewPathFileGetter(fsLayer)
-			logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
-			ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
-			defer ots.Close()
-			if _, err := io.Copy(pW, ots); err != nil {
-				pW.CloseWithError(err)
-				return
-			}
-			pW.Close()
-		}()
-		return pR, nil
+		return rdr, nil
 	}
 }