github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/config/dbconfig/config.go (about)

     1  // Copyright 2022 PingCAP, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dbconfig
    15  
    16  import (
    17  	"bytes"
    18  	"encoding/json"
    19  	"strings"
    20  
    21  	"github.com/BurntSushi/toml"
    22  	"github.com/pingcap/tiflow/dm/config/security"
    23  	"github.com/pingcap/tiflow/dm/pkg/log"
    24  	"github.com/pingcap/tiflow/dm/pkg/terror"
    25  	"github.com/pingcap/tiflow/dm/pkg/utils"
    26  	"go.uber.org/zap"
    27  )
    28  
    29  // AdjustDBTimeZone force adjust session `time_zone`.
    30  func AdjustDBTimeZone(config *DBConfig, timeZone string) {
    31  	for k, v := range config.Session {
    32  		if strings.ToLower(k) == "time_zone" {
    33  			if v != timeZone {
    34  				log.L().Warn("session variable 'time_zone' is overwritten by task config's timezone",
    35  					zap.String("time_zone", config.Session[k]))
    36  				config.Session[k] = timeZone
    37  			}
    38  			return
    39  		}
    40  	}
    41  	if config.Session == nil {
    42  		config.Session = make(map[string]string, 1)
    43  	}
    44  	config.Session["time_zone"] = timeZone
    45  }
    46  
    47  // RawDBConfig contains some low level database config.
    48  type RawDBConfig struct {
    49  	MaxIdleConns int
    50  	ReadTimeout  string
    51  	WriteTimeout string
    52  }
    53  
    54  // SetReadTimeout set readTimeout for raw database config.
    55  func (c *RawDBConfig) SetReadTimeout(readTimeout string) *RawDBConfig {
    56  	c.ReadTimeout = readTimeout
    57  	return c
    58  }
    59  
    60  // SetWriteTimeout set writeTimeout for raw database config.
    61  func (c *RawDBConfig) SetWriteTimeout(writeTimeout string) *RawDBConfig {
    62  	c.WriteTimeout = writeTimeout
    63  	return c
    64  }
    65  
    66  // SetMaxIdleConns set maxIdleConns for raw database config
    67  // set value <= 0 then no idle connections are retained.
    68  // set value > 0 then `value` idle connections are retained.
    69  func (c *RawDBConfig) SetMaxIdleConns(value int) *RawDBConfig {
    70  	c.MaxIdleConns = value
    71  	return c
    72  }
    73  
    74  // DBConfig is the DB configuration.
    75  type DBConfig struct {
    76  	Host     string `toml:"host" json:"host" yaml:"host"`
    77  	Port     int    `toml:"port" json:"port" yaml:"port"`
    78  	User     string `toml:"user" json:"user" yaml:"user"`
    79  	Password string `toml:"password" json:"-" yaml:"password"` // omit it for privacy
    80  	// deprecated, mysql driver could automatically fetch this value
    81  	MaxAllowedPacket *int              `toml:"max-allowed-packet" json:"max-allowed-packet" yaml:"max-allowed-packet"`
    82  	Session          map[string]string `toml:"session" json:"session" yaml:"session"`
    83  
    84  	// security config
    85  	Security *security.Security `toml:"security" json:"security" yaml:"security"`
    86  
    87  	RawDBCfg *RawDBConfig `toml:"-" json:"-" yaml:"-"`
    88  	Net      string       `toml:"-" json:"-" yaml:"-"`
    89  }
    90  
    91  var defaultMaxIdleConns = 2
    92  
    93  // DefaultRawDBConfig returns a default raw database config.
    94  func DefaultRawDBConfig() *RawDBConfig {
    95  	return &RawDBConfig{
    96  		MaxIdleConns: defaultMaxIdleConns,
    97  	}
    98  }
    99  
   100  func (db *DBConfig) String() string {
   101  	cfg, err := json.Marshal(db)
   102  	if err != nil {
   103  		log.L().Error("fail to marshal config to json", log.ShortError(err))
   104  	}
   105  	return string(cfg)
   106  }
   107  
   108  // Toml returns TOML format representation of config.
   109  func (db *DBConfig) Toml() (string, error) {
   110  	var b bytes.Buffer
   111  	enc := toml.NewEncoder(&b)
   112  	if err := enc.Encode(db); err != nil {
   113  		return "", terror.ErrConfigTomlTransform.Delegate(err, "encode db config to toml")
   114  	}
   115  	return b.String(), nil
   116  }
   117  
   118  // Decode loads config from file data.
   119  func (db *DBConfig) Decode(data string) error {
   120  	_, err := toml.Decode(data, db)
   121  	return terror.ErrConfigTomlTransform.Delegate(err, "decode db config")
   122  }
   123  
   124  // Adjust adjusts the config.
   125  func (db *DBConfig) Adjust() {
   126  	if len(db.Password) > 0 {
   127  		db.Password = utils.DecryptOrPlaintext(db.Password)
   128  	}
   129  }
   130  
   131  func (db *DBConfig) AdjustWithTimeZone(timeZone string) {
   132  	if timeZone != "" {
   133  		AdjustDBTimeZone(db, timeZone)
   134  	}
   135  	db.Adjust()
   136  }
   137  
   138  // Clone returns a deep copy of DBConfig. This function only fixes data race when adjusting Session.
   139  func (db *DBConfig) Clone() *DBConfig {
   140  	if db == nil {
   141  		return nil
   142  	}
   143  
   144  	clone := *db
   145  
   146  	if db.MaxAllowedPacket != nil {
   147  		packet := *(db.MaxAllowedPacket)
   148  		clone.MaxAllowedPacket = &packet
   149  	}
   150  
   151  	if db.Session != nil {
   152  		clone.Session = make(map[string]string, len(db.Session))
   153  		for k, v := range db.Session {
   154  			clone.Session[k] = v
   155  		}
   156  	}
   157  
   158  	clone.Security = db.Security.Clone()
   159  
   160  	if db.RawDBCfg != nil {
   161  		dbCfg := *(db.RawDBCfg)
   162  		clone.RawDBCfg = &dbCfg
   163  	}
   164  
   165  	return &clone
   166  }