vitess-gh/go/mysql/mariadb_gtid.go

277 строки
6.8 KiB
Go
Исходник Обычный вид История

/*
Copyright 2019 The Vitess Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mysql
2014-07-26 00:48:19 +04:00
import (
"fmt"
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
"sort"
2014-07-26 00:48:19 +04:00
"strconv"
"strings"
"vitess.io/vitess/go/vt/proto/vtrpc"
"vitess.io/vitess/go/vt/vterrors"
2014-07-26 00:48:19 +04:00
)
// MariadbFlavorID is the string identifier for the MariaDB flavor.
const MariadbFlavorID = "MariaDB"
2014-07-26 00:48:19 +04:00
// parseMariadbGTID is registered as a GTID parser.
2014-07-26 00:48:19 +04:00
func parseMariadbGTID(s string) (GTID, error) {
// Split into parts.
parts := strings.Split(s, "-")
if len(parts) != 3 {
return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "invalid MariaDB GTID (%v): expecting Domain-Server-Sequence", s)
2014-07-26 00:48:19 +04:00
}
// Parse Domain ID.
Domain, err := strconv.ParseUint(parts[0], 10, 32)
2014-07-26 00:48:19 +04:00
if err != nil {
return nil, vterrors.Wrapf(err, "invalid MariaDB GTID Domain ID (%v)", parts[0])
2014-07-26 00:48:19 +04:00
}
// Parse Server ID.
Server, err := strconv.ParseUint(parts[1], 10, 32)
2014-07-26 00:48:19 +04:00
if err != nil {
return nil, vterrors.Wrapf(err, "invalid MariaDB GTID Server ID (%v)", parts[1])
2014-07-26 00:48:19 +04:00
}
// Parse Sequence number.
Sequence, err := strconv.ParseUint(parts[2], 10, 64)
2014-07-26 00:48:19 +04:00
if err != nil {
return nil, vterrors.Wrapf(err, "invalid MariaDB GTID Sequence number (%v)", parts[2])
2014-07-26 00:48:19 +04:00
}
return MariadbGTID{
Domain: uint32(Domain),
Server: uint32(Server),
Sequence: Sequence,
2014-07-26 00:48:19 +04:00
}, nil
}
// parseMariadbGTIDSet is registered as a GTIDSet parser.
func parseMariadbGTIDSet(s string) (GTIDSet, error) {
gtidStrings := strings.Split(s, ",")
gtidSet := make(MariadbGTIDSet, len(gtidStrings))
for _, gtidString := range gtidStrings {
Adds RPCs to vttablet that vtorc requires (#10464) * feat: add vttablet rpc to reset replication parameters Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: added end to end testing for the rpc and fixed bug Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: fix typing error Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add basic full status rpc functionality and add test for it Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add all the fields needed in full status Signed-off-by: Manan Gupta <manan@planetscale.com> * test: moved the test to reparent tests and improved it Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: bug fix for no replication status and no primary status Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add version to the full status output Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add binlog information to full status Signed-off-by: Manan Gupta <manan@planetscale.com> * docs: fix the comment explaining the binlog information Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add semi-sync statuses to full status Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: call the correct command Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add server uuid and id to full status Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: make server_id a uint32 to accept the correct range of values Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add few more fields to the full status like version comment, semi-sync settings, binlog_row_image Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: generate vtadmin proto files Signed-off-by: Manan Gupta <manan@planetscale.com> * test: add assertion to check binlog row format is read correctly Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: split GTID mode in its own function because mariadb doesn't support it Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: fix parsing of empty mariadb gtid set Signed-off-by: Manan Gupta <manan@planetscale.com> * docs: add doucmentation for existing fields in ReplicationStatus Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add relay log file position to the replication status output Signed-off-by: Manan Gupta <manan@planetscale.com> * test: augmented full status test to check all the different positions stored Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add additional fields to replication status and read source user Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: read sql delay from show replica status output Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: read ssl allowed from show replica status output Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: read has replication filters from show replica status output Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: read auto position and using gtid from show replica status output Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: add replication lag unknown too to replication status Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: return nils from replication and primary postiion if it is not present Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: rename FileRelayLogPosition in replication status output to RelayLogSourceBinLogEquivalentPosition and augment test to make sure rpc changes are backward compatible Signed-off-by: Manan Gupta <manan@planetscale.com> * feat: update vtadmin proto files Signed-off-by: Manan Gupta <manan@planetscale.com> * refactor: rename BinLog to binlog in renamed proto field Signed-off-by: Manan Gupta <manan@planetscale.com>
2022-06-20 08:23:04 +03:00
gtidString = strings.TrimSpace(gtidString)
if gtidString == "" {
continue
}
gtid, err := parseMariadbGTID(gtidString)
if err != nil {
return nil, err
}
mdbGTID := gtid.(MariadbGTID)
gtidSet[mdbGTID.Domain] = mdbGTID
2014-09-04 23:13:47 +04:00
}
return gtidSet, nil
}
// MariadbGTID implements GTID.
type MariadbGTID struct {
// Domain is the ID number of the domain within which sequence numbers apply.
Domain uint32
// Server is the ID of the server that generated the transaction.
Server uint32
// Sequence is the sequence number of the transaction within the domain.
Sequence uint64
2014-07-26 00:48:19 +04:00
}
// String implements GTID.String().
func (gtid MariadbGTID) String() string {
return fmt.Sprintf("%d-%d-%d", gtid.Domain, gtid.Server, gtid.Sequence)
2014-07-26 00:48:19 +04:00
}
// Flavor implements GTID.Flavor().
func (gtid MariadbGTID) Flavor() string {
return MariadbFlavorID
2014-07-26 00:48:19 +04:00
}
// SequenceDomain implements GTID.SequenceDomain().
func (gtid MariadbGTID) SequenceDomain() any {
return gtid.Domain
}
// SourceServer implements GTID.SourceServer().
func (gtid MariadbGTID) SourceServer() any {
return gtid.Server
}
// SequenceNumber implements GTID.SequenceNumber().
func (gtid MariadbGTID) SequenceNumber() any {
return gtid.Sequence
}
// GTIDSet implements GTID.GTIDSet().
func (gtid MariadbGTID) GTIDSet() GTIDSet {
return MariadbGTIDSet{gtid.Domain: gtid}
}
// MariadbGTIDSet implements GTIDSet.
type MariadbGTIDSet map[uint32]MariadbGTID
// String implements GTIDSet.String()
func (gtidSet MariadbGTIDSet) String() string {
// Sort domains so the string format is deterministic.
domains := make([]uint32, 0, len(gtidSet))
for domain := range gtidSet {
domains = append(domains, domain)
}
sort.Slice(domains, func(i, j int) bool {
return domains[i] < domains[j]
})
// Convert each domain's GTID to a string and join all with comma.
s := make([]string, len(gtidSet))
for i, domain := range domains {
s[i] = gtidSet[domain].String()
}
return strings.Join(s, ",")
}
// Flavor implements GTIDSet.Flavor()
func (gtidSet MariadbGTIDSet) Flavor() string {
return MariadbFlavorID
}
// ContainsGTID implements GTIDSet.ContainsGTID().
func (gtidSet MariadbGTIDSet) ContainsGTID(other GTID) bool {
if other == nil {
return true
2014-07-26 00:48:19 +04:00
}
mdbOther, ok := other.(MariadbGTID)
if !ok {
return false
}
gtid, ok := gtidSet[mdbOther.Domain]
if !ok {
return false
}
return gtid.Sequence >= mdbOther.Sequence
}
2014-07-26 00:48:19 +04:00
// Contains implements GTIDSet.Contains().
func (gtidSet MariadbGTIDSet) Contains(other GTIDSet) bool {
if other == nil {
return false
}
mdbOther, ok := other.(MariadbGTIDSet)
if !ok {
return false
2014-07-26 00:48:19 +04:00
}
for _, gtid := range mdbOther {
if !gtidSet.ContainsGTID(gtid) {
return false
}
}
return true
}
// Equal implements GTIDSet.Equal().
func (gtidSet MariadbGTIDSet) Equal(other GTIDSet) bool {
mdbOther, ok := other.(MariadbGTIDSet)
if !ok {
return false
}
if len(gtidSet) != len(mdbOther) {
return false
}
for domain, gtid := range gtidSet {
otherGTID, ok := mdbOther[domain]
if !ok {
return false
}
if gtid != otherGTID {
return false
}
}
return true
}
2014-07-26 00:48:19 +04:00
// AddGTID implements GTIDSet.AddGTID().
func (gtidSet MariadbGTIDSet) AddGTID(other GTID) GTIDSet {
if other == nil {
return gtidSet
}
mdbOther, ok := other.(MariadbGTID)
if !ok {
return gtidSet
2014-07-26 00:48:19 +04:00
}
newSet := gtidSet.deepCopy()
newSet.addGTID(mdbOther)
return newSet
2014-07-26 00:48:19 +04:00
}
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
// Union implements GTIDSet.Union(). This is a pure method, and does not mutate the receiver.
func (gtidSet MariadbGTIDSet) Union(other GTIDSet) GTIDSet {
if gtidSet == nil && other != nil {
return other
}
if gtidSet == nil || other == nil {
return gtidSet
}
mdbOther, ok := other.(MariadbGTIDSet)
if !ok {
return gtidSet
}
newSet := gtidSet.deepCopy()
for _, otherGTID := range mdbOther {
newSet.addGTID(otherGTID)
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
}
return newSet
}
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
// Last returns the last gtid
func (gtidSet MariadbGTIDSet) Last() string {
// Sort domains so the string format is deterministic.
domains := make([]uint32, 0, len(gtidSet))
for domain := range gtidSet {
domains = append(domains, domain)
}
sort.Slice(domains, func(i, j int) bool {
return domains[i] < domains[j]
})
lastGTID := domains[len(gtidSet)-1]
return gtidSet[lastGTID].String()
}
// deepCopy returns a deep copy of the set.
func (gtidSet MariadbGTIDSet) deepCopy() MariadbGTIDSet {
newSet := make(MariadbGTIDSet, len(gtidSet))
for domain, gtid := range gtidSet {
newSet[domain] = gtid
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
}
return newSet
}
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
// addGTID is an internal method that adds a GTID to the set.
// Unlike the exported methods, this mutates the receiver.
func (gtidSet MariadbGTIDSet) addGTID(otherGTID MariadbGTID) {
gtid, ok := gtidSet[otherGTID.Domain]
if !ok || otherGTID.Sequence > gtid.Sequence {
gtidSet[otherGTID.Domain] = otherGTID
GTIDSet Union (#6180) * Corrected comment type. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added Union to the GTIDSet interface Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Wrote Union implementations for all current implementors of GTIDSet interface. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We need to check if stacks are empty before making comparisons. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added unit tests for mysql56 and mariadb implementations. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes per review suggestions. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added helper method for popping intervals so this logic doesn't need to live inside the while loop itself. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Multiple fixes. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Added test to ensure that return from Union is sorted by domain correctly. Also ran formatting. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * We don't need to explicitely non-allocate the second assignment. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Let this panic because supplying nil inputs is an invalid function call. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Comment update per review suggestion. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com> * Add check for receiver being nil but other being non-nil, in case of union always return non-nil set. Signed-off-by: Peter Farr <Peter@PrismaPhonic.com>
2020-05-15 00:31:08 +03:00
}
}
2014-07-26 00:48:19 +04:00
func init() {
gtidParsers[MariadbFlavorID] = parseMariadbGTID
gtidSetParsers[MariadbFlavorID] = parseMariadbGTIDSet
2014-07-26 00:48:19 +04:00
}