github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/storage/driver/azure/zerofillwriter.go (about)

     1  package azure
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  )
     7  
     8  type blockBlobWriter interface {
     9  	GetSize(container, blob string) (int64, error)
    10  	WriteBlobAt(container, blob string, offset int64, chunk io.Reader) (int64, error)
    11  }
    12  
    13  // zeroFillWriter enables writing to an offset outside a block blob's size
    14  // by offering the chunk to the underlying writer as a contiguous data with
    15  // the gap in between filled with NUL (zero) bytes.
    16  type zeroFillWriter struct {
    17  	blockBlobWriter
    18  }
    19  
    20  func newZeroFillWriter(b blockBlobWriter) zeroFillWriter {
    21  	w := zeroFillWriter{}
    22  	w.blockBlobWriter = b
    23  	return w
    24  }
    25  
    26  // Write writes the given chunk to the specified existing blob even though
    27  // offset is out of blob's size. The gaps are filled with zeros. Returned
    28  // written number count does not include zeros written.
    29  func (z *zeroFillWriter) Write(container, blob string, offset int64, chunk io.Reader) (int64, error) {
    30  	size, err := z.blockBlobWriter.GetSize(container, blob)
    31  	if err != nil {
    32  		return 0, err
    33  	}
    34  
    35  	var reader io.Reader
    36  	var zeroPadding int64
    37  	if offset <= size {
    38  		reader = chunk
    39  	} else {
    40  		zeroPadding = offset - size
    41  		offset = size // adjust offset to be the append index
    42  		zeros := bytes.NewReader(make([]byte, zeroPadding))
    43  		reader = io.MultiReader(zeros, chunk)
    44  	}
    45  
    46  	nn, err := z.blockBlobWriter.WriteBlobAt(container, blob, offset, reader)
    47  	nn -= zeroPadding
    48  	return nn, err
    49  }