-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriter.go
112 lines (91 loc) · 1.82 KB
/
writer.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package rotatelogs
import (
"sync"
"time"
)
type writeToFileFunc func(p []byte) (n int, err error)
type baseWriter struct {
wf writeToFileFunc
}
type channelWriter struct {
baseWriter
syncChannel chan *syncDone
logChannel chan []byte
logWait sync.WaitGroup
}
type syncDone struct {
doneChan chan struct{}
}
type fileWriter struct {
baseWriter
}
func (s *syncDone) waitDone() bool {
select {
case <-s.doneChan:
return true
case <-time.After(DoneTimeout):
return false
}
}
func (s *syncDone) done() {
s.doneChan <- struct{}{}
}
func (cw *channelWriter) Write(p []byte) (n int, err error) {
cw.logChannel <- p
return len(p), nil
}
func (cw *channelWriter) Sync() error {
sDone := syncDone{doneChan: make(chan struct{}, 1)}
cw.syncChannel <- &sDone
sDone.waitDone()
return nil
}
func (cw *channelWriter) Close() error {
close(cw.syncChannel)
cw.logWait.Wait()
return nil
}
func (cw *fileWriter) Write(p []byte) (n int, err error) {
return cw.wf(p)
}
func (cw *fileWriter) Sync() error {
return nil
}
func (cw *fileWriter) Close() error {
return nil
}
func newChannelWriter(w writeToFileFunc, logChannelLen int) *channelWriter {
var writer channelWriter
writer.wf = w
writer.logChannel = make(chan []byte, logChannelLen)
writer.syncChannel = make(chan *syncDone, 1)
writer.logWait.Add(1)
go func() {
defer writer.logWait.Done()
for writer.write() {
}
}()
return &writer
}
func newFileWriter(w writeToFileFunc) *fileWriter {
var writer fileWriter
writer.wf = w
return &writer
}
func (cw *channelWriter) write() bool {
var byteLog []byte
select {
case sDone := <-cw.syncChannel:
for i := 0; i < len(cw.logChannel); i++ {
byteLog = <-cw.logChannel
cw.wf(byteLog)
}
if sDone == nil {
return false
}
sDone.done()
case byteLog = <-cw.logChannel:
cw.wf(byteLog)
}
return true
}