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 }