github.com/go-spring/spring-base@v1.1.3/log/plugin_writer.go (about) 1 /* 2 * Copyright 2012-2019 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package log 18 19 import ( 20 "context" 21 "io" 22 "os" 23 "sync" 24 ) 25 26 // Writers manages the Get and Release of Writer(s). 27 var Writers = &writers{ 28 writers: make(map[string]*sharedWriter), 29 } 30 31 // Writer is io.Writer with a name and a Stop method. 32 type Writer interface { 33 io.Writer 34 Name() string 35 Stop(ctx context.Context) 36 } 37 38 // writers manages the Get and Release of Writer(s). 39 type writers struct { 40 lock sync.Mutex 41 writers map[string]*sharedWriter 42 } 43 44 // sharedWriter wrappers count when decreases to 0 the Writer will be released. 45 type sharedWriter struct { 46 writer Writer 47 count int32 48 } 49 50 // Has returns true if a Writer named by name is cached, otherwise false. 51 func (s *writers) Has(name string) bool { 52 s.lock.Lock() 53 defer s.lock.Unlock() 54 _, ok := s.writers[name] 55 return ok 56 } 57 58 // Get returns a Writer that created by fn and named by name. 59 func (s *writers) Get(name string, fn func() (Writer, error)) (Writer, error) { 60 s.lock.Lock() 61 defer s.lock.Unlock() 62 sw, ok := s.writers[name] 63 if ok { 64 sw.count++ 65 return sw.writer, nil 66 } 67 w, err := fn() 68 if err != nil { 69 return nil, err 70 } 71 sw = &sharedWriter{writer: w} 72 s.writers[name] = sw 73 sw.count++ 74 return sw.writer, nil 75 } 76 77 // Release removes a Writer when its share count decreases to 0. 78 func (s *writers) Release(ctx context.Context, writer Writer) { 79 s.lock.Lock() 80 defer s.lock.Unlock() 81 sw, ok := s.writers[writer.Name()] 82 if !ok { 83 return 84 } 85 sw.count-- 86 if sw.count > 0 { 87 return 88 } 89 delete(s.writers, writer.Name()) 90 writer.Stop(ctx) 91 } 92 93 // FileWriter is a Writer implementation by *os.File. 94 type FileWriter struct { 95 file *os.File 96 } 97 98 // NewFileWriter returns a FileWriter that a Writer implementation. 99 func NewFileWriter(fileName string) (Writer, error) { 100 flag := os.O_RDWR | os.O_CREATE | os.O_APPEND 101 file, err := os.OpenFile(fileName, flag, 666) 102 if err != nil { 103 return nil, err 104 } 105 return &FileWriter{file: file}, nil 106 } 107 108 func (c *FileWriter) Name() string { 109 return c.file.Name() 110 } 111 112 func (c *FileWriter) Write(p []byte) (n int, err error) { 113 return c.file.Write(p) 114 } 115 116 func (c *FileWriter) Stop(ctx context.Context) { 117 118 }