Browse code

graphdriver: Replace DiffPath with DiffGetter

This allows a graph driver to provide a custom FileGetter for tar-split
to use. Windows will use this to provide a more efficient implementation
in a follow-up change.

Signed-off-by: John Starks <jostarks@microsoft.com>

John Starks authored on 2016/02/19 10:58:23
Showing 4 changed files
... ...
@@ -34,6 +34,7 @@ import (
34 34
 	"syscall"
35 35
 
36 36
 	"github.com/Sirupsen/logrus"
37
+	"github.com/vbatts/tar-split/tar/storage"
37 38
 
38 39
 	"github.com/docker/docker/daemon/graphdriver"
39 40
 	"github.com/docker/docker/pkg/archive"
... ...
@@ -367,10 +368,19 @@ func (a *Driver) Diff(id, parent string) (archive.Archive, error) {
367 367
 	})
368 368
 }
369 369
 
370
-// DiffPath returns path to the directory that contains files for the layer
371
-// differences. Used for direct access for tar-split.
372
-func (a *Driver) DiffPath(id string) (string, func() error, error) {
373
-	return path.Join(a.rootPath(), "diff", id), func() error { return nil }, nil
370
+type fileGetNilCloser struct {
371
+	storage.FileGetter
372
+}
373
+
374
+func (f fileGetNilCloser) Close() error {
375
+	return nil
376
+}
377
+
378
+// DiffGetter returns a FileGetCloser that can read files from the directory that
379
+// contains files for the layer differences. Used for direct access for tar-split.
380
+func (a *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
381
+	p := path.Join(a.rootPath(), "diff", id)
382
+	return fileGetNilCloser{storage.NewPathFileGetter(p)}, nil
374 383
 }
375 384
 
376 385
 func (a *Driver) applyDiff(id string, diff archive.Reader) error {
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	"github.com/Sirupsen/logrus"
11
+	"github.com/vbatts/tar-split/tar/storage"
11 12
 
12 13
 	"github.com/docker/docker/pkg/archive"
13 14
 	"github.com/docker/docker/pkg/idtools"
... ...
@@ -92,6 +93,23 @@ type Driver interface {
92 92
 	DiffSize(id, parent string) (size int64, err error)
93 93
 }
94 94
 
95
+// DiffGetterDriver is the interface for layered file system drivers that
96
+// provide a specialized function for getting file contents for tar-split.
97
+type DiffGetterDriver interface {
98
+	Driver
99
+	// DiffGetter returns an interface to efficiently retrieve the contents
100
+	// of files in a layer.
101
+	DiffGetter(id string) (FileGetCloser, error)
102
+}
103
+
104
+// FileGetCloser extends the storage.FileGetter interface with a Close method
105
+// for cleaning up.
106
+type FileGetCloser interface {
107
+	storage.FileGetter
108
+	// Close cleans up any resources associated with the FileGetCloser.
109
+	Close() error
110
+}
111
+
95 112
 func init() {
96 113
 	drivers = make(map[string]InitFunc)
97 114
 }
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	"github.com/docker/docker/pkg/idtools"
23 23
 	"github.com/docker/docker/pkg/ioutils"
24 24
 	"github.com/docker/docker/pkg/random"
25
+	"github.com/vbatts/tar-split/tar/storage"
25 26
 )
26 27
 
27 28
 // init registers the windows graph drivers to the register.
... ...
@@ -47,6 +48,8 @@ type Driver struct {
47 47
 	active map[string]int
48 48
 }
49 49
 
50
+var _ graphdriver.DiffGetterDriver = &Driver{}
51
+
50 52
 // InitFilter returns a new Windows storage filter driver.
51 53
 func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
52 54
 	logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
... ...
@@ -564,8 +567,20 @@ func (d *Driver) setLayerChain(id string, chain []string) error {
564 564
 	return nil
565 565
 }
566 566
 
567
-// DiffPath returns a directory that contains files needed to construct layer diff.
568
-func (d *Driver) DiffPath(id string) (path string, release func() error, err error) {
567
+type fileGetDestroyCloser struct {
568
+	storage.FileGetter
569
+	d          *Driver
570
+	folderName string
571
+}
572
+
573
+func (f *fileGetDestroyCloser) Close() error {
574
+	// TODO: activate layers and release here?
575
+	return hcsshim.DestroyLayer(f.d.info, f.folderName)
576
+}
577
+
578
+// DiffGetter returns a FileGetCloser that can read files from the directory that
579
+// contains files for the layer differences. Used for direct access for tar-split.
580
+func (d *Driver) DiffGetter(id string) (fg graphdriver.FileGetCloser, err error) {
569 581
 	id, err = d.resolveID(id)
570 582
 	if err != nil {
571 583
 		return
... ...
@@ -597,9 +612,6 @@ func (d *Driver) DiffPath(id string) (path string, release func() error, err err
597 597
 		return
598 598
 	}
599 599
 
600
-	return tempFolder, func() error {
601
-		// TODO: activate layers and release here?
602
-		_, folderName := filepath.Split(tempFolder)
603
-		return hcsshim.DestroyLayer(d.info, folderName)
604
-	}, nil
600
+	_, folderName := filepath.Split(tempFolder)
601
+	return &fileGetDestroyCloser{storage.NewPathFileGetter(tempFolder), d, folderName}, nil
605 602
 }
... ...
@@ -577,11 +577,7 @@ func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc Mou
577 577
 }
578 578
 
579 579
 func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size *int64, w io.Writer) error {
580
-	type diffPathDriver interface {
581
-		DiffPath(string) (string, func() error, error)
582
-	}
583
-
584
-	diffDriver, ok := ls.driver.(diffPathDriver)
580
+	diffDriver, ok := ls.driver.(graphdriver.DiffGetterDriver)
585 581
 	if !ok {
586 582
 		diffDriver = &naiveDiffPathDriver{ls.driver}
587 583
 	}
... ...
@@ -589,17 +585,16 @@ func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size
589 589
 	defer metadata.Close()
590 590
 
591 591
 	// get our relative path to the container
592
-	fsPath, releasePath, err := diffDriver.DiffPath(graphID)
592
+	fileGetCloser, err := diffDriver.DiffGetter(graphID)
593 593
 	if err != nil {
594 594
 		return err
595 595
 	}
596
-	defer releasePath()
596
+	defer fileGetCloser.Close()
597 597
 
598 598
 	metaUnpacker := storage.NewJSONUnpacker(metadata)
599 599
 	upackerCounter := &unpackSizeCounter{metaUnpacker, size}
600
-	fileGetter := storage.NewPathFileGetter(fsPath)
601
-	logrus.Debugf("Assembling tar data for %s from %s", graphID, fsPath)
602
-	return asm.WriteOutputTarStream(fileGetter, upackerCounter, w)
600
+	logrus.Debugf("Assembling tar data for %s", graphID)
601
+	return asm.WriteOutputTarStream(fileGetCloser, upackerCounter, w)
603 602
 }
604 603
 
605 604
 func (ls *layerStore) Cleanup() error {
... ...
@@ -618,12 +613,20 @@ type naiveDiffPathDriver struct {
618 618
 	graphdriver.Driver
619 619
 }
620 620
 
621
-func (n *naiveDiffPathDriver) DiffPath(id string) (string, func() error, error) {
621
+type fileGetPutter struct {
622
+	storage.FileGetter
623
+	driver graphdriver.Driver
624
+	id     string
625
+}
626
+
627
+func (w *fileGetPutter) Close() error {
628
+	return w.driver.Put(w.id)
629
+}
630
+
631
+func (n *naiveDiffPathDriver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
622 632
 	p, err := n.Driver.Get(id, "")
623 633
 	if err != nil {
624
-		return "", nil, err
634
+		return nil, err
625 635
 	}
626
-	return p, func() error {
627
-		return n.Driver.Put(id)
628
-	}, nil
636
+	return &fileGetPutter{storage.NewPathFileGetter(p), n.Driver, id}, nil
629 637
 }