forked from vmware-archive/glider
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logbuffer.go
91 lines (66 loc) · 1.47 KB
/
logbuffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package logbuffer
import (
"errors"
"io"
"sync"
)
type LogBuffer struct {
content []byte
contentMutex *sync.RWMutex
sinks []io.WriteCloser
closed bool
waitForClosed chan struct{}
}
func NewLogBuffer() *LogBuffer {
return &LogBuffer{
contentMutex: new(sync.RWMutex),
waitForClosed: make(chan struct{}),
}
}
func (buffer *LogBuffer) Write(data []byte) (int, error) {
buffer.contentMutex.Lock()
buffer.content = append(buffer.content, data...)
newSinks := []io.WriteCloser{}
for _, sink := range buffer.sinks {
_, err := sink.Write(data)
if err != nil {
continue
}
newSinks = append(newSinks, sink)
}
buffer.sinks = newSinks
buffer.contentMutex.Unlock()
return len(data), nil
}
func (buffer *LogBuffer) Attach(sink io.WriteCloser) {
buffer.contentMutex.Lock()
sink.Write(buffer.content)
if buffer.closed {
sink.Close()
} else {
buffer.sinks = append(buffer.sinks, sink)
}
buffer.contentMutex.Unlock()
<-buffer.waitForClosed
}
func (buffer *LogBuffer) Close() error {
buffer.contentMutex.Lock()
defer buffer.contentMutex.Unlock()
if buffer.closed {
return errors.New("close twice")
}
for _, sink := range buffer.sinks {
sink.Close()
}
buffer.closed = true
buffer.sinks = nil
close(buffer.waitForClosed)
return nil
}
func (buffer *LogBuffer) Content() []byte {
buffer.contentMutex.Lock()
content := make([]byte, len(buffer.content))
copy(content, buffer.content)
buffer.contentMutex.Unlock()
return content
}