gitee.com/chunanyong/dm@v1.8.12/zc.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dm 6 7 import ( 8 "context" 9 "database/sql/driver" 10 "reflect" 11 "sync" 12 "sync/atomic" 13 "time" 14 ) 15 16 type filter interface { 17 DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) 18 DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) 19 20 DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) 21 DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver 22 23 DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) 24 DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) 25 DmConnectionCommit(filterChain *filterChain, c *DmConnection) error 26 DmConnectionRollback(filterChain *filterChain, c *DmConnection) error 27 DmConnectionClose(filterChain *filterChain, c *DmConnection) error 28 DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error 29 DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) 30 DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) 31 DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) 32 DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) 33 DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) 34 DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) 35 DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error 36 DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error 37 38 DmStatementClose(filterChain *filterChain, s *DmStatement) error 39 DmStatementNumInput(filterChain *filterChain, s *DmStatement) int 40 DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) 41 DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) 42 DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) 43 DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) 44 DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error 45 46 DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) 47 DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) 48 49 DmRowsColumns(filterChain *filterChain, r *DmRows) []string 50 DmRowsClose(filterChain *filterChain, r *DmRows) error 51 DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error 52 DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool 53 DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error 54 DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type 55 DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string 56 DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) 57 DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) 58 DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) 59 } 60 61 type IDGenerator int64 62 63 var dmDriverIDGenerator = new(IDGenerator) 64 var dmConntorIDGenerator = new(IDGenerator) 65 var dmConnIDGenerator = new(IDGenerator) 66 var dmStmtIDGenerator = new(IDGenerator) 67 var dmResultIDGenerator = new(IDGenerator) 68 var dmRowsIDGenerator = new(IDGenerator) 69 70 func (g *IDGenerator) incrementAndGet() int64 { 71 return atomic.AddInt64((*int64)(g), 1) 72 } 73 74 type RWSiteEnum int 75 76 const ( 77 PRIMARY RWSiteEnum = iota 78 STANDBY 79 ANYSITE 80 ) 81 82 var ( 83 goMapMu sync.RWMutex 84 goMap = make(map[string]goRun, 2) 85 ) 86 87 type filterable struct { 88 filterChain *filterChain 89 rwInfo *rwInfo 90 logInfo *logInfo 91 recoverInfo *recoverInfo 92 statInfo *statInfo 93 objId int64 94 idGenerator *IDGenerator 95 } 96 97 func runLog() { 98 goMapMu.Lock() 99 _, ok := goMap["log"] 100 if !ok { 101 goMap["log"] = &logWriter{ 102 flushQueue: make(chan []byte, LogFlushQueueSize), 103 date: time.Now().Format("2006-01-02"), 104 logFile: nil, 105 flushFreq: LogFlushFreq, 106 filePath: LogDir, 107 filePrefix: "dm_go", 108 buffer: Dm_build_935(), 109 } 110 go goMap["log"].doRun() 111 } 112 goMapMu.Unlock() 113 } 114 115 func runStat() { 116 goMapMu.Lock() 117 _, ok := goMap["stat"] 118 if !ok { 119 goMap["stat"] = newStatFlusher() 120 go goMap["stat"].doRun() 121 } 122 goMapMu.Unlock() 123 } 124 125 func (f *filterable) createFilterChain(bc *DmConnector, props *Properties) { 126 var filters = make([]filter, 0, 5) 127 128 if bc != nil { 129 if LogLevel != LOG_OFF { 130 filters = append(filters, &logFilter{}) 131 f.logInfo = &logInfo{logRecord: new(LogRecord)} 132 runLog() 133 } 134 135 if StatEnable { 136 filters = append(filters, &statFilter{}) 137 f.statInfo = newStatInfo() 138 goStatMu.Lock() 139 if goStat == nil { 140 goStat = newGoStat(1000) 141 } 142 goStatMu.Unlock() 143 runStat() 144 } 145 146 if bc.doSwitch != DO_SWITCH_OFF { 147 filters = append(filters, &reconnectFilter{}) 148 f.recoverInfo = newRecoverInfo() 149 } 150 151 if bc.rwSeparate { 152 filters = append(filters, &rwFilter{}) 153 f.rwInfo = newRwInfo() 154 } 155 } else if props != nil { 156 if ParseLogLevel(props) != LOG_OFF { 157 filters = append(filters, &logFilter{}) 158 f.logInfo = &logInfo{logRecord: new(LogRecord)} 159 runLog() 160 } 161 162 if props.GetBool("statEnable", StatEnable) { 163 filters = append(filters, &statFilter{}) 164 f.statInfo = newStatInfo() 165 goStatMu.Lock() 166 if goStat == nil { 167 goStat = newGoStat(1000) 168 } 169 goStatMu.Unlock() 170 runStat() 171 } 172 173 if props.GetInt(DoSwitchKey, int(DO_SWITCH_OFF), 0, 2) != int(DO_SWITCH_OFF) { 174 filters = append(filters, &reconnectFilter{}) 175 f.recoverInfo = newRecoverInfo() 176 } 177 178 if props.GetBool("rwSeparate", false) { 179 filters = append(filters, &rwFilter{}) 180 f.rwInfo = newRwInfo() 181 } 182 } 183 184 f.filterChain = newFilterChain(filters) 185 } 186 187 func (f *filterable) resetFilterable(src *filterable) { 188 f.filterChain = src.filterChain 189 f.logInfo = src.logInfo 190 f.rwInfo = src.rwInfo 191 f.statInfo = src.statInfo 192 } 193 194 func (f *filterable) getID() int64 { 195 if f.objId < 0 { 196 f.objId = f.idGenerator.incrementAndGet() 197 } 198 return f.objId 199 } 200 201 type logInfo struct { 202 logRecord *LogRecord 203 lastExecuteStartNano time.Time 204 } 205 206 type rwInfo struct { 207 distribute RWSiteEnum 208 209 rwCounter *rwCounter 210 211 connStandby *DmConnection 212 213 connCurrent *DmConnection 214 215 tryRecoverTs int64 216 217 stmtStandby *DmStatement 218 219 stmtCurrent *DmStatement 220 221 readOnly bool 222 } 223 224 func newRwInfo() *rwInfo { 225 rwInfo := new(rwInfo) 226 rwInfo.distribute = PRIMARY 227 rwInfo.readOnly = true 228 return rwInfo 229 } 230 231 func (rwi *rwInfo) cleanup() { 232 rwi.distribute = PRIMARY 233 rwi.rwCounter = nil 234 rwi.connStandby = nil 235 rwi.connCurrent = nil 236 rwi.stmtStandby = nil 237 rwi.stmtCurrent = nil 238 } 239 240 func (rwi *rwInfo) toPrimary() RWSiteEnum { 241 if rwi.distribute != PRIMARY { 242 243 rwi.rwCounter.countPrimary() 244 } 245 rwi.distribute = PRIMARY 246 return rwi.distribute 247 } 248 249 func (rwi *rwInfo) toAny() RWSiteEnum { 250 251 rwi.distribute = rwi.rwCounter.count(ANYSITE, rwi.connStandby) 252 return rwi.distribute 253 } 254 255 type recoverInfo struct { 256 checkEpRecoverTs int64 257 } 258 259 func newRecoverInfo() *recoverInfo { 260 recoverInfo := new(recoverInfo) 261 recoverInfo.checkEpRecoverTs = 0 262 return recoverInfo 263 } 264 265 type statInfo struct { 266 constructNano int64 267 268 connStat *connectionStat 269 270 lastExecuteStartNano int64 271 272 lastExecuteTimeNano int64 273 274 lastExecuteType ExecuteTypeEnum 275 276 firstResultSet bool 277 278 lastExecuteSql string 279 280 sqlStat *sqlStat 281 282 sql string 283 284 cursorIndex int 285 286 closeCount int 287 288 readStringLength int64 289 290 readBytesLength int64 291 292 openInputStreamCount int 293 294 openReaderCount int 295 } 296 297 var ( 298 goStatMu sync.RWMutex 299 goStat *GoStat 300 ) 301 302 func newStatInfo() *statInfo { 303 si := new(statInfo) 304 return si 305 } 306 func (si *statInfo) init(conn *DmConnection) { 307 si.connStat = goStat.createConnStat(conn) 308 } 309 310 func (si *statInfo) setConstructNano() { 311 si.constructNano = time.Now().UnixNano() 312 } 313 314 func (si *statInfo) getConstructNano() int64 { 315 return si.constructNano 316 } 317 318 func (si *statInfo) getConnStat() *connectionStat { 319 return si.connStat 320 } 321 322 func (si *statInfo) getLastExecuteStartNano() int64 { 323 return si.lastExecuteStartNano 324 } 325 326 func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) { 327 si.lastExecuteStartNano = lastExecuteStartNano 328 } 329 330 func (si *statInfo) getLastExecuteTimeNano() int64 { 331 return si.lastExecuteTimeNano 332 } 333 334 func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) { 335 si.lastExecuteTimeNano = lastExecuteTimeNano 336 } 337 338 func (si *statInfo) getLastExecuteType() ExecuteTypeEnum { 339 return si.lastExecuteType 340 } 341 342 func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) { 343 si.lastExecuteType = lastExecuteType 344 } 345 346 func (si *statInfo) isFirstResultSet() bool { 347 return si.firstResultSet 348 } 349 350 func (si *statInfo) setFirstResultSet(firstResultSet bool) { 351 si.firstResultSet = firstResultSet 352 } 353 354 func (si *statInfo) getLastExecuteSql() string { 355 return si.lastExecuteSql 356 } 357 358 func (si *statInfo) setLastExecuteSql(lastExecuteSql string) { 359 si.lastExecuteSql = lastExecuteSql 360 } 361 362 func (si *statInfo) getSqlStat() *sqlStat { 363 return si.sqlStat 364 } 365 366 func (si *statInfo) setSqlStat(sqlStat *sqlStat) { 367 si.sqlStat = sqlStat 368 } 369 370 func (si *statInfo) setConnStat(connStat *connectionStat) { 371 si.connStat = connStat 372 } 373 374 func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) { 375 si.constructNano = constructNano 376 } 377 378 func (si *statInfo) afterExecute(nanoSpan int64) { 379 si.lastExecuteTimeNano = nanoSpan 380 } 381 382 func (si *statInfo) beforeExecute() { 383 si.lastExecuteStartNano = time.Now().UnixNano() 384 } 385 386 func (si *statInfo) getSql() string { 387 return si.sql 388 } 389 390 func (si *statInfo) setSql(sql string) { 391 si.sql = sql 392 } 393 394 func (si *statInfo) getCursorIndex() int { 395 return si.cursorIndex 396 } 397 398 func (si *statInfo) setCursorIndex(cursorIndex int) { 399 si.cursorIndex = cursorIndex 400 } 401 402 func (si *statInfo) getCloseCount() int { 403 return si.closeCount 404 } 405 406 func (si *statInfo) setCloseCount(closeCount int) { 407 si.closeCount = closeCount 408 } 409 410 func (si *statInfo) getReadStringLength() int64 { 411 return si.readStringLength 412 } 413 414 func (si *statInfo) setReadStringLength(readStringLength int64) { 415 si.readStringLength = readStringLength 416 } 417 418 func (si *statInfo) getReadBytesLength() int64 { 419 return si.readBytesLength 420 } 421 422 func (si *statInfo) setReadBytesLength(readBytesLength int64) { 423 si.readBytesLength = readBytesLength 424 } 425 426 func (si *statInfo) getOpenInputStreamCount() int { 427 return si.openInputStreamCount 428 } 429 430 func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) { 431 si.openInputStreamCount = openInputStreamCount 432 } 433 434 func (si *statInfo) getOpenReaderCount() int { 435 return si.openReaderCount 436 } 437 438 func (si *statInfo) setOpenReaderCount(openReaderCount int) { 439 si.openReaderCount = openReaderCount 440 } 441 442 func (si *statInfo) incrementCloseCount() { 443 si.closeCount++ 444 }