zzm.go 13 KB

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