zzm.go 14 KB

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