github.com/XiaoMi/Gaea@v1.2.5/models/shard.go (about)

     1  // Copyright 2019 The Gaea Authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package models
    16  
    17  import (
    18  	"fmt"
    19  	"github.com/XiaoMi/Gaea/core/errors"
    20  	"regexp"
    21  	"strconv"
    22  )
    23  
    24  // constants of shard type
    25  const (
    26  	ShardDefault         = "default"
    27  	ShardGlobal          = "global"
    28  	ShardLinked          = "linked"
    29  	ShardMod             = "mod"
    30  	ShardHash            = "hash"
    31  	ShardRange           = "range"
    32  	ShardYear            = "date_year"
    33  	ShardMonth           = "date_month"
    34  	ShardDay             = "date_day"
    35  	ShardMycatMod        = "mycat_mod"
    36  	ShardMycatLong       = "mycat_long"
    37  	ShardMycatString     = "mycat_string"
    38  	ShardMycatMURMUR     = "mycat_murmur"
    39  	ShardMycatPaddingMod = "mycat_padding_mod"
    40  
    41  	// PartitionLength length of partition
    42  	PartitionLength = 1024
    43  
    44  	// mod padding
    45  	PaddingModLeftEnd  = 0
    46  	PaddingModRightEnd = 1
    47  
    48  	PaddingModDefaultPadFrom   = PaddingModRightEnd
    49  	PaddingModDefaultPadLength = 18
    50  	PaddingModDefaultModBegin  = 10
    51  	PaddingModDefaultModEnd    = 16
    52  	PaddingModDefaultMod       = 2
    53  )
    54  
    55  // Shard means shard model in etcd
    56  type Shard struct {
    57  	DB            string   `json:"db"`
    58  	Table         string   `json:"table"`
    59  	ParentTable   string   `json:"parent_table"`
    60  	Type          string   `json:"type"` // 表类型: 包括分表如hash/range/data,关联表如: linked 全局表如: global等
    61  	Key           string   `json:"key"`
    62  	Locations     []int    `json:"locations"`
    63  	Slices        []string `json:"slices"`
    64  	DateRange     []string `json:"date_range"`
    65  	TableRowLimit int      `json:"table_row_limit"`
    66  
    67  	// only used in mycat logic database (schema)
    68  	Databases []string `json:"databases"`
    69  
    70  	// used in mycat partition long shard and partition string shard
    71  	PartitionCount  string `json:"partition_count"`
    72  	PartitionLength string `json:"partition_length"`
    73  
    74  	// used in mycat partition string shard
    75  	HashSlice string `json:"hash_slice"`
    76  
    77  	// used in mycat murmur hash shard
    78  	Seed               string `json:"seed"`
    79  	VirtualBucketTimes string `json:"virtual_bucket_times"`
    80  
    81  	// used in mycat padding mod shard
    82  	PadFrom   string `json:"pad_from"`
    83  	PadLength string `json:"pad_length"`
    84  	ModBegin  string `json:"mod_begin"`
    85  	ModEnd    string `json:"mod_end"`
    86  }
    87  
    88  func (s *Shard) verify() error {
    89  	if err := s.verifyRuleSliceInfos(); err != nil {
    90  		return err
    91  	}
    92  	return nil
    93  }
    94  
    95  func (s *Shard) verifyRuleSliceInfos() error {
    96  	f, ok := ruleVerifyFuncMapping[s.Type]
    97  	if !ok {
    98  		return errors.ErrUnknownRuleType
    99  	}
   100  	return f(s)
   101  }
   102  
   103  // Encode encode json
   104  func (s *Shard) Encode() []byte {
   105  	return JSONEncode(s)
   106  }
   107  
   108  func IsMycatShardingRule(ruleType string) bool {
   109  	return ruleType == ShardMod || ruleType == ShardMycatLong || ruleType == ShardMycatMURMUR || ruleType == ShardMycatPaddingMod || ruleType == ShardMycatString
   110  }
   111  
   112  var rangeDatabaseRegex = regexp.MustCompile(`^(\S+?)\[(\d+)-(\d+)\]$`)
   113  
   114  // if a dbname is a database list, then parse the real dbnames and add to the result.
   115  // the range contains left bound and right bound, which means [left, right].
   116  func getRealDatabases(dbs []string) ([]string, error) {
   117  	var ret []string
   118  	for _, db := range dbs {
   119  		if rangeDatabaseRegex.MatchString(db) {
   120  			matches := rangeDatabaseRegex.FindStringSubmatch(db)
   121  			if len(matches) != 4 {
   122  				return nil, fmt.Errorf("invalid database list: %s", db)
   123  			}
   124  			dbPrefix := matches[1]
   125  			leftBoundStr := matches[2]
   126  			rightBoundStr := matches[3]
   127  			leftBound, err := strconv.Atoi(leftBoundStr)
   128  			if err != nil {
   129  				return nil, fmt.Errorf("invalid left bound value of database list: %s", db)
   130  			}
   131  			rightBound, err := strconv.Atoi(rightBoundStr)
   132  			if err != nil {
   133  				return nil, fmt.Errorf("invalid right bound value of database list: %s", db)
   134  			}
   135  			if rightBound <= leftBound {
   136  				return nil, fmt.Errorf("invalid bound value of database list: %s", db)
   137  			}
   138  			for i := leftBound; i <= rightBound; i++ {
   139  				realDB := dbPrefix + strconv.Itoa(i)
   140  				ret = append(ret, realDB)
   141  			}
   142  		} else {
   143  			ret = append(ret, db)
   144  		}
   145  	}
   146  	return ret, nil
   147  }