Browse code

utils/tarsum* -> pkg/tarsum

Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)

Erik Hollensbe authored on 2014/07/30 22:42:12
Showing 6 changed files
... ...
@@ -26,6 +26,7 @@ import (
26 26
 	"github.com/docker/docker/pkg/parsers"
27 27
 	"github.com/docker/docker/pkg/symlink"
28 28
 	"github.com/docker/docker/pkg/system"
29
+	"github.com/docker/docker/pkg/tarsum"
29 30
 	"github.com/docker/docker/registry"
30 31
 	"github.com/docker/docker/runconfig"
31 32
 	"github.com/docker/docker/utils"
... ...
@@ -50,7 +51,7 @@ type buildFile struct {
50 50
 	config     *runconfig.Config
51 51
 
52 52
 	contextPath string
53
-	context     *utils.TarSum
53
+	context     *tarsum.TarSum
54 54
 
55 55
 	verbose      bool
56 56
 	utilizeCache bool
... ...
@@ -555,7 +556,7 @@ func (b *buildFile) runContextCommand(args string, allowRemote bool, allowDecomp
555 555
 		if err != nil {
556 556
 			return err
557 557
 		}
558
-		tarSum := &utils.TarSum{Reader: r, DisableCompression: true}
558
+		tarSum := &tarsum.TarSum{Reader: r, DisableCompression: true}
559 559
 		if _, err := io.Copy(ioutil.Discard, tarSum); err != nil {
560 560
 			return err
561 561
 		}
... ...
@@ -777,7 +778,7 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
777 777
 		return "", err
778 778
 	}
779 779
 
780
-	b.context = &utils.TarSum{Reader: decompressedStream, DisableCompression: true}
780
+	b.context = &tarsum.TarSum{Reader: decompressedStream, DisableCompression: true}
781 781
 	if err := archive.Untar(b.context, tmpdirPath, nil); err != nil {
782 782
 		return "", err
783 783
 	}
784 784
new file mode 100644
... ...
@@ -0,0 +1,183 @@
0
+package tarsum
1
+
2
+import (
3
+	"bytes"
4
+	"compress/gzip"
5
+	"crypto/sha256"
6
+	"encoding/hex"
7
+	"hash"
8
+	"io"
9
+	"sort"
10
+	"strconv"
11
+	"strings"
12
+
13
+	"github.com/docker/docker/utils"
14
+	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
15
+)
16
+
17
+type TarSum struct {
18
+	io.Reader
19
+	tarR               *tar.Reader
20
+	tarW               *tar.Writer
21
+	gz                 writeCloseFlusher
22
+	bufTar             *bytes.Buffer
23
+	bufGz              *bytes.Buffer
24
+	h                  hash.Hash
25
+	sums               map[string]string
26
+	currentFile        string
27
+	finished           bool
28
+	first              bool
29
+	DisableCompression bool
30
+}
31
+
32
+type writeCloseFlusher interface {
33
+	io.WriteCloser
34
+	Flush() error
35
+}
36
+
37
+type nopCloseFlusher struct {
38
+	io.Writer
39
+}
40
+
41
+func (n *nopCloseFlusher) Close() error {
42
+	return nil
43
+}
44
+
45
+func (n *nopCloseFlusher) Flush() error {
46
+	return nil
47
+}
48
+
49
+func (ts *TarSum) encodeHeader(h *tar.Header) error {
50
+	for _, elem := range [][2]string{
51
+		{"name", h.Name},
52
+		{"mode", strconv.Itoa(int(h.Mode))},
53
+		{"uid", strconv.Itoa(h.Uid)},
54
+		{"gid", strconv.Itoa(h.Gid)},
55
+		{"size", strconv.Itoa(int(h.Size))},
56
+		{"mtime", strconv.Itoa(int(h.ModTime.UTC().Unix()))},
57
+		{"typeflag", string([]byte{h.Typeflag})},
58
+		{"linkname", h.Linkname},
59
+		{"uname", h.Uname},
60
+		{"gname", h.Gname},
61
+		{"devmajor", strconv.Itoa(int(h.Devmajor))},
62
+		{"devminor", strconv.Itoa(int(h.Devminor))},
63
+		// {"atime", strconv.Itoa(int(h.AccessTime.UTC().Unix()))},
64
+		// {"ctime", strconv.Itoa(int(h.ChangeTime.UTC().Unix()))},
65
+	} {
66
+		if _, err := ts.h.Write([]byte(elem[0] + elem[1])); err != nil {
67
+			return err
68
+		}
69
+	}
70
+	return nil
71
+}
72
+
73
+func (ts *TarSum) Read(buf []byte) (int, error) {
74
+	if ts.gz == nil {
75
+		ts.bufTar = bytes.NewBuffer([]byte{})
76
+		ts.bufGz = bytes.NewBuffer([]byte{})
77
+		ts.tarR = tar.NewReader(ts.Reader)
78
+		ts.tarW = tar.NewWriter(ts.bufTar)
79
+		if !ts.DisableCompression {
80
+			ts.gz = gzip.NewWriter(ts.bufGz)
81
+		} else {
82
+			ts.gz = &nopCloseFlusher{Writer: ts.bufGz}
83
+		}
84
+		ts.h = sha256.New()
85
+		ts.h.Reset()
86
+		ts.first = true
87
+		ts.sums = make(map[string]string)
88
+	}
89
+
90
+	if ts.finished {
91
+		return ts.bufGz.Read(buf)
92
+	}
93
+	buf2 := make([]byte, len(buf), cap(buf))
94
+
95
+	n, err := ts.tarR.Read(buf2)
96
+	if err != nil {
97
+		if err == io.EOF {
98
+			if _, err := ts.h.Write(buf2[:n]); err != nil {
99
+				return 0, err
100
+			}
101
+			if !ts.first {
102
+				ts.sums[ts.currentFile] = hex.EncodeToString(ts.h.Sum(nil))
103
+				ts.h.Reset()
104
+			} else {
105
+				ts.first = false
106
+			}
107
+
108
+			currentHeader, err := ts.tarR.Next()
109
+			if err != nil {
110
+				if err == io.EOF {
111
+					if err := ts.gz.Close(); err != nil {
112
+						return 0, err
113
+					}
114
+					ts.finished = true
115
+					return n, nil
116
+				}
117
+				return n, err
118
+			}
119
+			ts.currentFile = strings.TrimSuffix(strings.TrimPrefix(currentHeader.Name, "./"), "/")
120
+			if err := ts.encodeHeader(currentHeader); err != nil {
121
+				return 0, err
122
+			}
123
+			if err := ts.tarW.WriteHeader(currentHeader); err != nil {
124
+				return 0, err
125
+			}
126
+			if _, err := ts.tarW.Write(buf2[:n]); err != nil {
127
+				return 0, err
128
+			}
129
+			ts.tarW.Flush()
130
+			if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
131
+				return 0, err
132
+			}
133
+			ts.gz.Flush()
134
+
135
+			return ts.bufGz.Read(buf)
136
+		}
137
+		return n, err
138
+	}
139
+
140
+	// Filling the hash buffer
141
+	if _, err = ts.h.Write(buf2[:n]); err != nil {
142
+		return 0, err
143
+	}
144
+
145
+	// Filling the tar writter
146
+	if _, err = ts.tarW.Write(buf2[:n]); err != nil {
147
+		return 0, err
148
+	}
149
+	ts.tarW.Flush()
150
+
151
+	// Filling the gz writter
152
+	if _, err = io.Copy(ts.gz, ts.bufTar); err != nil {
153
+		return 0, err
154
+	}
155
+	ts.gz.Flush()
156
+
157
+	return ts.bufGz.Read(buf)
158
+}
159
+
160
+func (ts *TarSum) Sum(extra []byte) string {
161
+	var sums []string
162
+
163
+	for _, sum := range ts.sums {
164
+		sums = append(sums, sum)
165
+	}
166
+	sort.Strings(sums)
167
+	h := sha256.New()
168
+	if extra != nil {
169
+		h.Write(extra)
170
+	}
171
+	for _, sum := range sums {
172
+		utils.Debugf("-->%s<--", sum)
173
+		h.Write([]byte(sum))
174
+	}
175
+	checksum := "tarsum+sha256:" + hex.EncodeToString(h.Sum(nil))
176
+	utils.Debugf("checksum processed: %s", checksum)
177
+	return checksum
178
+}
179
+
180
+func (ts *TarSum) GetSums() map[string]string {
181
+	return ts.sums
182
+}
0 183
new file mode 100644
... ...
@@ -0,0 +1,225 @@
0
+package tarsum
1
+
2
+import (
3
+	"bytes"
4
+	"crypto/rand"
5
+	"fmt"
6
+	"io"
7
+	"io/ioutil"
8
+	"os"
9
+	"testing"
10
+
11
+	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
12
+)
13
+
14
+type testLayer struct {
15
+	filename string
16
+	options  *sizedOptions
17
+	jsonfile string
18
+	gzip     bool
19
+	tarsum   string
20
+}
21
+
22
+var testLayers = []testLayer{
23
+	{
24
+		filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
25
+		jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
26
+		tarsum:   "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
27
+	{
28
+		filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
29
+		jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
30
+		gzip:     true,
31
+		tarsum:   "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
32
+	{
33
+		filename: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar",
34
+		jsonfile: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json",
35
+		tarsum:   "tarsum+sha256:ac672ee85da9ab7f9667ae3c32841d3e42f33cc52c273c23341dabba1c8b0c8b"},
36
+	{
37
+		options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
38
+		tarsum:  "tarsum+sha256:8bf12d7e67c51ee2e8306cba569398b1b9f419969521a12ffb9d8875e8836738"},
39
+}
40
+
41
+type sizedOptions struct {
42
+	num      int64
43
+	size     int64
44
+	isRand   bool
45
+	realFile bool
46
+}
47
+
48
+// make a tar:
49
+// * num is the number of files the tar should have
50
+// * size is the bytes per file
51
+// * isRand is whether the contents of the files should be a random chunk (otherwise it's all zeros)
52
+// * realFile will write to a TempFile, instead of an in memory buffer
53
+func sizedTar(opts sizedOptions) io.Reader {
54
+	var (
55
+		fh  io.ReadWriter
56
+		err error
57
+	)
58
+	if opts.realFile {
59
+		fh, err = ioutil.TempFile("", "tarsum")
60
+		if err != nil {
61
+			return nil
62
+		}
63
+	} else {
64
+		fh = bytes.NewBuffer([]byte{})
65
+	}
66
+	tarW := tar.NewWriter(fh)
67
+	for i := int64(0); i < opts.num; i++ {
68
+		err := tarW.WriteHeader(&tar.Header{
69
+			Name: fmt.Sprintf("/testdata%d", i),
70
+			Mode: 0755,
71
+			Uid:  0,
72
+			Gid:  0,
73
+			Size: opts.size,
74
+		})
75
+		if err != nil {
76
+			return nil
77
+		}
78
+		var rBuf []byte
79
+		if opts.isRand {
80
+			rBuf = make([]byte, 8)
81
+			_, err = rand.Read(rBuf)
82
+			if err != nil {
83
+				return nil
84
+			}
85
+		} else {
86
+			rBuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
87
+		}
88
+
89
+		for i := int64(0); i < opts.size/int64(8); i++ {
90
+			tarW.Write(rBuf)
91
+		}
92
+	}
93
+	return fh
94
+}
95
+
96
+func TestTarSums(t *testing.T) {
97
+	for _, layer := range testLayers {
98
+		var (
99
+			fh  io.Reader
100
+			err error
101
+		)
102
+		if len(layer.filename) > 0 {
103
+			fh, err = os.Open(layer.filename)
104
+			if err != nil {
105
+				t.Errorf("failed to open %s: %s", layer.filename, err)
106
+				continue
107
+			}
108
+		} else if layer.options != nil {
109
+			fh = sizedTar(*layer.options)
110
+		} else {
111
+			// What else is there to test?
112
+			t.Errorf("what to do with %#v", layer)
113
+			continue
114
+		}
115
+		if file, ok := fh.(*os.File); ok {
116
+			defer file.Close()
117
+		}
118
+
119
+		//                                  double negatives!
120
+		ts := &TarSum{Reader: fh, DisableCompression: !layer.gzip}
121
+		_, err = io.Copy(ioutil.Discard, ts)
122
+		if err != nil {
123
+			t.Errorf("failed to copy from %s: %s", layer.filename, err)
124
+			continue
125
+		}
126
+		var gotSum string
127
+		if len(layer.jsonfile) > 0 {
128
+			jfh, err := os.Open(layer.jsonfile)
129
+			if err != nil {
130
+				t.Errorf("failed to open %s: %s", layer.jsonfile, err)
131
+				continue
132
+			}
133
+			buf, err := ioutil.ReadAll(jfh)
134
+			if err != nil {
135
+				t.Errorf("failed to readAll %s: %s", layer.jsonfile, err)
136
+				continue
137
+			}
138
+			gotSum = ts.Sum(buf)
139
+		} else {
140
+			gotSum = ts.Sum(nil)
141
+		}
142
+
143
+		if layer.tarsum != gotSum {
144
+			t.Errorf("expecting [%s], but got [%s]", layer.tarsum, gotSum)
145
+		}
146
+	}
147
+}
148
+
149
+func Benchmark9kTar(b *testing.B) {
150
+	buf := bytes.NewBuffer([]byte{})
151
+	fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
152
+	if err != nil {
153
+		b.Error(err)
154
+		return
155
+	}
156
+	n, err := io.Copy(buf, fh)
157
+	fh.Close()
158
+
159
+	b.SetBytes(n)
160
+	b.ResetTimer()
161
+	for i := 0; i < b.N; i++ {
162
+		ts := &TarSum{Reader: buf, DisableCompression: true}
163
+		io.Copy(ioutil.Discard, ts)
164
+		ts.Sum(nil)
165
+	}
166
+}
167
+
168
+func Benchmark9kTarGzip(b *testing.B) {
169
+	buf := bytes.NewBuffer([]byte{})
170
+	fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
171
+	if err != nil {
172
+		b.Error(err)
173
+		return
174
+	}
175
+	n, err := io.Copy(buf, fh)
176
+	fh.Close()
177
+
178
+	b.SetBytes(n)
179
+	b.ResetTimer()
180
+	for i := 0; i < b.N; i++ {
181
+		ts := &TarSum{Reader: buf, DisableCompression: false}
182
+		io.Copy(ioutil.Discard, ts)
183
+		ts.Sum(nil)
184
+	}
185
+}
186
+
187
+// this is a single big file in the tar archive
188
+func Benchmark1mbSingleFileTar(b *testing.B) {
189
+	benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, false)
190
+}
191
+
192
+// this is a single big file in the tar archive
193
+func Benchmark1mbSingleFileTarGzip(b *testing.B) {
194
+	benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, true)
195
+}
196
+
197
+// this is 1024 1k files in the tar archive
198
+func Benchmark1kFilesTar(b *testing.B) {
199
+	benchmarkTar(b, sizedOptions{1024, 1024, true, true}, false)
200
+}
201
+
202
+// this is 1024 1k files in the tar archive
203
+func Benchmark1kFilesTarGzip(b *testing.B) {
204
+	benchmarkTar(b, sizedOptions{1024, 1024, true, true}, true)
205
+}
206
+
207
+func benchmarkTar(b *testing.B, opts sizedOptions, isGzip bool) {
208
+	var fh *os.File
209
+	tarReader := sizedTar(opts)
210
+	if br, ok := tarReader.(*os.File); ok {
211
+		fh = br
212
+	}
213
+	defer os.Remove(fh.Name())
214
+	defer fh.Close()
215
+
216
+	b.SetBytes(opts.size * opts.num)
217
+	b.ResetTimer()
218
+	for i := 0; i < b.N; i++ {
219
+		ts := &TarSum{Reader: fh, DisableCompression: !isGzip}
220
+		io.Copy(ioutil.Discard, ts)
221
+		ts.Sum(nil)
222
+		fh.Seek(0, 0)
223
+	}
224
+}
... ...
@@ -26,6 +26,7 @@ import (
26 26
 	"github.com/docker/docker/dockerversion"
27 27
 	"github.com/docker/docker/pkg/httputils"
28 28
 	"github.com/docker/docker/pkg/parsers/kernel"
29
+	"github.com/docker/docker/pkg/tarsum"
29 30
 	"github.com/docker/docker/utils"
30 31
 )
31 32
 
... ...
@@ -638,7 +639,7 @@ func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registr
638 638
 
639 639
 	utils.Debugf("[registry] Calling PUT %s", registry+"images/"+imgID+"/layer")
640 640
 
641
-	tarsumLayer := &utils.TarSum{Reader: layer}
641
+	tarsumLayer := &tarsum.TarSum{Reader: layer}
642 642
 	h := sha256.New()
643 643
 	h.Write(jsonRaw)
644 644
 	h.Write([]byte{'\n'})
645 645
deleted file mode 100644
... ...
@@ -1,181 +0,0 @@
1
-package utils
2
-
3
-import (
4
-	"bytes"
5
-	"compress/gzip"
6
-	"crypto/sha256"
7
-	"encoding/hex"
8
-	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
9
-	"hash"
10
-	"io"
11
-	"sort"
12
-	"strconv"
13
-	"strings"
14
-)
15
-
16
-type TarSum struct {
17
-	io.Reader
18
-	tarR               *tar.Reader
19
-	tarW               *tar.Writer
20
-	gz                 writeCloseFlusher
21
-	bufTar             *bytes.Buffer
22
-	bufGz              *bytes.Buffer
23
-	h                  hash.Hash
24
-	sums               map[string]string
25
-	currentFile        string
26
-	finished           bool
27
-	first              bool
28
-	DisableCompression bool
29
-}
30
-
31
-type writeCloseFlusher interface {
32
-	io.WriteCloser
33
-	Flush() error
34
-}
35
-
36
-type nopCloseFlusher struct {
37
-	io.Writer
38
-}
39
-
40
-func (n *nopCloseFlusher) Close() error {
41
-	return nil
42
-}
43
-
44
-func (n *nopCloseFlusher) Flush() error {
45
-	return nil
46
-}
47
-
48
-func (ts *TarSum) encodeHeader(h *tar.Header) error {
49
-	for _, elem := range [][2]string{
50
-		{"name", h.Name},
51
-		{"mode", strconv.Itoa(int(h.Mode))},
52
-		{"uid", strconv.Itoa(h.Uid)},
53
-		{"gid", strconv.Itoa(h.Gid)},
54
-		{"size", strconv.Itoa(int(h.Size))},
55
-		{"mtime", strconv.Itoa(int(h.ModTime.UTC().Unix()))},
56
-		{"typeflag", string([]byte{h.Typeflag})},
57
-		{"linkname", h.Linkname},
58
-		{"uname", h.Uname},
59
-		{"gname", h.Gname},
60
-		{"devmajor", strconv.Itoa(int(h.Devmajor))},
61
-		{"devminor", strconv.Itoa(int(h.Devminor))},
62
-		// {"atime", strconv.Itoa(int(h.AccessTime.UTC().Unix()))},
63
-		// {"ctime", strconv.Itoa(int(h.ChangeTime.UTC().Unix()))},
64
-	} {
65
-		if _, err := ts.h.Write([]byte(elem[0] + elem[1])); err != nil {
66
-			return err
67
-		}
68
-	}
69
-	return nil
70
-}
71
-
72
-func (ts *TarSum) Read(buf []byte) (int, error) {
73
-	if ts.gz == nil {
74
-		ts.bufTar = bytes.NewBuffer([]byte{})
75
-		ts.bufGz = bytes.NewBuffer([]byte{})
76
-		ts.tarR = tar.NewReader(ts.Reader)
77
-		ts.tarW = tar.NewWriter(ts.bufTar)
78
-		if !ts.DisableCompression {
79
-			ts.gz = gzip.NewWriter(ts.bufGz)
80
-		} else {
81
-			ts.gz = &nopCloseFlusher{Writer: ts.bufGz}
82
-		}
83
-		ts.h = sha256.New()
84
-		ts.h.Reset()
85
-		ts.first = true
86
-		ts.sums = make(map[string]string)
87
-	}
88
-
89
-	if ts.finished {
90
-		return ts.bufGz.Read(buf)
91
-	}
92
-	buf2 := make([]byte, len(buf), cap(buf))
93
-
94
-	n, err := ts.tarR.Read(buf2)
95
-	if err != nil {
96
-		if err == io.EOF {
97
-			if _, err := ts.h.Write(buf2[:n]); err != nil {
98
-				return 0, err
99
-			}
100
-			if !ts.first {
101
-				ts.sums[ts.currentFile] = hex.EncodeToString(ts.h.Sum(nil))
102
-				ts.h.Reset()
103
-			} else {
104
-				ts.first = false
105
-			}
106
-
107
-			currentHeader, err := ts.tarR.Next()
108
-			if err != nil {
109
-				if err == io.EOF {
110
-					if err := ts.gz.Close(); err != nil {
111
-						return 0, err
112
-					}
113
-					ts.finished = true
114
-					return n, nil
115
-				}
116
-				return n, err
117
-			}
118
-			ts.currentFile = strings.TrimSuffix(strings.TrimPrefix(currentHeader.Name, "./"), "/")
119
-			if err := ts.encodeHeader(currentHeader); err != nil {
120
-				return 0, err
121
-			}
122
-			if err := ts.tarW.WriteHeader(currentHeader); err != nil {
123
-				return 0, err
124
-			}
125
-			if _, err := ts.tarW.Write(buf2[:n]); err != nil {
126
-				return 0, err
127
-			}
128
-			ts.tarW.Flush()
129
-			if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
130
-				return 0, err
131
-			}
132
-			ts.gz.Flush()
133
-
134
-			return ts.bufGz.Read(buf)
135
-		}
136
-		return n, err
137
-	}
138
-
139
-	// Filling the hash buffer
140
-	if _, err = ts.h.Write(buf2[:n]); err != nil {
141
-		return 0, err
142
-	}
143
-
144
-	// Filling the tar writter
145
-	if _, err = ts.tarW.Write(buf2[:n]); err != nil {
146
-		return 0, err
147
-	}
148
-	ts.tarW.Flush()
149
-
150
-	// Filling the gz writter
151
-	if _, err = io.Copy(ts.gz, ts.bufTar); err != nil {
152
-		return 0, err
153
-	}
154
-	ts.gz.Flush()
155
-
156
-	return ts.bufGz.Read(buf)
157
-}
158
-
159
-func (ts *TarSum) Sum(extra []byte) string {
160
-	var sums []string
161
-
162
-	for _, sum := range ts.sums {
163
-		sums = append(sums, sum)
164
-	}
165
-	sort.Strings(sums)
166
-	h := sha256.New()
167
-	if extra != nil {
168
-		h.Write(extra)
169
-	}
170
-	for _, sum := range sums {
171
-		Debugf("-->%s<--", sum)
172
-		h.Write([]byte(sum))
173
-	}
174
-	checksum := "tarsum+sha256:" + hex.EncodeToString(h.Sum(nil))
175
-	Debugf("checksum processed: %s", checksum)
176
-	return checksum
177
-}
178
-
179
-func (ts *TarSum) GetSums() map[string]string {
180
-	return ts.sums
181
-}
182 1
deleted file mode 100644
... ...
@@ -1,225 +0,0 @@
1
-package utils
2
-
3
-import (
4
-	"bytes"
5
-	"crypto/rand"
6
-	"fmt"
7
-	"io"
8
-	"io/ioutil"
9
-	"os"
10
-	"testing"
11
-
12
-	"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
13
-)
14
-
15
-type testLayer struct {
16
-	filename string
17
-	options  *sizedOptions
18
-	jsonfile string
19
-	gzip     bool
20
-	tarsum   string
21
-}
22
-
23
-var testLayers = []testLayer{
24
-	{
25
-		filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
26
-		jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
27
-		tarsum:   "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
28
-	{
29
-		filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
30
-		jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
31
-		gzip:     true,
32
-		tarsum:   "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
33
-	{
34
-		filename: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar",
35
-		jsonfile: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json",
36
-		tarsum:   "tarsum+sha256:ac672ee85da9ab7f9667ae3c32841d3e42f33cc52c273c23341dabba1c8b0c8b"},
37
-	{
38
-		options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
39
-		tarsum:  "tarsum+sha256:8bf12d7e67c51ee2e8306cba569398b1b9f419969521a12ffb9d8875e8836738"},
40
-}
41
-
42
-type sizedOptions struct {
43
-	num      int64
44
-	size     int64
45
-	isRand   bool
46
-	realFile bool
47
-}
48
-
49
-// make a tar:
50
-// * num is the number of files the tar should have
51
-// * size is the bytes per file
52
-// * isRand is whether the contents of the files should be a random chunk (otherwise it's all zeros)
53
-// * realFile will write to a TempFile, instead of an in memory buffer
54
-func sizedTar(opts sizedOptions) io.Reader {
55
-	var (
56
-		fh  io.ReadWriter
57
-		err error
58
-	)
59
-	if opts.realFile {
60
-		fh, err = ioutil.TempFile("", "tarsum")
61
-		if err != nil {
62
-			return nil
63
-		}
64
-	} else {
65
-		fh = bytes.NewBuffer([]byte{})
66
-	}
67
-	tarW := tar.NewWriter(fh)
68
-	for i := int64(0); i < opts.num; i++ {
69
-		err := tarW.WriteHeader(&tar.Header{
70
-			Name: fmt.Sprintf("/testdata%d", i),
71
-			Mode: 0755,
72
-			Uid:  0,
73
-			Gid:  0,
74
-			Size: opts.size,
75
-		})
76
-		if err != nil {
77
-			return nil
78
-		}
79
-		var rBuf []byte
80
-		if opts.isRand {
81
-			rBuf = make([]byte, 8)
82
-			_, err = rand.Read(rBuf)
83
-			if err != nil {
84
-				return nil
85
-			}
86
-		} else {
87
-			rBuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
88
-		}
89
-
90
-		for i := int64(0); i < opts.size/int64(8); i++ {
91
-			tarW.Write(rBuf)
92
-		}
93
-	}
94
-	return fh
95
-}
96
-
97
-func TestTarSums(t *testing.T) {
98
-	for _, layer := range testLayers {
99
-		var (
100
-			fh  io.Reader
101
-			err error
102
-		)
103
-		if len(layer.filename) > 0 {
104
-			fh, err = os.Open(layer.filename)
105
-			if err != nil {
106
-				t.Errorf("failed to open %s: %s", layer.filename, err)
107
-				continue
108
-			}
109
-		} else if layer.options != nil {
110
-			fh = sizedTar(*layer.options)
111
-		} else {
112
-			// What else is there to test?
113
-			t.Errorf("what to do with %#v", layer)
114
-			continue
115
-		}
116
-		if file, ok := fh.(*os.File); ok {
117
-			defer file.Close()
118
-		}
119
-
120
-		//                                  double negatives!
121
-		ts := &TarSum{Reader: fh, DisableCompression: !layer.gzip}
122
-		_, err = io.Copy(ioutil.Discard, ts)
123
-		if err != nil {
124
-			t.Errorf("failed to copy from %s: %s", layer.filename, err)
125
-			continue
126
-		}
127
-		var gotSum string
128
-		if len(layer.jsonfile) > 0 {
129
-			jfh, err := os.Open(layer.jsonfile)
130
-			if err != nil {
131
-				t.Errorf("failed to open %s: %s", layer.jsonfile, err)
132
-				continue
133
-			}
134
-			buf, err := ioutil.ReadAll(jfh)
135
-			if err != nil {
136
-				t.Errorf("failed to readAll %s: %s", layer.jsonfile, err)
137
-				continue
138
-			}
139
-			gotSum = ts.Sum(buf)
140
-		} else {
141
-			gotSum = ts.Sum(nil)
142
-		}
143
-
144
-		if layer.tarsum != gotSum {
145
-			t.Errorf("expecting [%s], but got [%s]", layer.tarsum, gotSum)
146
-		}
147
-	}
148
-}
149
-
150
-func Benchmark9kTar(b *testing.B) {
151
-	buf := bytes.NewBuffer([]byte{})
152
-	fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
153
-	if err != nil {
154
-		b.Error(err)
155
-		return
156
-	}
157
-	n, err := io.Copy(buf, fh)
158
-	fh.Close()
159
-
160
-	b.SetBytes(n)
161
-	b.ResetTimer()
162
-	for i := 0; i < b.N; i++ {
163
-		ts := &TarSum{Reader: buf, DisableCompression: true}
164
-		io.Copy(ioutil.Discard, ts)
165
-		ts.Sum(nil)
166
-	}
167
-}
168
-
169
-func Benchmark9kTarGzip(b *testing.B) {
170
-	buf := bytes.NewBuffer([]byte{})
171
-	fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
172
-	if err != nil {
173
-		b.Error(err)
174
-		return
175
-	}
176
-	n, err := io.Copy(buf, fh)
177
-	fh.Close()
178
-
179
-	b.SetBytes(n)
180
-	b.ResetTimer()
181
-	for i := 0; i < b.N; i++ {
182
-		ts := &TarSum{Reader: buf, DisableCompression: false}
183
-		io.Copy(ioutil.Discard, ts)
184
-		ts.Sum(nil)
185
-	}
186
-}
187
-
188
-// this is a single big file in the tar archive
189
-func Benchmark1mbSingleFileTar(b *testing.B) {
190
-	benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, false)
191
-}
192
-
193
-// this is a single big file in the tar archive
194
-func Benchmark1mbSingleFileTarGzip(b *testing.B) {
195
-	benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, true)
196
-}
197
-
198
-// this is 1024 1k files in the tar archive
199
-func Benchmark1kFilesTar(b *testing.B) {
200
-	benchmarkTar(b, sizedOptions{1024, 1024, true, true}, false)
201
-}
202
-
203
-// this is 1024 1k files in the tar archive
204
-func Benchmark1kFilesTarGzip(b *testing.B) {
205
-	benchmarkTar(b, sizedOptions{1024, 1024, true, true}, true)
206
-}
207
-
208
-func benchmarkTar(b *testing.B, opts sizedOptions, isGzip bool) {
209
-	var fh *os.File
210
-	tarReader := sizedTar(opts)
211
-	if br, ok := tarReader.(*os.File); ok {
212
-		fh = br
213
-	}
214
-	defer os.Remove(fh.Name())
215
-	defer fh.Close()
216
-
217
-	b.SetBytes(opts.size * opts.num)
218
-	b.ResetTimer()
219
-	for i := 0; i < b.N; i++ {
220
-		ts := &TarSum{Reader: fh, DisableCompression: !isGzip}
221
-		io.Copy(ioutil.Discard, ts)
222
-		ts.Sum(nil)
223
-		fh.Seek(0, 0)
224
-	}
225
-}