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  }