github.com/vicanso/pike@v1.0.1-0.20210630235453-9099e041f6ec/config/file_client.go (about)

     1  // MIT License
     2  
     3  // Copyright (c) 2020 Tree Xie
     4  
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy
     6  // of this software and associated documentation files (the "Software"), to deal
     7  // in the Software without restriction, including without limitation the rights
     8  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  // copies of the Software, and to permit persons to whom the Software is
    10  // furnished to do so, subject to the following conditions:
    11  
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21  // SOFTWARE.
    22  
    23  // file client for config
    24  
    25  package config
    26  
    27  import (
    28  	"io/ioutil"
    29  	"os"
    30  
    31  	"github.com/fsnotify/fsnotify"
    32  	"github.com/vicanso/pike/log"
    33  	"go.uber.org/zap"
    34  )
    35  
    36  // fileClient file client
    37  type fileClient struct {
    38  	file    string
    39  	watcher *fsnotify.Watcher
    40  }
    41  
    42  const defaultPerm os.FileMode = 0600
    43  
    44  // NewFileClient create a new file client
    45  func NewFileClient(file string) (client *fileClient, err error) {
    46  	f, err := os.OpenFile(file, os.O_RDONLY|os.O_CREATE, defaultPerm)
    47  	if err != nil {
    48  		return
    49  	}
    50  	defer f.Close()
    51  
    52  	watcher, err := fsnotify.NewWatcher()
    53  	if err != nil {
    54  		return
    55  	}
    56  
    57  	client = &fileClient{
    58  		file:    file,
    59  		watcher: watcher,
    60  	}
    61  	return
    62  }
    63  
    64  // Get get data from file
    65  func (fc *fileClient) Get() (data []byte, err error) {
    66  	return ioutil.ReadFile(fc.file)
    67  }
    68  
    69  // Set set data to file
    70  func (fc *fileClient) Set(data []byte) (err error) {
    71  	return ioutil.WriteFile(fc.file, data, defaultPerm)
    72  }
    73  
    74  // Watch watch config change
    75  func (fc *fileClient) Watch(onChange OnChange) {
    76  
    77  	err := fc.watcher.Add(fc.file)
    78  	if err != nil {
    79  		log.Default().Error("add watch fail",
    80  			zap.String("file", fc.file),
    81  			zap.Error(err),
    82  		)
    83  		return
    84  	}
    85  	for {
    86  		select {
    87  		case event, ok := <-fc.watcher.Events:
    88  			if !ok {
    89  				return
    90  			}
    91  			if event.Op&fsnotify.Write == fsnotify.Write {
    92  				onChange()
    93  			}
    94  		case err, ok := <-fc.watcher.Errors:
    95  			if !ok {
    96  				return
    97  			}
    98  			if err != nil {
    99  				log.Default().Error("watch error",
   100  					zap.String("file", fc.file),
   101  					zap.Error(err),
   102  				)
   103  			}
   104  		}
   105  	}
   106  }
   107  
   108  // Close close file client
   109  func (fc *fileClient) Close() error {
   110  	return fc.watcher.Close()
   111  }