github.com/turingchain2020/turingchain@v1.1.21/types/config_mver.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types
     6  
     7  import (
     8  	fmt "fmt"
     9  	"sort"
    10  	"strings"
    11  
    12  	tml "github.com/BurntSushi/toml"
    13  )
    14  
    15  //multi version config
    16  type versionList struct {
    17  	data     []int64
    18  	key      string
    19  	prefix   string
    20  	suffix   string
    21  	forkname map[int64]string
    22  }
    23  
    24  type mversion struct {
    25  	data    map[string]interface{}
    26  	version map[string]*versionList
    27  }
    28  
    29  func newMversion(cfgstring string) *mversion {
    30  	cfg := make(map[string]interface{})
    31  	if _, err := tml.Decode(cfgstring, &cfg); err != nil {
    32  		panic(err)
    33  	}
    34  	flat := FlatConfig(cfg)
    35  	mver := &mversion{
    36  		data:    make(map[string]interface{}),
    37  		version: make(map[string]*versionList),
    38  	}
    39  	for k, v := range flat {
    40  		if !strings.HasPrefix(k, "mver.") {
    41  			continue
    42  		}
    43  		mver.data[k] = v
    44  	}
    45  	return mver
    46  }
    47  
    48  func (m *mversion) Get(key string, height int64) (interface{}, error) {
    49  	vlist, ok := m.version[key]
    50  	if !ok {
    51  		return m.get(key)
    52  	}
    53  	key = vlist.GetForkName(height)
    54  	return m.get(key)
    55  }
    56  
    57  func (m *mversion) get(key string) (interface{}, error) {
    58  	if data, ok := m.data[key]; ok {
    59  		return data, nil
    60  	}
    61  	tlog.Error("mver config " + key + " not found")
    62  	return nil, ErrNotFound
    63  }
    64  
    65  // UpdateFork 根据Forks信息, 适配mver下的fork,
    66  // 该函数调用需要在所有代码中fork以及toml中fork
    67  // 载入之后以及载入toml中的mver配置之后调用
    68  func (m *mversion) UpdateFork(f *Forks) {
    69  	for k := range m.data {
    70  		//global fork
    71  		//mver.forkname.name
    72  		//mver.consensus.forkname.name
    73  		items := strings.Split(k, ".")
    74  		if len(items) < 3 {
    75  			continue
    76  		}
    77  		forkname := items[len(items)-2]
    78  		if !f.HasFork(forkname) {
    79  			//maybe sub forl
    80  			//mver.exec.sub.token.forkname
    81  			forkname = items[len(items)-3] + "." + items[len(items)-2]
    82  			if !f.HasFork(forkname) {
    83  				continue
    84  			}
    85  		}
    86  		id := f.GetFork(forkname)
    87  		items[len(items)-2] = items[len(items)-1]
    88  		suffix := items[len(items)-1]
    89  		prefix := strings.Join(items[0:len(items)-2], ".")
    90  		items = items[0 : len(items)-1]
    91  		key := strings.Join(items, ".")
    92  		if _, ok := m.version[key]; !ok {
    93  			m.version[key] = &versionList{key: key, prefix: prefix, suffix: suffix}
    94  		}
    95  		err := m.version[key].addItem(id, key, forkname)
    96  		if err != nil {
    97  			panic(err)
    98  		}
    99  	}
   100  	//sort all []int data
   101  	for k, v := range m.version {
   102  		sort.Slice(v.data, func(i, j int) bool { return v.data[i] < v.data[j] })
   103  		m.version[k] = v
   104  	}
   105  }
   106  
   107  func (v *versionList) addItem(forkid int64, key, forkname string) error {
   108  	if v.key != key {
   109  		return fmt.Errorf("version list key not the same")
   110  	}
   111  	if len(v.forkname) == 0 {
   112  		v.forkname = make(map[int64]string)
   113  	}
   114  	//这里要允许替换: 有时候会有相同的fork高度
   115  	if _, ok := v.forkname[forkid]; ok {
   116  		//以字母顺序替换
   117  		if strings.Compare(forkname, v.forkname[forkid]) > 0 {
   118  			tlog.Warn(key + " same fork height is set: old name is '" + v.forkname[forkid] + "' new name is '" + forkname + "'")
   119  			v.forkname[forkid] = forkname
   120  		}
   121  		return nil
   122  	}
   123  	v.forkname[forkid] = forkname
   124  	v.data = append(v.data, forkid)
   125  	return nil
   126  }
   127  
   128  func (v *versionList) GetForkName(height int64) string {
   129  	if len(v.data) == 0 {
   130  		return v.key
   131  	}
   132  	//find first big than [0, 10, 20] 11
   133  	for i := len(v.data) - 1; i >= 0; i-- {
   134  		if height >= v.data[i] {
   135  			//fork find
   136  			forkname := v.forkname[v.data[i]]
   137  			if strings.Contains(forkname, ".") {
   138  				items := strings.Split(forkname, ".")
   139  				forkname = items[1]
   140  			}
   141  			s := v.prefix + "." + forkname + "." + v.suffix
   142  			return s
   143  		}
   144  	}
   145  	return v.key
   146  }