github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/i.go (about)

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  
     6  package dm
     7  
     8  import (
     9  	"context"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  )
    14  
    15  const (
    16  	STATUS_VALID_TIME = 20 * time.Second // ms
    17  
    18  	// sort 值
    19  	SORT_SERVER_MODE_INVALID = -1 // 不允许连接的模式
    20  
    21  	SORT_SERVER_NOT_ALIVE = -2 // 站点无法连接
    22  
    23  	SORT_UNKNOWN = 0 // 站点还未连接过,模式未知
    24  
    25  	SORT_PRIMARY = 10
    26  
    27  	SORT_STANDBY = 20
    28  
    29  	SORT_NORMAL = 30
    30  
    31  	// OPEN>MOUNT>SUSPEND
    32  	SORT_OPEN = 3
    33  
    34  	SORT_MOUNT = 2
    35  
    36  	SORT_SUSPEND = 1
    37  )
    38  
    39  type DB struct {
    40  	host            string
    41  	port            int
    42  	alive           bool
    43  	statusRefreshTs int // 状态更新的时间点
    44  	serverMode      int
    45  	serverStatus    int
    46  	sort            int
    47  }
    48  
    49  func newDB(host string, port int) *DB {
    50  	db := new(DB)
    51  	db.host = host
    52  	db.port = port
    53  	db.serverMode = -1
    54  	db.serverStatus = -1
    55  	db.sort = SORT_UNKNOWN
    56  	return db
    57  }
    58  
    59  func (db *DB) getSort(checkTime bool) int {
    60  	if checkTime {
    61  		if int64(time.Now().Nanosecond()-db.statusRefreshTs) < int64(STATUS_VALID_TIME) {
    62  			return db.sort
    63  		} else {
    64  			return SORT_UNKNOWN
    65  		}
    66  	}
    67  
    68  	return db.sort
    69  }
    70  
    71  func (db *DB) calcSort(loginMode int) int {
    72  	sort := 0
    73  	switch loginMode {
    74  	case LOGIN_MODE_ALL_AND_PRIMARY_FIRST:
    75  		{
    76  			// 主机优先:PRIMARY>NORMAL>STANDBY
    77  			switch db.serverMode {
    78  			case SERVER_MODE_NORMAL:
    79  				sort += SORT_NORMAL * 10
    80  			case SERVER_MODE_PRIMARY:
    81  				sort += SORT_PRIMARY * 100
    82  			case SERVER_MODE_STANDBY:
    83  				sort += SORT_STANDBY
    84  			}
    85  		}
    86  	case LOGIN_MODE_ALL_AND_STANDBY_FIRST:
    87  		{
    88  			// STANDBY优先: STANDBY>PRIMARY>NORMAL
    89  			switch db.serverMode {
    90  			case SERVER_MODE_NORMAL:
    91  				sort += SORT_NORMAL
    92  			case SERVER_MODE_PRIMARY:
    93  				sort += SORT_PRIMARY * 10
    94  			case SERVER_MODE_STANDBY:
    95  				sort += SORT_STANDBY * 100
    96  			}
    97  		}
    98  	case LOGIN_MODE_ALL_AND_NORMAL_FIRST:
    99  		{
   100  			// NORMAL优先:NORMAL>PRIMARY>STANDBY
   101  			switch db.serverMode {
   102  			case SERVER_MODE_NORMAL:
   103  				sort += SORT_NORMAL * 100
   104  			case SERVER_MODE_PRIMARY:
   105  				sort += SORT_PRIMARY * 10
   106  			case SERVER_MODE_STANDBY:
   107  				sort += SORT_STANDBY
   108  			}
   109  		}
   110  	case LOGIN_MODE_PRIMARY:
   111  		if db.serverMode != SERVER_MODE_PRIMARY {
   112  			return SORT_SERVER_MODE_INVALID
   113  		}
   114  		sort += SORT_PRIMARY
   115  	case LOGIN_MODE_STANDBY:
   116  		if db.serverMode != SERVER_MODE_STANDBY {
   117  			return SORT_SERVER_MODE_INVALID
   118  		}
   119  		sort += SORT_STANDBY
   120  	}
   121  
   122  	switch db.serverStatus {
   123  	case SERVER_STATUS_MOUNT:
   124  		sort += SORT_MOUNT
   125  	case SERVER_STATUS_OPEN:
   126  		sort += SORT_OPEN
   127  	case SERVER_STATUS_SUSPEND:
   128  		sort += SORT_SUSPEND
   129  	}
   130  	return sort
   131  }
   132  
   133  func (db *DB) refreshStatus(alive bool, conn *DmConnection) {
   134  	db.alive = alive
   135  	db.statusRefreshTs = time.Now().Nanosecond()
   136  	if alive {
   137  		db.serverMode = int(conn.SvrMode)
   138  		db.serverStatus = int(conn.SvrStat)
   139  		db.sort = db.calcSort(conn.dmConnector.loginMode)
   140  	} else {
   141  		db.serverMode = -1
   142  		db.serverStatus = -1
   143  		db.sort = SORT_SERVER_NOT_ALIVE
   144  	}
   145  }
   146  
   147  func (db *DB) connect(connector *DmConnector, first bool) (*DmConnection, error) {
   148  	connector.host = db.host
   149  	connector.port = db.port
   150  	conn, err := connector.connectSingle(context.Background())
   151  	if err != nil {
   152  		db.refreshStatus(false, conn)
   153  		return nil, err
   154  	}
   155  	db.refreshStatus(true, conn)
   156  
   157  	// 模式不匹配, 这里使用的是连接之前的sort,连接之后server的状态可能发生改变sort也可能改变
   158  	if conn.dmConnector.loginStatus == SERVER_STATUS_OPEN && int(conn.SvrStat) != SERVER_STATUS_OPEN {
   159  		conn.close()
   160  		return nil, ECGO_INVALID_SERVER_MODE.throw()
   161  	}
   162  
   163  	if !db.checkServerMode(first, conn) {
   164  		conn.close()
   165  		return nil, ECGO_INVALID_SERVER_MODE.throw()
   166  	}
   167  
   168  	return conn, nil
   169  }
   170  
   171  func (db *DB) checkServerMode(first bool, conn *DmConnection) bool {
   172  	if !first {
   173  		switch conn.dmConnector.loginMode {
   174  		case LOGIN_MODE_PRIMARY:
   175  			return int(conn.SvrMode) == SERVER_MODE_PRIMARY
   176  
   177  		case LOGIN_MODE_STANDBY:
   178  			return int(conn.SvrMode) == SERVER_MODE_STANDBY
   179  
   180  		default:
   181  			return true
   182  		}
   183  	}
   184  
   185  	switch conn.dmConnector.loginMode {
   186  	case LOGIN_MODE_ALL_AND_PRIMARY_FIRST, LOGIN_MODE_PRIMARY:
   187  		return int(conn.SvrMode) == SERVER_MODE_PRIMARY
   188  
   189  	case LOGIN_MODE_ALL_AND_STANDBY_FIRST, LOGIN_MODE_STANDBY:
   190  		return int(conn.SvrMode) == SERVER_MODE_STANDBY
   191  
   192  	case LOGIN_MODE_ALL_AND_NORMAL_FIRST:
   193  		return int(conn.SvrMode) == SERVER_MODE_NORMAL
   194  
   195  	}
   196  
   197  	return false
   198  }
   199  
   200  func (db *DB) getServerStatusDesc(serverStatus int) string {
   201  	ret := ""
   202  	switch db.serverStatus {
   203  	case SERVER_STATUS_OPEN:
   204  		ret = "OPEN"
   205  	case SERVER_STATUS_MOUNT:
   206  		ret = "MOUNT"
   207  	case SERVER_STATUS_SUSPEND:
   208  		ret = "SUSPEND"
   209  	default:
   210  		ret = "UNKNOW"
   211  	}
   212  	return ret
   213  }
   214  
   215  func (db *DB) getServerModeDesc(serverMode int) string {
   216  	ret := ""
   217  	switch db.serverMode {
   218  	case SERVER_MODE_NORMAL:
   219  		ret = "NORMAL"
   220  	case SERVER_MODE_PRIMARY:
   221  		ret = "PRIMARY"
   222  	case SERVER_MODE_STANDBY:
   223  		ret = "STANDBY"
   224  	default:
   225  		ret = "UNKNOW"
   226  	}
   227  	return ret
   228  }
   229  
   230  func (db *DB) String() string {
   231  	return strings.TrimSpace(db.host) + ":" + strconv.Itoa(db.port) +
   232  		" (" + db.getServerModeDesc(db.serverMode) + ", " + db.getServerStatusDesc(db.serverStatus) + ")"
   233  }