vitess.io/vitess@v0.16.2/go/mysql/mysql56_gtid.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mysql
    18  
    19  import (
    20  	"encoding/hex"
    21  	"fmt"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"vitess.io/vitess/go/vt/proto/vtrpc"
    26  	"vitess.io/vitess/go/vt/vterrors"
    27  )
    28  
    29  // Mysql56FlavorID is the string identifier for the Mysql56 flavor.
    30  const Mysql56FlavorID = "MySQL56"
    31  
    32  // parseMysql56GTID is registered as a GTID parser.
    33  func parseMysql56GTID(s string) (GTID, error) {
    34  	// Split into parts.
    35  	parts := strings.Split(s, ":")
    36  	if len(parts) != 2 {
    37  		return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "invalid MySQL 5.6 GTID (%v): expecting UUID:Sequence", s)
    38  	}
    39  
    40  	// Parse Server ID.
    41  	sid, err := ParseSID(parts[0])
    42  	if err != nil {
    43  		return nil, vterrors.Wrapf(err, "invalid MySQL 5.6 GTID Server ID (%v)", parts[0])
    44  	}
    45  
    46  	// Parse Sequence number.
    47  	seq, err := strconv.ParseInt(parts[1], 10, 64)
    48  	if err != nil {
    49  		return nil, vterrors.Wrapf(err, "invalid MySQL 5.6 GTID Sequence number (%v)", parts[1])
    50  	}
    51  
    52  	return Mysql56GTID{Server: sid, Sequence: seq}, nil
    53  }
    54  
    55  // SID is the 16-byte unique ID of a MySQL 5.6 server.
    56  type SID [16]byte
    57  
    58  // String prints an SID in the form used by MySQL 5.6.
    59  func (sid SID) String() string {
    60  	dst := []byte("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
    61  	hex.Encode(dst, sid[:4])
    62  	hex.Encode(dst[9:], sid[4:6])
    63  	hex.Encode(dst[14:], sid[6:8])
    64  	hex.Encode(dst[19:], sid[8:10])
    65  	hex.Encode(dst[24:], sid[10:16])
    66  	return string(dst)
    67  }
    68  
    69  // ParseSID parses an SID in the form used by MySQL 5.6.
    70  func ParseSID(s string) (sid SID, err error) {
    71  	if len(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
    72  		return sid, vterrors.Errorf(vtrpc.Code_INTERNAL, "invalid MySQL 5.6 SID %q", s)
    73  	}
    74  
    75  	// Drop the dashes so we can just check the error of Decode once.
    76  	var b [32]byte
    77  	copy(b[0:], s[:8])
    78  	copy(b[8:], s[9:13])
    79  	copy(b[12:], s[14:18])
    80  	copy(b[16:], s[19:23])
    81  	copy(b[20:], s[24:])
    82  
    83  	if _, err := hex.Decode(sid[:], b[:]); err != nil {
    84  		return sid, vterrors.Wrapf(err, "invalid MySQL 5.6 SID %q", s)
    85  	}
    86  	return sid, nil
    87  }
    88  
    89  // Mysql56GTID implements GTID
    90  type Mysql56GTID struct {
    91  	// Server is the SID of the server that originally committed the transaction.
    92  	Server SID
    93  	// Sequence is the sequence number of the transaction within a given Server's
    94  	// scope.
    95  	Sequence int64
    96  }
    97  
    98  // String implements GTID.String().
    99  func (gtid Mysql56GTID) String() string {
   100  	return fmt.Sprintf("%s:%d", gtid.Server, gtid.Sequence)
   101  }
   102  
   103  // Flavor implements GTID.Flavor().
   104  func (gtid Mysql56GTID) Flavor() string {
   105  	return Mysql56FlavorID
   106  }
   107  
   108  // SequenceDomain implements GTID.SequenceDomain().
   109  func (gtid Mysql56GTID) SequenceDomain() any {
   110  	return nil
   111  }
   112  
   113  // SourceServer implements GTID.SourceServer().
   114  func (gtid Mysql56GTID) SourceServer() any {
   115  	return gtid.Server
   116  }
   117  
   118  // SequenceNumber implements GTID.SequenceNumber().
   119  func (gtid Mysql56GTID) SequenceNumber() any {
   120  	return gtid.Sequence
   121  }
   122  
   123  // GTIDSet implements GTID.GTIDSet().
   124  func (gtid Mysql56GTID) GTIDSet() GTIDSet {
   125  	return Mysql56GTIDSet{}.AddGTID(gtid)
   126  }
   127  
   128  func init() {
   129  	gtidParsers[Mysql56FlavorID] = parseMysql56GTID
   130  }