vitess.io/vitess@v0.16.2/go/vt/vtctl/reparentutil/durability_funcs.go (about) 1 /* 2 Copyright 2022 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 reparentutil 18 19 import ( 20 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 21 "vitess.io/vitess/go/vt/topo/topoproto" 22 "vitess.io/vitess/go/vt/vtctl/reparentutil/promotionrule" 23 ) 24 25 // SemiSyncAckersForPrimary returns the list of tablets which are capable of sending Semi-Sync Acks for the given primary tablet 26 func SemiSyncAckersForPrimary(durability Durabler, primary *topodatapb.Tablet, allTablets []*topodatapb.Tablet) (semiSyncAckers []*topodatapb.Tablet) { 27 for _, tablet := range allTablets { 28 if topoproto.TabletAliasEqual(primary.Alias, tablet.Alias) { 29 continue 30 } 31 if IsReplicaSemiSync(durability, primary, tablet) { 32 semiSyncAckers = append(semiSyncAckers, tablet) 33 } 34 } 35 return 36 } 37 38 // haveRevokedForTablet checks whether we have reached enough tablets such that the given primary eligible tablet cannot accept any new writes 39 // The tablets reached should have their replication stopped and must be set to read only. 40 func haveRevokedForTablet(durability Durabler, primaryEligible *topodatapb.Tablet, tabletsReached []*topodatapb.Tablet, allTablets []*topodatapb.Tablet) bool { 41 // if we have reached the primaryEligible tablet and stopped its replication and marked it read only, then it will not 42 // accept any new writes 43 if topoproto.IsTabletInList(primaryEligible, tabletsReached) { 44 return true 45 } 46 47 // semiSyncAckersReached is the list of reachable tablets capable of sending semi sync Acks for the given primaryEligible tablet 48 semiSyncAckersReached := SemiSyncAckersForPrimary(durability, primaryEligible, tabletsReached) 49 50 // allSemiSyncAckers is the list of reachable tablets capable of sending semi sync Acks for the given primaryEligible tablet 51 allSemiSyncAckers := SemiSyncAckersForPrimary(durability, primaryEligible, allTablets) 52 53 // numOfSemiSyncAcksRequired is the number of semi sync Acks that the primaryEligible tablet requires 54 numOfSemiSyncAcksRequired := SemiSyncAckers(durability, primaryEligible) 55 56 // if we have reached enough semi-sync Acking tablets such that the primaryEligible cannot accept a write 57 // we have revoked from the tablet 58 return len(allSemiSyncAckers)-len(semiSyncAckersReached) < numOfSemiSyncAcksRequired 59 } 60 61 // haveRevoked checks whether we have reached enough tablets to guarantee that no tablet eligible to become a primary can accept any write 62 // All the tablets reached must have their replication stopped and set to read only for us to guarantee that we have revoked access 63 // from all the primary eligible tablets (prevent them from accepting any new writes) 64 func haveRevoked(durability Durabler, tabletsReached []*topodatapb.Tablet, allTablets []*topodatapb.Tablet) bool { 65 for _, tablet := range allTablets { 66 if PromotionRule(durability, tablet) == promotionrule.MustNot { 67 continue 68 } 69 if !haveRevokedForTablet(durability, tablet, tabletsReached, allTablets) { 70 return false 71 } 72 } 73 return true 74 } 75 76 // canEstablishForTablet checks whether we have reached enough tablets to say that the given primary eligible tablet will be able to accept new writes 77 func canEstablishForTablet(durability Durabler, primaryEligible *topodatapb.Tablet, tabletsReached []*topodatapb.Tablet) bool { 78 // if we have not reached the primaryEligible tablet, then it cannot be considered eligible to accept writes 79 // since it might have been stopped 80 if !topoproto.IsTabletInList(primaryEligible, tabletsReached) { 81 return false 82 } 83 84 // semiSyncAckersReached is the list of reachable tablets capable of sending semi sync Acks for the given primaryEligible tablet 85 semiSyncAckersReached := SemiSyncAckersForPrimary(durability, primaryEligible, tabletsReached) 86 87 // numOfSemiSyncAcksRequired is the number of semi sync Acks that the primaryEligible tablet requires 88 numOfSemiSyncAcksRequired := SemiSyncAckers(durability, primaryEligible) 89 90 // if we have reached enough semi-sync Acking tablets such that the primaryEligible can accept a write 91 // we can safely promote this tablet 92 return len(semiSyncAckersReached) >= numOfSemiSyncAcksRequired 93 }