github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/zb.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 ANYOF 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 statInfo *statInfo 92 objId int64 93 idGenerator *IDGenerator 94 } 95 96 func runLog() { 97 goMapMu.Lock() 98 _, ok := goMap["log"] 99 if !ok { 100 goMap["log"] = &logWriter{ 101 flushQueue: make(chan []byte, LogFlushQueueSize), 102 date: time.Now().Format("2006-01-02"), 103 logFile: nil, 104 flushFreq: LogFlushFreq, 105 filePath: LogDir, 106 filePrefix: "dm_go", 107 buffer: Dm_build_879(), 108 } 109 go goMap["log"].doRun() 110 } 111 goMapMu.Unlock() 112 } 113 114 func runStat() { 115 goMapMu.Lock() 116 _, ok := goMap["stat"] 117 if !ok { 118 goMap["stat"] = newStatFlusher() 119 go goMap["stat"].doRun() 120 } 121 goMapMu.Unlock() 122 } 123 124 func (f *filterable) createFilterChain(bc *DmConnector, props *Properties) { 125 var filters = make([]filter, 0, 5) 126 127 if bc != nil { 128 if LogLevel != LOG_OFF { 129 filters = append(filters, &logFilter{}) 130 f.logInfo = &logInfo{logRecord: new(LogRecord)} 131 runLog() 132 } 133 134 if StatEnable { 135 filters = append(filters, &statFilter{}) 136 f.statInfo = newStatInfo() 137 goStatMu.Lock() 138 if goStat == nil { 139 goStat = newGoStat(1000) 140 } 141 goStatMu.Unlock() 142 runStat() 143 } 144 145 if bc.doSwitch { 146 filters = append(filters, &reconnectFilter{}) 147 } 148 149 if bc.rwSeparate { 150 filters = append(filters, &rwFilter{}) 151 f.rwInfo = newRwInfo() 152 } 153 } else if props != nil { 154 if ParseLogLevel(props) != LOG_OFF { 155 filters = append(filters, &logFilter{}) 156 f.logInfo = &logInfo{logRecord: new(LogRecord)} 157 runLog() 158 } 159 160 if props.GetBool("statEnable", StatEnable) { 161 filters = append(filters, &statFilter{}) 162 f.statInfo = newStatInfo() 163 goStatMu.Lock() 164 if goStat == nil { 165 goStat = newGoStat(1000) 166 } 167 goStatMu.Unlock() 168 runStat() 169 } 170 171 if props.GetBool("doSwitch", false) { 172 filters = append(filters, &reconnectFilter{}) 173 } 174 175 if props.GetBool("rwSeparate", false) { 176 filters = append(filters, &rwFilter{}) 177 f.rwInfo = newRwInfo() 178 } 179 } 180 181 f.filterChain = newFilterChain(filters) 182 } 183 184 func (f *filterable) resetFilterable(src *filterable) { 185 f.filterChain = src.filterChain 186 f.logInfo = src.logInfo 187 f.rwInfo = src.rwInfo 188 f.statInfo = src.statInfo 189 } 190 191 func (f filterable) getID() int64 { 192 if f.objId < 0 { 193 f.objId = f.idGenerator.incrementAndGet() 194 } 195 return f.objId 196 } 197 198 type logInfo struct { 199 logRecord *LogRecord 200 lastExecuteStartNano time.Time 201 } 202 203 type rwInfo struct { 204 distribute RWSiteEnum 205 206 rwCounter *rwCounter 207 208 connStandby *DmConnection 209 210 connCurrent *DmConnection 211 212 tryRecoverTs int 213 214 stmtStandby *DmStatement 215 216 stmtCurrent *DmStatement 217 } 218 219 func newRwInfo() *rwInfo { 220 rwInfo := new(rwInfo) 221 rwInfo.distribute = PRIMARY 222 return rwInfo 223 } 224 225 func (rwi *rwInfo) cleanup() { 226 rwi.distribute = PRIMARY 227 rwi.rwCounter = nil 228 rwi.connStandby = nil 229 rwi.connCurrent = nil 230 rwi.stmtStandby = nil 231 rwi.stmtCurrent = nil 232 } 233 234 type statInfo struct { 235 constructNano int64 236 237 connStat *connectionStat 238 239 lastExecuteStartNano int64 240 241 lastExecuteTimeNano int64 242 243 lastExecuteType ExecuteTypeEnum 244 245 firstResultSet bool 246 247 lastExecuteSql string 248 249 sqlStat *sqlStat 250 251 sql string 252 253 cursorIndex int 254 255 closeCount int 256 257 readStringLength int64 258 259 readBytesLength int64 260 261 openInputStreamCount int 262 263 openReaderCount int 264 } 265 266 var ( 267 goStatMu sync.RWMutex 268 goStat *GoStat 269 ) 270 271 func newStatInfo() *statInfo { 272 si := new(statInfo) 273 return si 274 } 275 func (si *statInfo) init(conn *DmConnection) { 276 si.connStat = goStat.createConnStat(conn) 277 } 278 279 func (si *statInfo) setConstructNano() { 280 si.constructNano = time.Now().UnixNano() 281 } 282 283 func (si *statInfo) getConstructNano() int64 { 284 return si.constructNano 285 } 286 287 func (si *statInfo) getConnStat() *connectionStat { 288 return si.connStat 289 } 290 291 func (si *statInfo) getLastExecuteStartNano() int64 { 292 return si.lastExecuteStartNano 293 } 294 295 func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) { 296 si.lastExecuteStartNano = lastExecuteStartNano 297 } 298 299 func (si *statInfo) getLastExecuteTimeNano() int64 { 300 return si.lastExecuteTimeNano 301 } 302 303 func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) { 304 si.lastExecuteTimeNano = lastExecuteTimeNano 305 } 306 307 func (si *statInfo) getLastExecuteType() ExecuteTypeEnum { 308 return si.lastExecuteType 309 } 310 311 func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) { 312 si.lastExecuteType = lastExecuteType 313 } 314 315 func (si *statInfo) isFirstResultSet() bool { 316 return si.firstResultSet 317 } 318 319 func (si *statInfo) setFirstResultSet(firstResultSet bool) { 320 si.firstResultSet = firstResultSet 321 } 322 323 func (si *statInfo) getLastExecuteSql() string { 324 return si.lastExecuteSql 325 } 326 327 func (si *statInfo) setLastExecuteSql(lastExecuteSql string) { 328 si.lastExecuteSql = lastExecuteSql 329 } 330 331 func (si *statInfo) getSqlStat() *sqlStat { 332 return si.sqlStat 333 } 334 335 func (si *statInfo) setSqlStat(sqlStat *sqlStat) { 336 si.sqlStat = sqlStat 337 } 338 339 func (si *statInfo) setConnStat(connStat *connectionStat) { 340 si.connStat = connStat 341 } 342 343 func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) { 344 si.constructNano = constructNano 345 } 346 347 func (si *statInfo) afterExecute(nanoSpan int64) { 348 si.lastExecuteTimeNano = nanoSpan 349 } 350 351 func (si *statInfo) beforeExecute() { 352 si.lastExecuteStartNano = time.Now().UnixNano() 353 } 354 355 func (si *statInfo) getSql() string { 356 return si.sql 357 } 358 359 func (si *statInfo) setSql(sql string) { 360 si.sql = sql 361 } 362 363 func (si *statInfo) getCursorIndex() int { 364 return si.cursorIndex 365 } 366 367 func (si *statInfo) setCursorIndex(cursorIndex int) { 368 si.cursorIndex = cursorIndex 369 } 370 371 func (si *statInfo) getCloseCount() int { 372 return si.closeCount 373 } 374 375 func (si *statInfo) setCloseCount(closeCount int) { 376 si.closeCount = closeCount 377 } 378 379 func (si *statInfo) getReadStringLength() int64 { 380 return si.readStringLength 381 } 382 383 func (si *statInfo) setReadStringLength(readStringLength int64) { 384 si.readStringLength = readStringLength 385 } 386 387 func (si *statInfo) getReadBytesLength() int64 { 388 return si.readBytesLength 389 } 390 391 func (si *statInfo) setReadBytesLength(readBytesLength int64) { 392 si.readBytesLength = readBytesLength 393 } 394 395 func (si *statInfo) getOpenInputStreamCount() int { 396 return si.openInputStreamCount 397 } 398 399 func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) { 400 si.openInputStreamCount = openInputStreamCount 401 } 402 403 func (si *statInfo) getOpenReaderCount() int { 404 return si.openReaderCount 405 } 406 407 func (si *statInfo) setOpenReaderCount(openReaderCount int) { 408 si.openReaderCount = openReaderCount 409 } 410 411 func (si *statInfo) incrementCloseCount() { 412 si.closeCount++ 413 }