cubefs

Форк
0
/
reload_conf.go 
162 строки · 3.8 Кб
1
// Copyright 2023 The CubeFS Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
14

15
package reloadconf
16

17
import (
18
	"bytes"
19
	"crypto/md5"
20
	"encoding/base64"
21
	"fmt"
22
	"os"
23
	"sync"
24
	"time"
25

26
	"github.com/cubefs/cubefs/blobstore/util/errors"
27
	"github.com/cubefs/cubefs/util/log"
28
)
29

30
// ReloadConf loads remote configuration change dynamically
31
type ReloadConf struct {
32
	ConfName      string
33
	ReloadSec     int
34
	RequestRemote func() ([]byte, error)
35

36
	md5sum []byte
37
	mutex  sync.Mutex
38
}
39

40
func (self *ReloadConf) reload(reload func(data []byte) error) error {
41
	self.mutex.Lock()
42
	defer self.mutex.Unlock()
43

44
	// remote load
45
	if self.RequestRemote != nil {
46
		errRemote := self.remoteReload(reload)
47
		if errRemote != nil {
48
			log.LogWarn("remoteReload failed", self.ConfName, errors.Detail(errRemote))
49
		} else {
50
			return nil
51
		}
52
	}
53

54
	// local load
55
	errLocal := self.localReload(reload)
56
	if errLocal != nil {
57
		err := errors.Info(errLocal, "localReload").Detail(errLocal)
58
		return err
59
	}
60
	return nil
61
}
62

63
func (self *ReloadConf) remoteReload(reload func(data []byte) error) (err error) {
64
	data, md5sum, err := fetchRemote(self.RequestRemote)
65
	if err != nil {
66
		err = errors.Info(err, "fetchRemote").Detail(err)
67
		return
68
	}
69

70
	// compare whether md5sum is changed
71
	if bytes.Equal(md5sum, self.md5sum) {
72
		log.LogDebug("remoteReload:", self.ConfName, "do nothing cause of md5sum is equal")
73
		return nil
74
	}
75

76
	confName := fmt.Sprintf("%v_%v", self.ConfName, base64.URLEncoding.EncodeToString(md5sum))
77
	err = os.WriteFile(confName, data, 0o666)
78
	if err != nil {
79
		err = errors.Info(err, "os.WriteFile")
80
		return
81
	}
82
	log.LogInfof("remoteReload %v remote file is changed, oldmd5: %v, newmd5: %v", self.ConfName, self.md5sum, md5sum)
83

84
	err = reload(data)
85
	if err != nil {
86
		os.Remove(confName)
87
		err = errors.Info(err, "reload", confName).Detail(err)
88
		return
89
	}
90

91
	err = os.Rename(confName, self.ConfName)
92
	if err != nil {
93
		os.Remove(confName)
94
		err = errors.Info(err, "os.Rename")
95
		return
96
	}
97
	self.md5sum = md5sum
98

99
	return
100
}
101

102
func (self *ReloadConf) localReload(reload func(data []byte) error) (err error) {
103
	data, err := os.ReadFile(self.ConfName)
104
	if err != nil {
105
		err = errors.Info(err, "os.ReadFile").Detail(err)
106
		return
107
	}
108
	md5sum := calcMD5Sum(data)
109

110
	if bytes.Equal(md5sum, self.md5sum) {
111
		log.LogDebug("localReload:", self.ConfName, "do nothing cause of md5sum is equal")
112
		return nil
113
	}
114

115
	log.LogInfof("localReload: %v local file is changed, oldmd5: %v, newmd5: %v", self.ConfName, self.md5sum, md5sum)
116
	err = reload(data)
117
	if err != nil {
118
		err = errors.Info(err, "reload").Detail(err)
119
		return
120
	}
121
	self.md5sum = md5sum
122
	return
123
}
124

125
func fetchRemote(requestRemote func() ([]byte, error)) (data, md5sum []byte, err error) {
126
	data, err = requestRemote()
127
	if err != nil {
128
		err = errors.Info(err, "io.ReadAll")
129
		return
130
	}
131
	md5sum = calcMD5Sum(data)
132

133
	return
134
}
135

136
func StartReload(cfg *ReloadConf, reload func(data []byte) error) (err error) {
137
	err = cfg.reload(reload)
138
	if err != nil {
139
		log.LogError("cfg.reload:", cfg.ConfName, errors.Detail(err))
140
		return
141
	}
142

143
	if cfg.ReloadSec == 0 {
144
		return
145
	}
146
	go func() {
147
		dur := time.Duration(cfg.ReloadSec) * time.Second
148
		for range time.Tick(dur) {
149
			err := cfg.reload(reload)
150
			if err != nil {
151
				log.LogError("cfg.reload:", cfg.ConfName, errors.Detail(err))
152
			}
153
		}
154
	}()
155
	return
156
}
157

158
func calcMD5Sum(b []byte) []byte {
159
	h := md5.New()
160
	h.Write(b)
161
	return h.Sum(nil)
162
}
163

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.