-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathappender.go
112 lines (91 loc) · 2.09 KB
/
appender.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 logf
import (
"io"
"os"
"syscall"
)
// Appender is the interface for your own strategies for outputting log
// entries.
type Appender interface {
// Append logs the Entry in Appender specific way.
Append(Entry) error
// Flush writes uncommitted changes to the underlying buffer of Writer.
Flush() error
// Sync writes uncommitted changes to the stable storage. For files this
// means flushing the file system's in-memory copy of recently written
// data to disk.
Sync() error
}
// NewDiscardAppender returns a new Appender that does nothing.
func NewDiscardAppender() Appender {
return &discardAppender{}
}
type discardAppender struct {
}
func (a *discardAppender) Append(Entry) error {
return nil
}
func (a *discardAppender) Sync() (err error) {
return nil
}
func (a *discardAppender) Flush() error {
return nil
}
// NewWriteAppender returns a new Appender with the given Writer and Encoder.
func NewWriteAppender(w io.Writer, enc Encoder) Appender {
s, _ := w.(syncer)
if s != nil {
err := s.Sync()
// Check for EINVAL and ENOTSUP - known errors if Writer is bound to
// a special File (e.g., a pipe or socket) which does not support
// synchronization.
if pathErr, ok := err.(*os.PathError); ok {
if errno, ok := pathErr.Err.(syscall.Errno); ok {
if errno == syscall.EINVAL || errno == syscall.ENOTSUP {
// Disable future syncs.
s = nil
}
}
}
}
return &writeAppender{
w: w,
s: s,
enc: enc,
buf: NewBufferWithCapacity(PageSize * 2),
}
}
// syncer provides access the the Sync function of a Writer.
type syncer interface {
Sync() error
}
type writeAppender struct {
w io.Writer
s syncer
enc Encoder
buf *Buffer
}
func (a *writeAppender) Append(entry Entry) error {
err := a.enc.Encode(a.buf, entry)
if err != nil {
return err
}
if a.buf.Len() > PageSize {
a.Flush()
}
return nil
}
func (a *writeAppender) Sync() error {
if a.s == nil {
return nil
}
return a.s.Sync()
}
func (a *writeAppender) Flush() error {
if a.buf.Len() != 0 {
defer a.buf.Reset()
_, err := a.w.Write(a.buf.Bytes())
return err
}
return nil
}