Browse code

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 authored on 2015/07/21 10:32:14
Showing 3 changed files
... ...
@@ -28,6 +28,8 @@ import (
28 28
 	"github.com/docker/docker/pkg/system"
29 29
 	"github.com/docker/docker/pkg/truncindex"
30 30
 	"github.com/docker/docker/runconfig"
31
+	"github.com/vbatts/tar-split/tar/asm"
32
+	"github.com/vbatts/tar-split/tar/storage"
31 33
 )
32 34
 
33 35
 // The type is used to protect pulling or building related image
... ...
@@ -530,3 +532,80 @@ func (graph *Graph) RawJSON(id string) ([]byte, error) {
530 530
 func jsonPath(root string) string {
531 531
 	return filepath.Join(root, jsonFileName)
532 532
 }
533
+
534
+func (graph *Graph) disassembleAndApplyTarLayer(img *image.Image, layerData archive.ArchiveReader, root string) error {
535
+	// this is saving the tar-split metadata
536
+	mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
537
+	if err != nil {
538
+		return err
539
+	}
540
+	mfz := gzip.NewWriter(mf)
541
+	metaPacker := storage.NewJSONPacker(mfz)
542
+	defer mf.Close()
543
+	defer mfz.Close()
544
+
545
+	inflatedLayerData, err := archive.DecompressStream(layerData)
546
+	if err != nil {
547
+		return err
548
+	}
549
+
550
+	// we're passing nil here for the file putter, because the ApplyDiff will
551
+	// handle the extraction of the archive
552
+	rdr, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
553
+	if err != nil {
554
+		return err
555
+	}
556
+
557
+	if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(rdr)); err != nil {
558
+		return err
559
+	}
560
+
561
+	return nil
562
+}
563
+
564
+func (graph *Graph) assembleTarLayer(img *image.Image) (archive.Archive, error) {
565
+	root := graph.imageRoot(img.ID)
566
+	mFileName := filepath.Join(root, tarDataFileName)
567
+	mf, err := os.Open(mFileName)
568
+	if err != nil {
569
+		if !os.IsNotExist(err) {
570
+			logrus.Errorf("failed to open %q: %s", mFileName, err)
571
+		}
572
+		return nil, err
573
+	}
574
+	pR, pW := io.Pipe()
575
+	// this will need to be in a goroutine, as we are returning the stream of a
576
+	// tar archive, but can not close the metadata reader early (when this
577
+	// function returns)...
578
+	go func() {
579
+		defer mf.Close()
580
+		// let's reassemble!
581
+		logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
582
+		mfz, err := gzip.NewReader(mf)
583
+		if err != nil {
584
+			pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
585
+			return
586
+		}
587
+		defer mfz.Close()
588
+
589
+		// get our relative path to the container
590
+		fsLayer, err := graph.driver.Get(img.ID, "")
591
+		if err != nil {
592
+			pW.CloseWithError(err)
593
+			return
594
+		}
595
+		defer graph.driver.Put(img.ID)
596
+
597
+		metaUnpacker := storage.NewJSONUnpacker(mfz)
598
+		fileGetter := storage.NewPathFileGetter(fsLayer)
599
+		logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
600
+		ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
601
+		defer ots.Close()
602
+		if _, err := io.Copy(pW, ots); err != nil {
603
+			pW.CloseWithError(err)
604
+			return
605
+		}
606
+		pW.Close()
607
+	}()
608
+	return pR, nil
609
+}
... ...
@@ -3,10 +3,8 @@
3 3
 package graph
4 4
 
5 5
 import (
6
-	"compress/gzip"
7 6
 	"encoding/json"
8 7
 	"fmt"
9
-	"io"
10 8
 	"os"
11 9
 	"path/filepath"
12 10
 	"strings"
... ...
@@ -16,8 +14,6 @@ import (
16 16
 	"github.com/docker/docker/image"
17 17
 	"github.com/docker/docker/pkg/archive"
18 18
 	"github.com/docker/docker/pkg/system"
19
-	"github.com/vbatts/tar-split/tar/asm"
20
-	"github.com/vbatts/tar-split/tar/storage"
21 19
 )
22 20
 
23 21
 // setupInitLayer populates a directory with mountpoints suitable
... ...
@@ -95,29 +91,7 @@ func (graph *Graph) restoreBaseImages() ([]string, error) {
95 95
 func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
96 96
 	// Store the layer. If layerData is not nil, unpack it into the new layer
97 97
 	if layerData != nil {
98
-		// this is saving the tar-split metadata
99
-		mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
100
-		if err != nil {
101
-			return err
102
-		}
103
-		defer mf.Close()
104
-		mfz := gzip.NewWriter(mf)
105
-		defer mfz.Close()
106
-		metaPacker := storage.NewJSONPacker(mfz)
107
-
108
-		inflatedLayerData, err := archive.DecompressStream(layerData)
109
-		if err != nil {
110
-			return err
111
-		}
112
-
113
-		// we're passing nil here for the file putter, because the ApplyDiff will
114
-		// handle the extraction of the archive
115
-		its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
116
-		if err != nil {
117
-			return err
118
-		}
119
-
120
-		if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
98
+		if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
121 99
 			return err
122 100
 		}
123 101
 	}
... ...
@@ -138,49 +112,10 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
138 138
 
139 139
 // TarLayer returns a tar archive of the image's filesystem layer.
140 140
 func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
141
-	root := graph.imageRoot(img.ID)
142
-	mFileName := filepath.Join(root, tarDataFileName)
143
-	mf, err := os.Open(mFileName)
141
+	rdr, err := graph.assembleTarLayer(img)
144 142
 	if err != nil {
145
-		if !os.IsNotExist(err) {
146
-			logrus.Errorf("failed to open %q: %s", mFileName, err)
147
-		}
148 143
 		logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
149 144
 		return graph.driver.Diff(img.ID, img.Parent)
150 145
 	}
151
-	pR, pW := io.Pipe()
152
-	// this will need to be in a goroutine, as we are returning the stream of a
153
-	// tar archive, but can not close the metadata reader early (when this
154
-	// function returns)...
155
-	go func() {
156
-		defer mf.Close()
157
-		// let's reassemble!
158
-		logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
159
-		mfz, err := gzip.NewReader(mf)
160
-		if err != nil {
161
-			pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
162
-			return
163
-		}
164
-		defer mfz.Close()
165
-
166
-		// get our relative path to the container
167
-		fsLayer, err := graph.driver.Get(img.ID, "")
168
-		if err != nil {
169
-			pW.CloseWithError(err)
170
-			return
171
-		}
172
-		defer graph.driver.Put(img.ID)
173
-
174
-		metaUnpacker := storage.NewJSONUnpacker(mfz)
175
-		fileGetter := storage.NewPathFileGetter(fsLayer)
176
-		logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
177
-		ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
178
-		defer ots.Close()
179
-		if _, err := io.Copy(pW, ots); err != nil {
180
-			pW.CloseWithError(err)
181
-			return
182
-		}
183
-		pW.Close()
184
-	}()
185
-	return pR, nil
146
+	return rdr, nil
186 147
 }
... ...
@@ -3,19 +3,14 @@
3 3
 package graph
4 4
 
5 5
 import (
6
-	"compress/gzip"
7 6
 	"encoding/json"
8 7
 	"fmt"
9
-	"io"
10 8
 	"os"
11
-	"path/filepath"
12 9
 
13 10
 	"github.com/Sirupsen/logrus"
14 11
 	"github.com/docker/docker/daemon/graphdriver/windows"
15 12
 	"github.com/docker/docker/image"
16 13
 	"github.com/docker/docker/pkg/archive"
17
-	"github.com/vbatts/tar-split/tar/asm"
18
-	"github.com/vbatts/tar-split/tar/storage"
19 14
 )
20 15
 
21 16
 // setupInitLayer populates a directory with mountpoints suitable
... ...
@@ -120,29 +115,7 @@ func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader
120 120
 
121 121
 		// Store the layer. If layerData is not nil, unpack it into the new layer
122 122
 		if layerData != nil {
123
-			// this is saving the tar-split metadata
124
-			mf, err := os.OpenFile(filepath.Join(root, tarDataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
125
-			if err != nil {
126
-				return err
127
-			}
128
-			defer mf.Close()
129
-			mfz := gzip.NewWriter(mf)
130
-			defer mfz.Close()
131
-			metaPacker := storage.NewJSONPacker(mfz)
132
-
133
-			inflatedLayerData, err := archive.DecompressStream(layerData)
134
-			if err != nil {
135
-				return err
136
-			}
137
-
138
-			// we're passing nil here for the file putter, because the ApplyDiff will
139
-			// handle the extraction of the archive
140
-			its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
141
-			if err != nil {
142
-				return err
143
-			}
144
-
145
-			if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
123
+			if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
146 124
 				return err
147 125
 			}
148 126
 		}
... ...
@@ -183,50 +156,11 @@ func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error)
183 183
 		// We keep this functionality here so that we can still work with the VFS
184 184
 		// driver during development. VFS is not supported (and just will not work)
185 185
 		// for Windows containers.
186
-		root := graph.imageRoot(img.ID)
187
-		mFileName := filepath.Join(root, tarDataFileName)
188
-		mf, err := os.Open(mFileName)
186
+		rdr, err := graph.assembleTarLayer(img)
189 187
 		if err != nil {
190
-			if !os.IsNotExist(err) {
191
-				logrus.Errorf("failed to open %q: %s", mFileName, err)
192
-			}
193 188
 			logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
194 189
 			return graph.driver.Diff(img.ID, img.Parent)
195 190
 		}
196
-		pR, pW := io.Pipe()
197
-		// this will need to be in a goroutine, as we are returning the stream of a
198
-		// tar archive, but can not close the metadata reader early (when this
199
-		// function returns)...
200
-		go func() {
201
-			defer mf.Close()
202
-			// let's reassemble!
203
-			logrus.Debugf("[graph] TarLayer with reassembly: %s", img.ID)
204
-			mfz, err := gzip.NewReader(mf)
205
-			if err != nil {
206
-				pW.CloseWithError(fmt.Errorf("[graph] error with %s:  %s", mFileName, err))
207
-				return
208
-			}
209
-			defer mfz.Close()
210
-
211
-			// get our relative path to the container
212
-			fsLayer, err := graph.driver.Get(img.ID, "")
213
-			if err != nil {
214
-				pW.CloseWithError(err)
215
-				return
216
-			}
217
-			defer graph.driver.Put(img.ID)
218
-
219
-			metaUnpacker := storage.NewJSONUnpacker(mfz)
220
-			fileGetter := storage.NewPathFileGetter(fsLayer)
221
-			logrus.Debugf("[graph] %s is at %q", img.ID, fsLayer)
222
-			ots := asm.NewOutputTarStream(fileGetter, metaUnpacker)
223
-			defer ots.Close()
224
-			if _, err := io.Copy(pW, ots); err != nil {
225
-				pW.CloseWithError(err)
226
-				return
227
-			}
228
-			pW.Close()
229
-		}()
230
-		return pR, nil
191
+		return rdr, nil
231 192
 	}
232 193
 }