github.com/titanous/docker@v1.4.1/pkg/ioutils/readers.go (about) 1 package ioutils 2 3 import ( 4 "bytes" 5 "io" 6 "sync" 7 ) 8 9 type readCloserWrapper struct { 10 io.Reader 11 closer func() error 12 } 13 14 func (r *readCloserWrapper) Close() error { 15 return r.closer() 16 } 17 18 func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { 19 return &readCloserWrapper{ 20 Reader: r, 21 closer: closer, 22 } 23 } 24 25 type readerErrWrapper struct { 26 reader io.Reader 27 closer func() 28 } 29 30 func (r *readerErrWrapper) Read(p []byte) (int, error) { 31 n, err := r.reader.Read(p) 32 if err != nil { 33 r.closer() 34 } 35 return n, err 36 } 37 38 func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader { 39 return &readerErrWrapper{ 40 reader: r, 41 closer: closer, 42 } 43 } 44 45 type bufReader struct { 46 sync.Mutex 47 buf *bytes.Buffer 48 reader io.Reader 49 err error 50 wait sync.Cond 51 drainBuf []byte 52 } 53 54 func NewBufReader(r io.Reader) *bufReader { 55 reader := &bufReader{ 56 buf: &bytes.Buffer{}, 57 drainBuf: make([]byte, 1024), 58 reader: r, 59 } 60 reader.wait.L = &reader.Mutex 61 go reader.drain() 62 return reader 63 } 64 65 func NewBufReaderWithDrainbufAndBuffer(r io.Reader, drainBuffer []byte, buffer *bytes.Buffer) *bufReader { 66 reader := &bufReader{ 67 buf: buffer, 68 drainBuf: drainBuffer, 69 reader: r, 70 } 71 reader.wait.L = &reader.Mutex 72 go reader.drain() 73 return reader 74 } 75 76 func (r *bufReader) drain() { 77 for { 78 n, err := r.reader.Read(r.drainBuf) 79 r.Lock() 80 if err != nil { 81 r.err = err 82 } else { 83 r.buf.Write(r.drainBuf[0:n]) 84 } 85 r.wait.Signal() 86 r.Unlock() 87 if err != nil { 88 break 89 } 90 } 91 } 92 93 func (r *bufReader) Read(p []byte) (n int, err error) { 94 r.Lock() 95 defer r.Unlock() 96 for { 97 n, err = r.buf.Read(p) 98 if n > 0 { 99 return n, err 100 } 101 if r.err != nil { 102 return 0, r.err 103 } 104 r.wait.Wait() 105 } 106 } 107 108 func (r *bufReader) Close() error { 109 closer, ok := r.reader.(io.ReadCloser) 110 if !ok { 111 return nil 112 } 113 return closer.Close() 114 }