@@ -1756,6 +1756,7 @@ func (r *Replica) reportSnapshotStatus(ctx context.Context, to roachpb.ReplicaID
17561756type snapTruncationInfo struct {
17571757 index uint64
17581758 recipientStore roachpb.StoreID
1759+ initial bool
17591760}
17601761
17611762// addSnapshotLogTruncation creates a log truncation record which will prevent
@@ -1771,8 +1772,10 @@ type snapTruncationInfo struct {
17711772// a possibly stale value here is harmless since the values increases
17721773// monotonically. The actual snapshot index, may preserve more from a log
17731774// truncation perspective.
1775+ // If initial is true, the snapshot is marked as being sent by the replicate
1776+ // queue to a new replica; some callers only care about these snapshots.
17741777func (r * Replica ) addSnapshotLogTruncationConstraint (
1775- ctx context.Context , snapUUID uuid.UUID , recipientStore roachpb.StoreID ,
1778+ ctx context.Context , snapUUID uuid.UUID , initial bool , recipientStore roachpb.StoreID ,
17761779) (uint64 , func ()) {
17771780 r .mu .Lock ()
17781781 defer r .mu .Unlock ()
@@ -1794,6 +1797,7 @@ func (r *Replica) addSnapshotLogTruncationConstraint(
17941797 r .mu .snapshotLogTruncationConstraints [snapUUID ] = snapTruncationInfo {
17951798 index : appliedIndex ,
17961799 recipientStore : recipientStore ,
1800+ initial : initial ,
17971801 }
17981802
17991803 return appliedIndex , func () {
@@ -1814,48 +1818,53 @@ func (r *Replica) addSnapshotLogTruncationConstraint(
18141818 }
18151819}
18161820
1817- // getSnapshotLogTruncationConstraints returns the minimum index of any
1821+ // getSnapshotLogTruncationConstraintsRLocked returns the minimum index of any
18181822// currently outstanding snapshot being sent from this replica to the specified
18191823// recipient or 0 if there isn't one. Passing 0 for recipientStore means any
1820- // recipient.
1821- func (r * Replica ) getSnapshotLogTruncationConstraints (
1822- recipientStore roachpb.StoreID ,
1823- ) (minSnapIndex uint64 ) {
1824- r .mu .RLock ()
1825- defer r .mu .RUnlock ()
1826- return r .getSnapshotLogTruncationConstraintsRLocked (recipientStore )
1827- }
1828-
1824+ // recipient. If initialOnly is set, only snapshots sent by the replicate queue
1825+ // to new replicas are considered.
18291826func (r * Replica ) getSnapshotLogTruncationConstraintsRLocked (
1830- recipientStore roachpb.StoreID ,
1831- ) (minSnapIndex uint64 ) {
1827+ recipientStore roachpb.StoreID , initialOnly bool ,
1828+ ) (_ []snapTruncationInfo , minSnapIndex uint64 ) {
1829+ var sl []snapTruncationInfo
18321830 for _ , item := range r .mu .snapshotLogTruncationConstraints {
1831+ if initialOnly && ! item .initial {
1832+ continue
1833+ }
18331834 if recipientStore != 0 && item .recipientStore != recipientStore {
18341835 continue
18351836 }
18361837 if minSnapIndex == 0 || minSnapIndex > item .index {
18371838 minSnapIndex = item .index
18381839 }
1840+ sl = append (sl , item )
18391841 }
1840- return minSnapIndex
1842+ return sl , minSnapIndex
18411843}
18421844
1843- // hasOutstandingLearnerSnapshotInFlight returns true if there is a snapshot in
1844- // progress from this replica to a learner replica for this range.
1845- func (r * Replica ) hasOutstandingLearnerSnapshotInFlight () bool {
1845+ // errOnOutstandingLearnerSnapshotInflight returns an error if there is a
1846+ // snapshot in progress from this replica to a learner replica for this range.
1847+ func (r * Replica ) errOnOutstandingLearnerSnapshotInflight () error {
18461848 learners := r .Desc ().Replicas ().LearnerDescriptors ()
18471849 for _ , repl := range learners {
1848- if r .hasOutstandingSnapshotInFlightToStore (repl .StoreID ) {
1849- return true
1850+ sl , _ := r .hasOutstandingSnapshotInFlightToStore (repl .StoreID , true /* initialOnly */ )
1851+ if len (sl ) > 0 {
1852+ return errors .Errorf ("INITIAL snapshots in flight to s%d: %v" , repl .StoreID , sl )
18501853 }
18511854 }
1852- return false
1855+ return nil
18531856}
18541857
18551858// hasOutstandingSnapshotInFlightToStore returns true if there is a snapshot in
1856- // flight from this replica to the store with the given ID.
1857- func (r * Replica ) hasOutstandingSnapshotInFlightToStore (storeID roachpb.StoreID ) bool {
1858- return r .getSnapshotLogTruncationConstraints (storeID ) > 0
1859+ // flight from this replica to the store with the given ID. If initialOnly is
1860+ // true, only snapshots sent by the replicate queue to new replicas are considered.
1861+ func (r * Replica ) hasOutstandingSnapshotInFlightToStore (
1862+ storeID roachpb.StoreID , initialOnly bool ,
1863+ ) ([]snapTruncationInfo , bool ) {
1864+ r .mu .RLock ()
1865+ defer r .mu .RUnlock ()
1866+ sl , idx := r .getSnapshotLogTruncationConstraintsRLocked (storeID , initialOnly )
1867+ return sl , idx > 0
18591868}
18601869
18611870// HasRaftLeader returns true if the raft group has a raft leader currently.
0 commit comments