gitee.com/curryzheng/dm@v0.0.1/zzn.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 6 package dm 7 8 import ( 9 "bufio" 10 "gitee.com/curryzheng/dm/util" 11 "io" 12 "os" 13 "runtime" 14 "strconv" 15 "strings" 16 ) 17 18 var LogDirDef, _ = os.Getwd() 19 20 var StatDirDef, _ = os.Getwd() 21 22 const ( 23 DEFAULT_PORT int32 = 5236 24 25 //log level 26 LOG_OFF int = 0 27 28 LOG_ERROR int = 1 29 30 LOG_WARN int = 2 31 32 LOG_SQL int = 3 33 34 LOG_INFO int = 4 35 36 LOG_DEBUG int = 5 37 38 LOG_ALL int = 9 39 40 //stat 41 STAT_SQL_REMOVE_LATEST int = 0 42 43 STAT_SQL_REMOVE_OLDEST int = 1 44 45 // 编码字符集 46 ENCODING_UTF8 string = "UTF-8" 47 48 ENCODING_EUCKR string = "EUC-KR" 49 50 ENCODING_GB18030 string = "GB18030" 51 52 DbAliveCheckFreqDef = 0 53 54 LocaleDef = 0 55 56 // log 57 LogLevelDef = LOG_OFF // 日志级别:off, error, warn, sql, info, all 58 59 LogFlushFreqDef = 10 // 日志刷盘时间s (>=0) 60 61 LogFlushQueueSizeDef = 100 //日志队列大小 62 63 LogBufferSizeDef = 32 * 1024 // 日志缓冲区大小 (>0) 64 65 // stat 66 StatEnableDef = false // 67 68 StatFlushFreqDef = 3 // 日志刷盘时间s (>=0) 69 70 StatSlowSqlCountDef = 100 // 慢sql top行数,(0-1000) 71 72 StatHighFreqSqlCountDef = 100 // 高频sql top行数, (0-1000) 73 74 StatSqlMaxCountDef = 100000 // sql 统计最大值(0-100000) 75 76 StatSqlRemoveModeDef = STAT_SQL_REMOVE_LATEST // 记录sql数超过最大值时,sql淘汰方式 77 ) 78 79 var ( 80 DbAliveCheckFreq = DbAliveCheckFreqDef 81 82 Locale = LocaleDef // 0:简体中文 1:英文 2:繁体中文 83 84 // log 85 LogLevel = LogLevelDef // 日志级别:off, error, warn, sql, info, all 86 87 LogDir = LogDirDef 88 89 LogFlushFreq = LogFlushFreqDef // 日志刷盘时间s (>=0) 90 91 LogFlushQueueSize = LogFlushQueueSizeDef 92 93 LogBufferSize = LogBufferSizeDef // 日志缓冲区大小 (>0) 94 95 // stat 96 StatEnable = StatEnableDef // 97 98 StatDir = StatDirDef // jdbc工作目录,所有生成的文件都在该目录下 99 100 StatFlushFreq = StatFlushFreqDef // 日志刷盘时间s (>=0) 101 102 StatSlowSqlCount = StatSlowSqlCountDef // 慢sql top行数,(0-1000) 103 104 StatHighFreqSqlCount = StatHighFreqSqlCountDef // 高频sql top行数, (0-1000) 105 106 StatSqlMaxCount = StatSqlMaxCountDef // sql 统计最大值(0-100000) 107 108 StatSqlRemoveMode = StatSqlRemoveModeDef // 记录sql数超过最大值时,sql淘汰方式 109 110 /*---------------------------------------------------------------*/ 111 ServerGroupMap = make(map[string]*epGroup) 112 113 GlobalProperties = NewProperties() 114 ) 115 116 // filePath: dm_svc.conf 文件路径 117 func load(filePath string) { 118 if filePath == "" { 119 switch runtime.GOOS { 120 case "windows": 121 filePath = os.Getenv("SystemRoot") + "\\system32\\dm_svc.conf" 122 case "linux": 123 filePath = "/etc/dm_svc.conf" 124 default: 125 return 126 } 127 } 128 file, err := os.Open(filePath) 129 defer file.Close() 130 if err != nil { 131 return 132 } 133 fileReader := bufio.NewReader(file) 134 135 // GlobalProperties = NewProperties() 136 var groupProps *Properties 137 var line string //dm_svc.conf读取到的一行 138 139 for line, err = fileReader.ReadString('\n'); line != "" && (err == nil || err == io.EOF); line, err = fileReader.ReadString('\n') { 140 // 去除#标记的注释 141 if notesIndex := strings.IndexByte(line, '#'); notesIndex != -1 { 142 line = line[:notesIndex] 143 } 144 // 去除前后多余的空格 145 line = strings.TrimSpace(line) 146 if line == "" { 147 continue 148 } 149 150 if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { 151 groupName := strings.ToLower(line[1 : len(line)-1]) 152 dbGroup, ok := ServerGroupMap[groupName] 153 if groupName == "" || !ok { 154 continue 155 } 156 groupProps = dbGroup.props 157 if groupProps.IsNil() { 158 groupProps = NewProperties() 159 groupProps.SetProperties(GlobalProperties) 160 dbGroup.props = groupProps 161 } 162 163 } else { 164 cfgInfo := strings.Split(line, "=") 165 if len(cfgInfo) < 2 { 166 continue 167 } 168 key := strings.TrimSpace(cfgInfo[0]) 169 value := strings.TrimSpace(cfgInfo[1]) 170 if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") { 171 value = strings.TrimSpace(value[1 : len(value)-1]) 172 } 173 if key == "" || value == "" { 174 continue 175 } 176 // 区分属性是全局的还是组的 177 var success bool 178 if groupProps.IsNil() { 179 success = SetServerGroupProperties(GlobalProperties, key, value) 180 } else { 181 success = SetServerGroupProperties(groupProps, key, value) 182 } 183 if !success { 184 var serverGroup = parseServerName(key, value) 185 if serverGroup != nil { 186 serverGroup.props = NewProperties() 187 serverGroup.props.SetProperties(GlobalProperties) 188 ServerGroupMap[strings.ToLower(key)] = serverGroup 189 } 190 } 191 } 192 } 193 } 194 195 func SetServerGroupProperties(props *Properties, key string, value string) bool { 196 if util.StringUtil.EqualsIgnoreCase(key, "ADDRESS_REMAP") { 197 tmp := props.GetString(AddressRemapKey, "") 198 props.Set(AddressRemapKey, tmp+"("+value+")") 199 } else if util.StringUtil.EqualsIgnoreCase(key, "ALWAYS_ALLOW_COMMIT") { 200 props.Set(AlwayseAllowCommitKey, value) 201 } else if util.StringUtil.EqualsIgnoreCase(key, "APP_NAME") { 202 props.Set(AppNameKey, value) 203 } else if util.StringUtil.EqualsIgnoreCase(key, "AUTO_COMMIT") { 204 props.Set(AutoCommitKey, value) 205 } else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_ALLOW_MAX_ERRORS") { 206 props.Set(BatchAllowMaxErrorsKey, value) 207 } else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_CONTINUE_ON_ERROR") || 208 util.StringUtil.EqualsIgnoreCase(key, "CONTINUE_BATCH_ON_ERROR") { 209 props.Set(ContinueBatchOnErrorKey, value) 210 } else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_NOT_ON_CALL") { 211 props.Set(BatchNotOnCallKey, value) 212 } else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_TYPE") { 213 props.Set(BatchTypeKey, value) 214 } else if util.StringUtil.EqualsIgnoreCase(key, "BUF_PREFETCH") { 215 props.Set(BufPrefetchKey, value) 216 } else if util.StringUtil.EqualsIgnoreCase(key, "CIPHER_PATH") { 217 props.Set(CipherPathKey, value) 218 } else if util.StringUtil.EqualsIgnoreCase(key, "CLUSTER") { 219 props.Set(ClusterKey, value) 220 } else if util.StringUtil.EqualsIgnoreCase(key, "COLUMN_NAME_UPPER_CASE") { 221 props.Set(ColumnNameUpperCaseKey, value) 222 } else if util.StringUtil.EqualsIgnoreCase(key, "COLUMN_NAME_CASE") { 223 props.Set(ColumnNameCaseKey, value) 224 } else if util.StringUtil.EqualsIgnoreCase(key, "COMPATIBLE_MODE") { 225 props.Set(CompatibleModeKey, value) 226 } else if util.StringUtil.EqualsIgnoreCase(key, "COMPRESS") || 227 util.StringUtil.EqualsIgnoreCase(key, "COMPRESS_MSG") { 228 props.Set(CompressKey, value) 229 } else if util.StringUtil.EqualsIgnoreCase(key, "COMPRESS_ID") { 230 props.Set(CompressIdKey, value) 231 } else if util.StringUtil.EqualsIgnoreCase(key, "CONNECT_TIMEOUT") { 232 props.Set(ConnectTimeoutKey, value) 233 } else if util.StringUtil.EqualsIgnoreCase(key, "DO_SWITCH") || 234 util.StringUtil.EqualsIgnoreCase(key, "AUTO_RECONNECT") { 235 props.Set(DoSwitchKey, value) 236 } else if util.StringUtil.EqualsIgnoreCase(key, "ENABLE_RS_CACHE") { 237 props.Set(EnRsCacheKey, value) 238 } else if util.StringUtil.EqualsIgnoreCase(key, "EP_SELECTION") { 239 props.Set(EpSelectorKey, value) 240 } else if util.StringUtil.EqualsIgnoreCase(key, "ESCAPE_PROCESS") { 241 props.Set(EscapeProcessKey, value) 242 } else if util.StringUtil.EqualsIgnoreCase(key, "IS_BDTA_RS") { 243 props.Set(IsBdtaRSKey, value) 244 } else if util.StringUtil.EqualsIgnoreCase(key, "KEY_WORDS") || 245 util.StringUtil.EqualsIgnoreCase(key, "KEYWORDS") { 246 props.Set(KeywordsKey, value) 247 } else if util.StringUtil.EqualsIgnoreCase(key, "LANGUAGE") { 248 props.Set(LanguageKey, value) 249 } else if util.StringUtil.EqualsIgnoreCase(key, "LOB_MODE") { 250 props.Set(LobModeKey, value) 251 } else if util.StringUtil.EqualsIgnoreCase(key, "LOG_DIR") { 252 props.Set(LogDirKey, value) 253 } else if util.StringUtil.EqualsIgnoreCase(key, "LOG_FLUSH_FREQ") { 254 props.Set(LogFlushFreqKey, value) 255 } else if util.StringUtil.EqualsIgnoreCase(key, "LOG_LEVEL") { 256 props.Set(LogLevelKey, value) 257 } else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_DSC_CTRL") { 258 props.Set(LoginDscCtrlKey, value) 259 } else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_ENCRYPT") { 260 props.Set(LoginEncryptKey, value) 261 } else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_MODE") { 262 props.Set(LoginModeKey, value) 263 } else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_STATUS") { 264 props.Set(LoginStatusKey, value) 265 } else if util.StringUtil.EqualsIgnoreCase(key, "MAX_ROWS") { 266 props.Set(MaxRowsKey, value) 267 } else if util.StringUtil.EqualsIgnoreCase(key, "MPP_LOCAL") { 268 props.Set(MppLocalKey, value) 269 } else if util.StringUtil.EqualsIgnoreCase(key, "OS_NAME") { 270 props.Set(OsNameKey, value) 271 } else if util.StringUtil.EqualsIgnoreCase(key, "RS_CACHE_SIZE") { 272 props.Set(RsCacheSizeKey, value) 273 } else if util.StringUtil.EqualsIgnoreCase(key, "RS_REFRESH_FREQ") { 274 props.Set(RsRefreshFreqKey, value) 275 } else if util.StringUtil.EqualsIgnoreCase(key, "RW_HA") { 276 props.Set(RwHAKey, value) 277 } else if util.StringUtil.EqualsIgnoreCase(key, "RW_IGNORE_SQL") { 278 props.Set(RwIgnoreSqlKey, value) 279 } else if util.StringUtil.EqualsIgnoreCase(key, "RW_PERCENT") { 280 props.Set(RwPercentKey, value) 281 } else if util.StringUtil.EqualsIgnoreCase(key, "RW_SEPARATE") { 282 props.Set(RwSeparateKey, value) 283 } else if util.StringUtil.EqualsIgnoreCase(key, "RW_STANDBY_RECOVER_TIME") { 284 props.Set(RwStandbyRecoverTimeKey, value) 285 } else if util.StringUtil.EqualsIgnoreCase(key, "SCHEMA") { 286 props.Set(SchemaKey, value) 287 } else if util.StringUtil.EqualsIgnoreCase(key, "SESS_ENCODE") { 288 if IsSupportedCharset(value) { 289 props.Set("sessEncode", value) 290 } 291 } else if util.StringUtil.EqualsIgnoreCase(key, "SESSION_TIMEOUT") { 292 props.Set(SessionTimeoutKey, value) 293 } else if util.StringUtil.EqualsIgnoreCase(key, "SOCKET_TIMEOUT") { 294 props.Set(SocketTimeoutKey, value) 295 } else if util.StringUtil.EqualsIgnoreCase(key, "SSL_FILES_PATH") { 296 props.Set(SslFilesPathKey, value) 297 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_DIR") { 298 props.Set(StatDirKey, value) 299 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_ENABLE") { 300 props.Set(StatEnableKey, value) 301 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_FLUSH_FREQ") { 302 props.Set(StatFlushFreqKey, value) 303 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_HIGH_FREQ_SQL_COUNT") { 304 props.Set(StatHighFreqSqlCountKey, value) 305 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SLOW_SQL_COUNT") { 306 props.Set(StatSlowSqlCountKey, value) 307 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SQL_MAX_COUNT") { 308 props.Set(StatSqlMaxCountKey, value) 309 } else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SQL_REMOVE_MODE") { 310 props.Set(StatSqlRemoveModeKey, value) 311 } else if util.StringUtil.EqualsIgnoreCase(key, "SWITCH_INTERVAL") { 312 props.Set(SwitchIntervalKey, value) 313 } else if util.StringUtil.EqualsIgnoreCase(key, "SWITCH_TIME") || 314 util.StringUtil.EqualsIgnoreCase(key, "SWITCH_TIMES") { 315 props.Set(SwitchTimesKey, value) 316 } else if util.StringUtil.EqualsIgnoreCase(key, "TIME_ZONE") { 317 props.Set(TimeZoneKey, value) 318 props.Set("localTimezone", value) 319 } else if util.StringUtil.EqualsIgnoreCase(key, "USER_REMAP") { 320 tmp := props.GetString(UserRemapKey, "") 321 props.Set(UserRemapKey, tmp+"("+value+")") 322 } else { 323 return false 324 } 325 return true 326 } 327 328 func parseServerName(name string, value string) *epGroup { 329 values := strings.Split(value, ",") 330 331 var tmpVals []string 332 var tmpName string 333 var tmpPort int 334 var svrList = make([]*ep, 0, len(values)) 335 336 for _, v := range values { 337 338 var tmp *ep 339 // 先查找IPV6,以[]包括 340 begin := strings.IndexByte(v, '[') 341 end := -1 342 if begin != -1 { 343 end = strings.IndexByte(v[begin:], ']') 344 } 345 if end != -1 { 346 tmpName = v[begin+1 : end] 347 348 // port 349 if portIndex := strings.IndexByte(v[end:], ':'); portIndex != -1 { 350 tmpPort, _ = strconv.Atoi(strings.TrimSpace(v[portIndex+1:])) 351 } else { 352 tmpPort = int(DEFAULT_PORT) 353 } 354 tmp = newEP(tmpName, int32(tmpPort)) 355 svrList = append(svrList, tmp) 356 continue 357 } 358 // IPV4 359 tmpVals = strings.Split(v, ":") 360 tmpName = strings.TrimSpace(tmpVals[0]) 361 if len(tmpVals) >= 2 { 362 tmpPort, _ = strconv.Atoi(tmpVals[1]) 363 } else { 364 tmpPort = int(DEFAULT_PORT) 365 } 366 tmp = newEP(tmpName, int32(tmpPort)) 367 svrList = append(svrList, tmp) 368 } 369 370 if len(svrList) == 0 { 371 return nil 372 } 373 return newEPGroup(name, svrList) 374 } 375 376 func setDriverAttributes(props *Properties) { 377 if props == nil || props.Len() == 0 { 378 return 379 } 380 381 parseLanguage(props.GetString(LanguageKey, "cn")) 382 DbAliveCheckFreq = props.GetInt(DbAliveCheckFreqKey, DbAliveCheckFreqDef, 1, int(INT32_MAX)) 383 384 //// log 385 //LogLevel = ParseLogLevel(props) 386 //LogDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef)) 387 //LogBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX)) 388 //LogFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX)) 389 //LogFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX)) 390 // 391 //// stat 392 //StatEnable = props.GetBool(StatEnableKey, StatEnableDef) 393 //StatDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef)) 394 //StatFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX)) 395 //StatHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000) 396 //StatSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000) 397 //StatSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000) 398 //parseStatSqlRemoveMode(props) 399 } 400 401 func parseLanguage(value string) { 402 if util.StringUtil.EqualsIgnoreCase("cn", value) { 403 Locale = 0 404 } else if util.StringUtil.EqualsIgnoreCase("en", value) { 405 Locale = 1 406 } 407 } 408 409 func IsSupportedCharset(charset string) bool { 410 if util.StringUtil.EqualsIgnoreCase(ENCODING_UTF8, charset) || util.StringUtil.EqualsIgnoreCase(ENCODING_GB18030, charset) || util.StringUtil.EqualsIgnoreCase(ENCODING_EUCKR, charset) { 411 return true 412 } 413 return false 414 } 415 416 func ParseLogLevel(props *Properties) int { 417 logLevel := LOG_OFF 418 value := props.GetString(LogLevelKey, "") 419 if value != "" && !util.StringUtil.IsDigit(value) { 420 if util.StringUtil.EqualsIgnoreCase("debug", value) { 421 logLevel = LOG_DEBUG 422 } else if util.StringUtil.EqualsIgnoreCase("info", value) { 423 logLevel = LOG_INFO 424 } else if util.StringUtil.EqualsIgnoreCase("sql", value) { 425 logLevel = LOG_SQL 426 } else if util.StringUtil.EqualsIgnoreCase("warn", value) { 427 logLevel = LOG_WARN 428 } else if util.StringUtil.EqualsIgnoreCase("error", value) { 429 logLevel = LOG_ERROR 430 } else if util.StringUtil.EqualsIgnoreCase("off", value) { 431 logLevel = LOG_OFF 432 } else if util.StringUtil.EqualsIgnoreCase("all", value) { 433 logLevel = LOG_ALL 434 } 435 } else { 436 logLevel = props.GetInt(LogLevelKey, logLevel, LOG_OFF, LOG_INFO) 437 } 438 439 return logLevel 440 }