gitee.com/curryzheng/dm@v0.0.1/zd.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_284(), 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 } 149 150 if bc.rwSeparate { 151 filters = append(filters, &rwFilter{}) 152 f.rwInfo = newRwInfo() 153 } 154 } else if props != nil { 155 if ParseLogLevel(props) != LOG_OFF { 156 filters = append(filters, &logFilter{}) 157 f.logInfo = &logInfo{logRecord: new(LogRecord)} 158 runLog() 159 } 160 161 if props.GetBool("statEnable", StatEnable) { 162 filters = append(filters, &statFilter{}) 163 f.statInfo = newStatInfo() 164 goStatMu.Lock() 165 if goStat == nil { 166 goStat = newGoStat(1000) 167 } 168 goStatMu.Unlock() 169 runStat() 170 } 171 172 if props.GetInt(DoSwitchKey, int(DO_SWITCH_OFF), 0, 2) != int(DO_SWITCH_OFF) { 173 filters = append(filters, &reconnectFilter{}) 174 f.recoverInfo = newRecoverInfo() 175 } 176 177 if props.GetBool("rwSeparate", false) { 178 filters = append(filters, &rwFilter{}) 179 f.rwInfo = newRwInfo() 180 } 181 } 182 183 f.filterChain = newFilterChain(filters) 184 } 185 186 func (f *filterable) resetFilterable(src *filterable) { 187 f.filterChain = src.filterChain 188 f.logInfo = src.logInfo 189 f.rwInfo = src.rwInfo 190 f.statInfo = src.statInfo 191 } 192 193 func (f filterable) getID() int64 { 194 if f.objId < 0 { 195 f.objId = f.idGenerator.incrementAndGet() 196 } 197 return f.objId 198 } 199 200 type logInfo struct { 201 logRecord *LogRecord 202 lastExecuteStartNano time.Time 203 } 204 205 type rwInfo struct { 206 distribute RWSiteEnum 207 208 rwCounter *rwCounter 209 210 connStandby *DmConnection 211 212 connCurrent *DmConnection 213 214 tryRecoverTs int64 215 216 stmtStandby *DmStatement 217 218 stmtCurrent *DmStatement 219 220 readOnly bool 221 } 222 223 func newRwInfo() *rwInfo { 224 rwInfo := new(rwInfo) 225 rwInfo.distribute = PRIMARY 226 rwInfo.readOnly = true 227 return rwInfo 228 } 229 230 func (rwi *rwInfo) cleanup() { 231 rwi.distribute = PRIMARY 232 rwi.rwCounter = nil 233 rwi.connStandby = nil 234 rwi.connCurrent = nil 235 rwi.stmtStandby = nil 236 rwi.stmtCurrent = nil 237 } 238 239 func (rwi *rwInfo) toPrimary() RWSiteEnum { 240 if rwi.distribute != PRIMARY { 241 242 rwi.rwCounter.countPrimary() 243 } 244 rwi.distribute = PRIMARY 245 return rwi.distribute 246 } 247 248 func (rwi *rwInfo) toAny() RWSiteEnum { 249 250 rwi.distribute = rwi.rwCounter.count(ANYSITE, rwi.connStandby) 251 return rwi.distribute 252 } 253 254 type recoverInfo struct { 255 checkEpRecoverTs int64 256 } 257 258 func newRecoverInfo() *recoverInfo { 259 recoverInfo := new(recoverInfo) 260 recoverInfo.checkEpRecoverTs = 0 261 return recoverInfo 262 } 263 264 type statInfo struct { 265 constructNano int64 266 267 connStat *connectionStat 268 269 lastExecuteStartNano int64 270 271 lastExecuteTimeNano int64 272 273 lastExecuteType ExecuteTypeEnum 274 275 firstResultSet bool 276 277 lastExecuteSql string 278 279 sqlStat *sqlStat 280 281 sql string 282 283 cursorIndex int 284 285 closeCount int 286 287 readStringLength int64 288 289 readBytesLength int64 290 291 openInputStreamCount int 292 293 openReaderCount int 294 } 295 296 var ( 297 goStatMu sync.RWMutex 298 goStat *GoStat 299 ) 300 301 func newStatInfo() *statInfo { 302 si := new(statInfo) 303 return si 304 } 305 func (si *statInfo) init(conn *DmConnection) { 306 si.connStat = goStat.createConnStat(conn) 307 } 308 309 func (si *statInfo) setConstructNano() { 310 si.constructNano = time.Now().UnixNano() 311 } 312 313 func (si *statInfo) getConstructNano() int64 { 314 return si.constructNano 315 } 316 317 func (si *statInfo) getConnStat() *connectionStat { 318 return si.connStat 319 } 320 321 func (si *statInfo) getLastExecuteStartNano() int64 { 322 return si.lastExecuteStartNano 323 } 324 325 func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) { 326 si.lastExecuteStartNano = lastExecuteStartNano 327 } 328 329 func (si *statInfo) getLastExecuteTimeNano() int64 { 330 return si.lastExecuteTimeNano 331 } 332 333 func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) { 334 si.lastExecuteTimeNano = lastExecuteTimeNano 335 } 336 337 func (si *statInfo) getLastExecuteType() ExecuteTypeEnum { 338 return si.lastExecuteType 339 } 340 341 func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) { 342 si.lastExecuteType = lastExecuteType 343 } 344 345 func (si *statInfo) isFirstResultSet() bool { 346 return si.firstResultSet 347 } 348 349 func (si *statInfo) setFirstResultSet(firstResultSet bool) { 350 si.firstResultSet = firstResultSet 351 } 352 353 func (si *statInfo) getLastExecuteSql() string { 354 return si.lastExecuteSql 355 } 356 357 func (si *statInfo) setLastExecuteSql(lastExecuteSql string) { 358 si.lastExecuteSql = lastExecuteSql 359 } 360 361 func (si *statInfo) getSqlStat() *sqlStat { 362 return si.sqlStat 363 } 364 365 func (si *statInfo) setSqlStat(sqlStat *sqlStat) { 366 si.sqlStat = sqlStat 367 } 368 369 func (si *statInfo) setConnStat(connStat *connectionStat) { 370 si.connStat = connStat 371 } 372 373 func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) { 374 si.constructNano = constructNano 375 } 376 377 func (si *statInfo) afterExecute(nanoSpan int64) { 378 si.lastExecuteTimeNano = nanoSpan 379 } 380 381 func (si *statInfo) beforeExecute() { 382 si.lastExecuteStartNano = time.Now().UnixNano() 383 } 384 385 func (si *statInfo) getSql() string { 386 return si.sql 387 } 388 389 func (si *statInfo) setSql(sql string) { 390 si.sql = sql 391 } 392 393 func (si *statInfo) getCursorIndex() int { 394 return si.cursorIndex 395 } 396 397 func (si *statInfo) setCursorIndex(cursorIndex int) { 398 si.cursorIndex = cursorIndex 399 } 400 401 func (si *statInfo) getCloseCount() int { 402 return si.closeCount 403 } 404 405 func (si *statInfo) setCloseCount(closeCount int) { 406 si.closeCount = closeCount 407 } 408 409 func (si *statInfo) getReadStringLength() int64 { 410 return si.readStringLength 411 } 412 413 func (si *statInfo) setReadStringLength(readStringLength int64) { 414 si.readStringLength = readStringLength 415 } 416 417 func (si *statInfo) getReadBytesLength() int64 { 418 return si.readBytesLength 419 } 420 421 func (si *statInfo) setReadBytesLength(readBytesLength int64) { 422 si.readBytesLength = readBytesLength 423 } 424 425 func (si *statInfo) getOpenInputStreamCount() int { 426 return si.openInputStreamCount 427 } 428 429 func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) { 430 si.openInputStreamCount = openInputStreamCount 431 } 432 433 func (si *statInfo) getOpenReaderCount() int { 434 return si.openReaderCount 435 } 436 437 func (si *statInfo) setOpenReaderCount(openReaderCount int) { 438 si.openReaderCount = openReaderCount 439 } 440 441 func (si *statInfo) incrementCloseCount() { 442 si.closeCount++ 443 }