🌐 AI搜索 & 代理 主页
blob: 520073e3ab56c4b4ceae6f6f031270b5e56f4c2e [file] [log] [blame]
Andrea Luzzardia27b4b82013-01-19 00:13:391package docker
2
3import (
4 "bytes"
5 "container/list"
6 "io"
Andrea Luzzardie6adfa22013-02-13 21:58:287 "os"
Solomon Hykes37035362013-01-27 08:59:498 "os/exec"
Andrea Luzzardie6adfa22013-02-13 21:58:289 "path/filepath"
Andrea Luzzardi333abbf2013-01-28 22:30:0510 "sync"
Andrea Luzzardia27b4b82013-01-19 00:13:3911)
12
Solomon Hykesbcfe2aa2013-01-29 11:18:0713func Trunc(s string, maxlen int) string {
14 if len(s) <= maxlen {
15 return s
16 }
17 return s[:maxlen]
18}
19
Andrea Luzzardie6adfa22013-02-13 21:58:2820// Figure out the absolute path of our own binary
21func SelfPath() string {
22 path, err := exec.LookPath(os.Args[0])
23 if err != nil {
24 panic(err)
25 }
26 path, err = filepath.Abs(path)
27 if err != nil {
28 panic(err)
29 }
30 return path
31}
32
Solomon Hykes5d6dd222013-01-26 23:56:4233type nopWriteCloser struct {
34 io.Writer
35}
36
37func (w *nopWriteCloser) Close() error { return nil }
38
39func NopWriteCloser(w io.Writer) io.WriteCloser {
40 return &nopWriteCloser{w}
41}
42
Andrea Luzzardia27b4b82013-01-19 00:13:3943type bufReader struct {
44 buf *bytes.Buffer
45 reader io.Reader
46 err error
47 l sync.Mutex
48 wait sync.Cond
49}
50
51func newBufReader(r io.Reader) *bufReader {
52 reader := &bufReader{
53 buf: &bytes.Buffer{},
54 reader: r,
55 }
56 reader.wait.L = &reader.l
57 go reader.drain()
58 return reader
59}
60
61func (r *bufReader) drain() {
62 buf := make([]byte, 1024)
63 for {
64 n, err := r.reader.Read(buf)
65 if err != nil {
66 r.err = err
67 } else {
68 r.buf.Write(buf[0:n])
69 }
70 r.l.Lock()
71 r.wait.Signal()
72 r.l.Unlock()
73 if err != nil {
74 break
75 }
76 }
77}
78
79func (r *bufReader) Read(p []byte) (n int, err error) {
80 for {
81 n, err = r.buf.Read(p)
82 if n > 0 {
83 return n, err
84 }
85 if r.err != nil {
86 return 0, r.err
87 }
88 r.l.Lock()
89 r.wait.Wait()
90 r.l.Unlock()
91 }
92 return
93}
94
95func (r *bufReader) Close() error {
96 closer, ok := r.reader.(io.ReadCloser)
97 if !ok {
98 return nil
99 }
100 return closer.Close()
101}
102
103type writeBroadcaster struct {
104 writers *list.List
105}
106
107func (w *writeBroadcaster) AddWriter(writer io.WriteCloser) {
108 w.writers.PushBack(writer)
109}
110
111func (w *writeBroadcaster) RemoveWriter(writer io.WriteCloser) {
112 for e := w.writers.Front(); e != nil; e = e.Next() {
113 v := e.Value.(io.Writer)
114 if v == writer {
115 w.writers.Remove(e)
116 return
117 }
118 }
119}
120
121func (w *writeBroadcaster) Write(p []byte) (n int, err error) {
122 failed := []*list.Element{}
123 for e := w.writers.Front(); e != nil; e = e.Next() {
124 writer := e.Value.(io.Writer)
125 if n, err := writer.Write(p); err != nil || n != len(p) {
126 // On error, evict the writer
127 failed = append(failed, e)
128 }
129 }
130 // We cannot remove while iterating, so it has to be done in
131 // a separate step
132 for _, e := range failed {
133 w.writers.Remove(e)
134 }
135 return len(p), nil
136}
137
138func (w *writeBroadcaster) Close() error {
139 for e := w.writers.Front(); e != nil; e = e.Next() {
140 writer := e.Value.(io.WriteCloser)
141 writer.Close()
142 }
143 return nil
144}
145
146func newWriteBroadcaster() *writeBroadcaster {
147 return &writeBroadcaster{list.New()}
148}