github.com/a4a881d4/docker@v1.9.0-rc2/pkg/progressreader/progressreader.go (about)

     1  // Package progressreader provides a Reader with a progress bar that can be
     2  // printed out using the streamformatter package.
     3  package progressreader
     4  
     5  import (
     6  	"io"
     7  
     8  	"github.com/docker/docker/pkg/jsonmessage"
     9  	"github.com/docker/docker/pkg/streamformatter"
    10  )
    11  
    12  // Config contains the configuration for a Reader with progress bar.
    13  type Config struct {
    14  	In         io.ReadCloser // Stream to read from
    15  	Out        io.Writer     // Where to send progress bar to
    16  	Formatter  *streamformatter.StreamFormatter
    17  	Size       int64
    18  	Current    int64
    19  	LastUpdate int64
    20  	NewLines   bool
    21  	ID         string
    22  	Action     string
    23  }
    24  
    25  // New creates a new Config.
    26  func New(newReader Config) *Config {
    27  	return &newReader
    28  }
    29  
    30  func (config *Config) Read(p []byte) (n int, err error) {
    31  	read, err := config.In.Read(p)
    32  	config.Current += int64(read)
    33  	updateEvery := int64(1024 * 512) //512kB
    34  	if config.Size > 0 {
    35  		// Update progress for every 1% read if 1% < 512kB
    36  		if increment := int64(0.01 * float64(config.Size)); increment < updateEvery {
    37  			updateEvery = increment
    38  		}
    39  	}
    40  	if config.Current-config.LastUpdate > updateEvery || err != nil {
    41  		updateProgress(config)
    42  		config.LastUpdate = config.Current
    43  	}
    44  
    45  	if err != nil && read == 0 {
    46  		updateProgress(config)
    47  		if config.NewLines {
    48  			config.Out.Write(config.Formatter.FormatStatus("", ""))
    49  		}
    50  	}
    51  	return read, err
    52  }
    53  
    54  // Close closes the reader (Config).
    55  func (config *Config) Close() error {
    56  	if config.Current < config.Size {
    57  		//print a full progress bar when closing prematurely
    58  		config.Current = config.Size
    59  		updateProgress(config)
    60  	}
    61  	return config.In.Close()
    62  }
    63  
    64  func updateProgress(config *Config) {
    65  	progress := jsonmessage.JSONProgress{Current: config.Current, Total: config.Size}
    66  	fmtMessage := config.Formatter.FormatProgress(config.ID, config.Action, &progress)
    67  	config.Out.Write(fmtMessage)
    68  }