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  }