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

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  
     6  package dm
     7  
     8  import (
     9  	"math/rand"
    10  	"strconv"
    11  	"time"
    12  )
    13  
    14  var rwMap = make(map[string]*rwCounter)
    15  
    16  type rwCounter struct {
    17  	ntrx_primary int64
    18  
    19  	ntrx_total int64
    20  
    21  	primaryPercent float64
    22  
    23  	standbyPercent float64
    24  
    25  	standbyNTrxMap map[string]int64
    26  
    27  	standbyCount int
    28  }
    29  
    30  func newRWCounter(primaryPercent int, standbyCount int) *rwCounter {
    31  	rwc := new(rwCounter)
    32  	rwc.reset(primaryPercent, standbyCount)
    33  	return rwc
    34  }
    35  
    36  func (rwc *rwCounter) reset(primaryPercent int, standbyCount int) {
    37  	rwc.ntrx_primary = 0
    38  	rwc.ntrx_total = 0
    39  	rwc.standbyNTrxMap = make(map[string]int64)
    40  	rwc.standbyCount = standbyCount
    41  	if standbyCount > 0 {
    42  		rwc.primaryPercent = float64(primaryPercent) / 100.0
    43  		rwc.standbyPercent = float64(100-primaryPercent) / 100.0 / float64(standbyCount)
    44  	} else {
    45  		rwc.primaryPercent = 1
    46  		rwc.standbyPercent = 0
    47  	}
    48  }
    49  
    50  /**
    51  * 连接创建成功后调用,需要服务器返回standbyCount
    52   */
    53  func getRwCounterInstance(conn *DmConnection) *rwCounter {
    54  	key := conn.dmConnector.host + "_" + strconv.Itoa(conn.dmConnector.port) + "_" + strconv.Itoa(conn.dmConnector.rwPercent)
    55  
    56  	rwc, ok := rwMap[key]
    57  	if !ok {
    58  		rwc = newRWCounter(conn.dmConnector.rwPercent, int(conn.StandbyCount))
    59  		rwMap[key] = rwc
    60  	} else if rwc.standbyCount != int(conn.StandbyCount) {
    61  		rwc.reset(conn.dmConnector.rwPercent, int(conn.StandbyCount))
    62  	}
    63  	return rwc
    64  }
    65  
    66  /**
    67  * @return 主机;
    68   */
    69  func (rwc *rwCounter) countPrimary() RWSiteEnum {
    70  	rwc.adjustNtrx()
    71  	rwc.ntrx_primary++
    72  	rwc.ntrx_total++
    73  	return PRIMARY
    74  }
    75  
    76  /**
    77  * @param dest 主机; 备机; any;
    78  * @return 主机; 备机
    79   */
    80  func (rwc *rwCounter) count(dest RWSiteEnum, standby *DmConnection) RWSiteEnum {
    81  	rwc.adjustNtrx()
    82  	switch dest {
    83  	case ANYOF:
    84  		{
    85  			if rwc.primaryPercent != 1 && (rwc.primaryPercent == 0 || float64(rwc.getStandbyNtrx(standby)) < float64(rwc.ntrx_total)*rwc.standbyPercent || float64(rwc.ntrx_primary) > float64(rwc.ntrx_total)*rwc.primaryPercent) {
    86  				rwc.incrementStandbyNtrx(standby)
    87  				dest = STANDBY
    88  			} else {
    89  				rwc.ntrx_primary++
    90  				dest = PRIMARY
    91  			}
    92  		}
    93  	case STANDBY:
    94  		{
    95  			rwc.incrementStandbyNtrx(standby)
    96  		}
    97  	case PRIMARY:
    98  		{
    99  			rwc.ntrx_primary++
   100  		}
   101  	}
   102  
   103  	rwc.ntrx_total++
   104  	return dest
   105  }
   106  
   107  /**
   108  * 防止ntrx超出有效范围,等比调整
   109   */
   110  func (rwc *rwCounter) adjustNtrx() {
   111  	if rwc.ntrx_total < INT64_MAX {
   112  		return
   113  	}
   114  
   115  	var min int64
   116  	i := 0
   117  	for _, value := range rwc.standbyNTrxMap {
   118  		if i == 0 {
   119  			min = value
   120  		} else {
   121  			if value < min {
   122  				min = value
   123  			}
   124  		}
   125  		i++
   126  	}
   127  
   128  	if min >= rwc.ntrx_primary {
   129  		min = rwc.ntrx_primary
   130  	}
   131  
   132  	rwc.ntrx_primary = rwc.ntrx_primary / min
   133  	rwc.ntrx_total = rwc.ntrx_total / min
   134  
   135  	for key, value := range rwc.standbyNTrxMap {
   136  		rwc.standbyNTrxMap[key] = value / min
   137  	}
   138  
   139  }
   140  
   141  func (rwc *rwCounter) getStandbyNtrx(standby *DmConnection) int64 {
   142  	key := standby.dmConnector.host + ":" + strconv.Itoa(standby.dmConnector.port)
   143  	ret, ok := rwc.standbyNTrxMap[key]
   144  	if !ok {
   145  		ret = 0
   146  	}
   147  
   148  	return ret
   149  }
   150  
   151  func (rwc *rwCounter) incrementStandbyNtrx(standby *DmConnection) {
   152  	key := standby.dmConnector.host + ":" + strconv.Itoa(standby.dmConnector.port)
   153  	ret, ok := rwc.standbyNTrxMap[key]
   154  	if ok {
   155  		ret += 1
   156  	} else {
   157  		ret = 1
   158  	}
   159  	rwc.standbyNTrxMap[key] = ret
   160  }
   161  
   162  func (rwc *rwCounter) random(rowCount int) int {
   163  	rand.Seed(time.Now().UnixNano())
   164  	return int(rand.Int31n(int32(rowCount)))
   165  }
   166  
   167  func (rwc *rwCounter) String() string {
   168  	return "PERCENT(P/S) : " + strconv.FormatFloat(rwc.primaryPercent, 'f', -1, 64) + "/" + strconv.FormatFloat(rwc.standbyPercent, 'f', -1, 64) + "\nNTRX_PRIMARY : " +
   169  		strconv.FormatInt(rwc.ntrx_primary, 10) + "\nNTRX_TOTAL : " + strconv.FormatInt(rwc.ntrx_total, 10) + "\nNTRX_STANDBY : "
   170  }