fsdiff.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package graphdriver
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/docker/docker/archive"
  6. "github.com/docker/docker/pkg/ioutils"
  7. "github.com/docker/docker/pkg/log"
  8. "github.com/docker/docker/utils"
  9. )
  10. // GenericDriverWrapper takes a generic Driver and adds the
  11. // capability of the following methods which it doesn't
  12. // support on its own:
  13. // Diff(id, parent string) (archive.Archive, error)
  14. // Changes(id, parent string) ([]archive.Change, error)
  15. // ApplyDiff(id, parent string, diff archive.ArchiveReader) (bytes int64, err error)
  16. // DiffSize(id, parent string) (bytes int64, err error)
  17. // Notably, the AUFS driver doesn't need to be wrapped like this.
  18. type GenericDriverWrapper struct {
  19. GenericDriver
  20. }
  21. // NewGenericDriverWrapper returns a fully functional driver that wraps the given GenericDriver.
  22. func NewGenericDriverWrapper(driver GenericDriver) Driver {
  23. return &GenericDriverWrapper{GenericDriver: driver}
  24. }
  25. // Diff produces an archive of the changes between the specified
  26. // layer and its parent layer which may be "".
  27. func (gdw *GenericDriverWrapper) Diff(id, parent string) (arch archive.Archive, err error) {
  28. driver := gdw.GenericDriver
  29. layerFs, err := driver.Get(id, "")
  30. if err != nil {
  31. return nil, err
  32. }
  33. defer func() {
  34. if err != nil {
  35. driver.Put(id)
  36. }
  37. }()
  38. if parent == "" {
  39. archive, err := archive.Tar(layerFs, archive.Uncompressed)
  40. if err != nil {
  41. return nil, err
  42. }
  43. return ioutils.NewReadCloserWrapper(archive, func() error {
  44. err := archive.Close()
  45. driver.Put(id)
  46. return err
  47. }), nil
  48. }
  49. parentFs, err := driver.Get(parent, "")
  50. if err != nil {
  51. return nil, err
  52. }
  53. defer driver.Put(parent)
  54. changes, err := archive.ChangesDirs(layerFs, parentFs)
  55. if err != nil {
  56. return nil, err
  57. }
  58. archive, err := archive.ExportChanges(layerFs, changes)
  59. if err != nil {
  60. return nil, err
  61. }
  62. return ioutils.NewReadCloserWrapper(archive, func() error {
  63. err := archive.Close()
  64. driver.Put(id)
  65. return err
  66. }), nil
  67. }
  68. // Changes produces a list of changes between the specified layer
  69. // and its parent layer. If parent is "", then all changes will be ADD changes.
  70. func (gdw *GenericDriverWrapper) Changes(id, parent string) ([]archive.Change, error) {
  71. driver := gdw.GenericDriver
  72. layerFs, err := driver.Get(id, "")
  73. if err != nil {
  74. return nil, err
  75. }
  76. defer driver.Put(id)
  77. parentFs := ""
  78. if parent != "" {
  79. parentFs, err = driver.Get(parent, "")
  80. if err != nil {
  81. return nil, err
  82. }
  83. defer driver.Put(parent)
  84. }
  85. return archive.ChangesDirs(layerFs, parentFs)
  86. }
  87. // ApplyDiff extracts the changeset from the given diff into the
  88. // layer with the specified id and parent, returning the size of the
  89. // new layer in bytes.
  90. func (gdw *GenericDriverWrapper) ApplyDiff(id, parent string, diff archive.ArchiveReader) (bytes int64, err error) {
  91. driver := gdw.GenericDriver
  92. // Mount the root filesystem so we can apply the diff/layer.
  93. layerFs, err := driver.Get(id, "")
  94. if err != nil {
  95. return
  96. }
  97. defer driver.Put(id)
  98. start := time.Now().UTC()
  99. log.Debugf("Start untar layer")
  100. if err = archive.ApplyLayer(layerFs, diff); err != nil {
  101. return
  102. }
  103. log.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
  104. if parent == "" {
  105. return utils.TreeSize(layerFs)
  106. }
  107. parentFs, err := driver.Get(parent, "")
  108. if err != nil {
  109. err = fmt.Errorf("Driver %s failed to get image parent %s: %s", driver, parent, err)
  110. return
  111. }
  112. defer driver.Put(parent)
  113. changes, err := archive.ChangesDirs(layerFs, parentFs)
  114. if err != nil {
  115. return
  116. }
  117. return archive.ChangesSize(layerFs, changes), nil
  118. }
  119. // DiffSize calculates the changes between the specified layer
  120. // and its parent and returns the size in bytes of the changes
  121. // relative to its base filesystem directory.
  122. func (gdw *GenericDriverWrapper) DiffSize(id, parent string) (bytes int64, err error) {
  123. driver := gdw.GenericDriver
  124. changes, err := gdw.Changes(id, parent)
  125. if err != nil {
  126. return
  127. }
  128. layerFs, err := driver.Get(id, "")
  129. if err != nil {
  130. return
  131. }
  132. defer driver.Put(id)
  133. return archive.ChangesSize(layerFs, changes), nil
  134. }