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  }