OSDN Git Service

delete miner
[bytom/vapor.git] / vendor / github.com / go-kit / kit / log / sync.go
1 package log
2
3 import (
4         "io"
5         "sync"
6         "sync/atomic"
7 )
8
9 // SwapLogger wraps another logger that may be safely replaced while other
10 // goroutines use the SwapLogger concurrently. The zero value for a SwapLogger
11 // will discard all log events without error.
12 //
13 // SwapLogger serves well as a package global logger that can be changed by
14 // importers.
15 type SwapLogger struct {
16         logger atomic.Value
17 }
18
19 type loggerStruct struct {
20         Logger
21 }
22
23 // Log implements the Logger interface by forwarding keyvals to the currently
24 // wrapped logger. It does not log anything if the wrapped logger is nil.
25 func (l *SwapLogger) Log(keyvals ...interface{}) error {
26         s, ok := l.logger.Load().(loggerStruct)
27         if !ok || s.Logger == nil {
28                 return nil
29         }
30         return s.Log(keyvals...)
31 }
32
33 // Swap replaces the currently wrapped logger with logger. Swap may be called
34 // concurrently with calls to Log from other goroutines.
35 func (l *SwapLogger) Swap(logger Logger) {
36         l.logger.Store(loggerStruct{logger})
37 }
38
39 // NewSyncWriter returns a new writer that is safe for concurrent use by
40 // multiple goroutines. Writes to the returned writer are passed on to w. If
41 // another write is already in progress, the calling goroutine blocks until
42 // the writer is available.
43 //
44 // If w implements the following interface, so does the returned writer.
45 //
46 //    interface {
47 //        Fd() uintptr
48 //    }
49 func NewSyncWriter(w io.Writer) io.Writer {
50         switch w := w.(type) {
51         case fdWriter:
52                 return &fdSyncWriter{fdWriter: w}
53         default:
54                 return &syncWriter{Writer: w}
55         }
56 }
57
58 // syncWriter synchronizes concurrent writes to an io.Writer.
59 type syncWriter struct {
60         sync.Mutex
61         io.Writer
62 }
63
64 // Write writes p to the underlying io.Writer. If another write is already in
65 // progress, the calling goroutine blocks until the syncWriter is available.
66 func (w *syncWriter) Write(p []byte) (n int, err error) {
67         w.Lock()
68         n, err = w.Writer.Write(p)
69         w.Unlock()
70         return n, err
71 }
72
73 // fdWriter is an io.Writer that also has an Fd method. The most common
74 // example of an fdWriter is an *os.File.
75 type fdWriter interface {
76         io.Writer
77         Fd() uintptr
78 }
79
80 // fdSyncWriter synchronizes concurrent writes to an fdWriter.
81 type fdSyncWriter struct {
82         sync.Mutex
83         fdWriter
84 }
85
86 // Write writes p to the underlying io.Writer. If another write is already in
87 // progress, the calling goroutine blocks until the fdSyncWriter is available.
88 func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
89         w.Lock()
90         n, err = w.fdWriter.Write(p)
91         w.Unlock()
92         return n, err
93 }
94
95 // syncLogger provides concurrent safe logging for another Logger.
96 type syncLogger struct {
97         mu     sync.Mutex
98         logger Logger
99 }
100
101 // NewSyncLogger returns a logger that synchronizes concurrent use of the
102 // wrapped logger. When multiple goroutines use the SyncLogger concurrently
103 // only one goroutine will be allowed to log to the wrapped logger at a time.
104 // The other goroutines will block until the logger is available.
105 func NewSyncLogger(logger Logger) Logger {
106         return &syncLogger{logger: logger}
107 }
108
109 // Log logs keyvals to the underlying Logger. If another log is already in
110 // progress, the calling goroutine blocks until the syncLogger is available.
111 func (l *syncLogger) Log(keyvals ...interface{}) error {
112         l.mu.Lock()
113         err := l.logger.Log(keyvals...)
114         l.mu.Unlock()
115         return err
116 }