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  }