github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/k.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 6 package dm 7 8 import ( 9 "bytes" 10 "github.com/xiyichan/dm8/util" 11 "time" 12 ) 13 14 /** 15 * dm_svc.conf中配置的服务名对应的一组实例, 以及相关属性和状态信息 16 */ 17 type DBGroup struct { 18 Name string 19 ServerList []DB 20 Props *Properties 21 } 22 23 var curServerPos = -1 24 25 func newDBGroup(name string, serverList []DB) *DBGroup { 26 g := new(DBGroup) 27 g.Name = name 28 g.ServerList = serverList 29 return g 30 } 31 32 func (g *DBGroup) connect(connector *DmConnector) (*DmConnection, error) { 33 serverCount := len(g.ServerList) 34 startPos := 0 35 36 curServerPos = (curServerPos + 1) % serverCount 37 startPos = curServerPos 38 39 // 指定开始序号,是为了相同状态的站点上的连接能均匀分布 40 count := len(g.ServerList) 41 orgServers := make([]DB, count) 42 for i := 0; i < count; i++ { 43 orgServers[i] = g.ServerList[(i+startPos)%count] 44 } 45 return g.tryConnectServerList(connector, orgServers) 46 } 47 48 /** 49 * 按sort从大到小排序,相同sort值顺序不变 50 */ 51 func sortServer(orgServers []DB, checkTime bool) []DB { 52 count := len(orgServers) 53 sortServers := make([]DB, count) 54 var max, tmp DB 55 for i := 0; i < count; i++ { 56 max = orgServers[i] 57 for j := i + 1; j < count; j++ { 58 if max.getSort(checkTime) < orgServers[j].getSort(checkTime) { 59 tmp = max 60 max = orgServers[j] 61 orgServers[j] = tmp 62 } 63 } 64 sortServers[i] = max 65 } 66 return sortServers 67 } 68 69 /** 70 * 遍历连接服务名列表中的各个站点 71 * 72 */ 73 func (g *DBGroup) tryConnectServerList(connector *DmConnector, servers []DB) (*DmConnection, error) { 74 var sortServers []DB 75 var ex error 76 for i := 0; i < connector.switchTimes; i++ { 77 // 循环了一遍,如果没有符合要求的, 重新排序, 再尝试连接 78 sortServers = sortServer(servers, i == 0) 79 conn, err := g.traverseServerList(connector, sortServers, i == 0) 80 if err != nil { 81 ex = err 82 time.Sleep(time.Duration(connector.switchInterval) * time.Millisecond) 83 continue 84 } 85 return conn, nil 86 } 87 88 return nil, ex 89 } 90 91 /** 92 * 从指定编号开始,遍历一遍服务名中的ip列表,只连接指定类型(主机或备机)的ip 93 * @param servers 94 * @param checkTime 95 * 96 * @exception 97 * DBError.ECJDBC_INVALID_SERVER_MODE 有站点的模式不匹配 98 * DBError.ECJDBC_COMMUNITION_ERROR 所有站点都连不上 99 */ 100 func (g *DBGroup) traverseServerList(connector *DmConnector, servers []DB, checkTime bool) (*DmConnection, error) { 101 errorMsg := bytes.NewBufferString("") 102 var invalidModeErr error 103 for _, server := range servers { 104 conn, err := server.connect(connector, checkTime) 105 if err != nil { 106 if err == ECGO_INVALID_SERVER_MODE { 107 invalidModeErr = err 108 } 109 errorMsg.WriteString("[") 110 errorMsg.WriteString(server.String()) 111 errorMsg.WriteString("]") 112 errorMsg.WriteString(err.Error()) 113 errorMsg.WriteString(util.StringUtil.LineSeparator()) 114 continue 115 } 116 return conn, nil 117 } 118 119 if invalidModeErr != nil { 120 return nil, ECGO_INVALID_SERVER_MODE.addDetail("(" + errorMsg.String() + ")") 121 } else if errorMsg.Len() > 0 { 122 return nil, ECGO_COMMUNITION_ERROR.addDetail("(" + errorMsg.String() + ")") 123 } 124 125 return nil, ECGO_COMMUNITION_ERROR.throw() 126 }