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  }