Tizen_4.0 base
[platform/upstream/docker-engine.git] / distribution / utils / progress.go
1 package utils
2
3 import (
4         "io"
5         "net"
6         "os"
7         "syscall"
8
9         "github.com/Sirupsen/logrus"
10         "github.com/docker/docker/pkg/progress"
11         "github.com/docker/docker/pkg/streamformatter"
12 )
13
14 // WriteDistributionProgress is a helper for writing progress from chan to JSON
15 // stream with an optional cancel function.
16 func WriteDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) {
17         progressOutput := streamformatter.NewJSONProgressOutput(outStream, false)
18         operationCancelled := false
19
20         for prog := range progressChan {
21                 if err := progressOutput.WriteProgress(prog); err != nil && !operationCancelled {
22                         // don't log broken pipe errors as this is the normal case when a client aborts
23                         if isBrokenPipe(err) {
24                                 logrus.Info("Pull session cancelled")
25                         } else {
26                                 logrus.Errorf("error writing progress to client: %v", err)
27                         }
28                         cancelFunc()
29                         operationCancelled = true
30                         // Don't return, because we need to continue draining
31                         // progressChan until it's closed to avoid a deadlock.
32                 }
33         }
34 }
35
36 func isBrokenPipe(e error) bool {
37         if netErr, ok := e.(*net.OpError); ok {
38                 e = netErr.Err
39                 if sysErr, ok := netErr.Err.(*os.SyscallError); ok {
40                         e = sysErr.Err
41                 }
42         }
43         return e == syscall.EPIPE
44 }