123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package middleware
- import (
- "fmt"
- "os"
- "path/filepath"
- "regexp"
- "sort"
- "xg_dba/internal/models"
- "github.com/mitchellh/mapstructure"
- "github.com/spf13/viper"
- )
- // InitCache 初始化缓存,从指定目录中读取 TOML 文件内容并存储到 packageModels 映射中。
- func InitCache(folderPath string) {
- packageModels := make(map[string]models.Cache)
- err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if info.IsDir() {
- listenFilePath := filepath.Join(path, "listen.toml")
- var connectInfo models.ConnectInfo
- var systemMetaInfo models.SystemMetaInfo
- // 如果 listen.toml 文件存在,解析它到 connectInfo 结构体中
- if fileExists(listenFilePath) {
- if err := parseTomlFile(listenFilePath, &connectInfo); err != nil {
- return err
- }
- }
- // 获取目录中最新的 os_info.toml 文件
- latestOsInfoFilePath, err := getLatestOsInfoFile(path)
- if err != nil {
- return err
- }
- // 如果找到最新的 os_info.toml 文件,解析它到 systemMetaInfo 结构体中
- if latestOsInfoFilePath != "" {
- if err := parseTomlFile(latestOsInfoFilePath, &systemMetaInfo); err != nil {
- return err
- }
- }
- // 使用主机地址作为键,将解析的信息存储到 packageModels 映射中
- host := connectInfo.Ssh.Host
- if host != "" {
- packageModels[host] = models.Cache{
- ConnectInfo: connectInfo,
- SystemMetaInfo: systemMetaInfo,
- }
- }
- }
- return nil
- })
- if err != nil {
- fmt.Printf("遍历路径 %q 时出错: %v\n", folderPath, err)
- return
- }
- // 打印每个主机的缓存数据
- for host, cache := range packageModels {
- fmt.Printf("主机: %s, 缓存: %+v\n", host, cache)
- }
- }
- // fileExists 检查给定路径的文件是否存在。
- func fileExists(filename string) bool {
- info, err := os.Stat(filename)
- if os.IsNotExist(err) {
- return false
- }
- return !info.IsDir()
- }
- // parseTomlFile 使用 viper 解析 TOML 文件到提供的结构体中。
- func parseTomlFile(filePath string, v interface{}) error {
- // 为了防止 viper 的全局状态干扰解析结果,使用新的 viper 实例
- vp := viper.New()
- vp.SetConfigFile(filePath)
- vp.SetConfigType("toml")
- if err := vp.ReadInConfig(); err != nil {
- return err
- }
- // 使用 `vp.AllSettings()` 将配置映射到提供的结构体
- settings := vp.AllSettings()
- if err := decodeSettings(settings, v); err != nil {
- return err
- }
- return nil
- }
- // decodeSettings 将 viper 的设置映射解码到目标结构体。
- func decodeSettings(settings map[string]interface{}, v interface{}) error {
- decoderConfig := &mapstructure.DecoderConfig{
- Result: v,
- TagName: "toml",
- WeaklyTypedInput: true,
- }
- decoder, err := mapstructure.NewDecoder(decoderConfig)
- if err != nil {
- return err
- }
- return decoder.Decode(settings)
- }
- // getLatestOsInfoFile 在给定目录中查找最新的 os_info TOML 文件。
- // 它查找匹配模式 "os_info_<timestamp>.toml" 的文件,并返回最新的一个。
- func getLatestOsInfoFile(dirPath string) (string, error) {
- pattern := regexp.MustCompile(`^os_info(?:_\d{8}_\d{6})?\.toml$`)
- files, err := os.ReadDir(dirPath)
- if err != nil {
- return "", err
- }
- var matchingFiles []string
- for _, file := range files {
- if !file.IsDir() && pattern.MatchString(file.Name()) {
- matchingFiles = append(matchingFiles, filepath.Join(dirPath, file.Name()))
- }
- }
- // 如果没有找到匹配的文件,返回空字符串
- if len(matchingFiles) == 0 {
- return "", nil
- }
- // 将匹配的文件按降序排序,以获取最新的文件
- sort.Slice(matchingFiles, func(i, j int) bool {
- return matchingFiles[i] > matchingFiles[j]
- })
- return matchingFiles[0], nil
- }
|