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