@@ -144,6 +144,9 @@ func checkCanInitializeEngine(ctx context.Context, eng storage.Engine) error {
144144 return err
145145}
146146
147+ type readKeyFn func (roachpb.Key , protoutil.Message ) (bool , error )
148+ type scanRangeIDFn func (roachpb.RangeID , readKeyFn ) error
149+
147150// IterateIDPrefixKeys helps visit system keys that use RangeID prefixing (such
148151// as RaftHardStateKey, RangeTombstoneKey, and many others). Such keys could in
149152// principle exist at any RangeID, and this helper efficiently discovers all the
@@ -152,11 +155,7 @@ func checkCanInitializeEngine(ctx context.Context, eng storage.Engine) error {
152155//
153156// Iteration stops on the first error (and will pass through that error).
154157func IterateIDPrefixKeys (
155- ctx context.Context ,
156- reader storage.Reader ,
157- keyFn func (roachpb.RangeID ) roachpb.Key ,
158- msg protoutil.Message ,
159- f func (_ roachpb.RangeID ) error ,
158+ ctx context.Context , reader storage.Reader , scanRangeID scanRangeIDFn ,
160159) error {
161160 // NB: Range-ID local keys have no versions and no intents.
162161 iter , err := reader .NewMVCCIterator (ctx , storage .MVCCKeyIterKind , storage.IterOptions {
@@ -167,40 +166,62 @@ func IterateIDPrefixKeys(
167166 }
168167 defer iter .Close ()
169168
170- for rangeID := roachpb .RangeID (1 ); ; {
171- rangeIDKey := keyFn (rangeID )
172- iter .SeekGE (storage .MakeMVCCMetadataKey (rangeIDKey ))
169+ iter .SeekGE (storage .MakeMVCCMetadataKey (keys .LocalRangeIDPrefix .AsRawKey ()))
170+ iterOK , iterErr := iter .Valid ()
171+ if ! iterOK || iterErr != nil {
172+ return iterErr
173+ }
173174
174- if ok , err := iter .Valid (); ! ok || err != nil {
175- return err
175+ getKeyFn := func (key roachpb.Key , msg protoutil.Message ) (bool , error ) {
176+ if ! iterOK || iterErr != nil {
177+ return iterOK , iterErr
176178 }
177-
178179 unsafeKey := iter .UnsafeKey ().Key
179- if comp := unsafeKey .Compare (rangeIDKey ); comp > 0 { // overshot
180- curRangeID , _ , _ , _ , err := keys .DecodeRangeIDKey (unsafeKey )
181- if err != nil {
182- return err
180+ comp := unsafeKey .Compare (key )
181+ if comp < 0 {
182+ iter .SeekGE (storage .MakeMVCCMetadataKey (key ))
183+ if iterOK , iterErr = iter .Valid (); ! iterOK || iterErr != nil {
184+ return iterOK , iterErr
185+ }
186+ unsafeKey = iter .UnsafeKey ().Key
187+ comp = unsafeKey .Compare (key )
188+ if comp < 0 {
189+ return false , errors .AssertionFailedf ("SeekGE undershot key %s" , key )
183190 }
184- rangeID = max (curRangeID , rangeID + 1 )
185- continue
186- } else if comp < 0 { // undershot
187- return errors .AssertionFailedf ("SeekGE undershot key %s" , rangeIDKey )
188191 }
189-
190- // Found the key. Parse and report the value.
192+ if comp > 0 {
193+ return false , nil
194+ }
195+ // Found the key (comp == 0). Parse and report the value.
191196 var meta enginepb.MVCCMetadata
192197 if err := iter .ValueProto (& meta ); err != nil {
193- return errors .Errorf ("unable to unmarshal %s into MVCCMetadata" , unsafeKey )
198+ return false , errors .Errorf ("unable to unmarshal %s into MVCCMetadata" , unsafeKey )
194199 }
195200 val := roachpb.Value {RawBytes : meta .RawBytes }
196201 if err := val .GetProto (msg ); err != nil {
197- return errors .Errorf ("unable to unmarshal %s into %T" , unsafeKey , msg )
202+ return false , errors .Errorf ("unable to unmarshal %s into %T" , unsafeKey , msg )
198203 }
199- if err := f (rangeID ); err != nil {
204+ return true , nil
205+ }
206+
207+ for iterOK && iterErr == nil {
208+ rangeID , _ , _ , _ , err := keys .DecodeRangeIDKey (iter .UnsafeKey ().Key )
209+ if err != nil {
210+ return err
211+ } else if err := scanRangeID (rangeID , getKeyFn ); err != nil {
200212 return iterutil .Map (err )
213+ } else if ! iterOK || iterErr != nil {
214+ return iterErr
215+ }
216+ newRangeID , _ , _ , _ , err := keys .DecodeRangeIDKey (iter .UnsafeKey ().Key )
217+ if err != nil {
218+ return err
219+ } else if newRangeID <= rangeID {
220+ iter .SeekGE (storage .MakeMVCCMetadataKey (keys .MakeRangeIDPrefix (rangeID + 1 )))
221+ iterOK , iterErr = iter .Valid ()
201222 }
202- rangeID ++
203223 }
224+ return iterErr
204225}
205226
206227// ReadStoreIdent reads the StoreIdent from the store.
@@ -485,41 +506,31 @@ func loadReplicas(ctx context.Context, eng storage.Engine) ([]Replica, error) {
485506 // TODO(tbg): tighten up the case where we see a RaftReplicaID but no HardState.
486507 // This leads to the general desire to validate the internal consistency of the
487508 // entire raft state (i.e. HardState, TruncatedState, Log).
488- {
489- logEvery := log .Every (10 * time .Second )
490- var i int
491- var msg kvserverpb.RaftReplicaID
492- if err := IterateIDPrefixKeys (ctx , eng , func (rangeID roachpb.RangeID ) roachpb.Key {
493- return keys .RaftReplicaIDKey (rangeID )
494- }, & msg , func (rangeID roachpb.RangeID ) error {
495- if logEvery .ShouldLog () && i > 0 { // only log if slow
496- log .KvExec .Infof (ctx , "loaded replica ID for %d/%d replicas" , i , len (s ))
497- }
498- i ++
499- s .setReplicaID (rangeID , msg .ReplicaID )
500- return nil
501- }); err != nil {
502- return nil , err
509+ logEvery := log .Every (10 * time .Second )
510+ var i int
511+ if err := IterateIDPrefixKeys (ctx , eng , func (id roachpb.RangeID , get readKeyFn ) error {
512+ if logEvery .ShouldLog () && i > 0 { // only log if slow
513+ log .KvExec .Infof (ctx , "loaded state for %d/%d replicas" , i , len (s ))
503514 }
504- log .KvExec .Infof (ctx , "loaded replica ID for %d/%d replicas" , len (s ), len (s ))
505-
506- logEvery = log .Every (10 * time .Second )
507- i = 0
515+ i ++
508516 var hs raftpb.HardState
509- if err := IterateIDPrefixKeys (ctx , eng , func (rangeID roachpb.RangeID ) roachpb.Key {
510- return keys .RaftHardStateKey (rangeID )
511- }, & hs , func (rangeID roachpb.RangeID ) error {
512- if logEvery .ShouldLog () && i > 0 { // only log if slow
513- log .KvExec .Infof (ctx , "loaded Raft state for %d/%d replicas" , i , len (s ))
514- }
515- i ++
516- s .setHardState (rangeID , hs )
517- return nil
518- }); err != nil {
519- return nil , err
517+ if ok , err := get (keys .RaftHardStateKey (id ), & hs ); err != nil {
518+ return err
519+ } else if ok {
520+ s .setHardState (id , hs )
520521 }
521- log .KvExec .Infof (ctx , "loaded Raft state for %d/%d replicas" , len (s ), len (s ))
522+ var rID kvserverpb.RaftReplicaID
523+ if ok , err := get (keys .RaftReplicaIDKey (id ), & rID ); err != nil {
524+ return err
525+ } else if ok {
526+ s .setReplicaID (id , rID .ReplicaID )
527+ }
528+ return nil
529+ }); err != nil {
530+ return nil , err
522531 }
532+ log .KvExec .Infof (ctx , "loaded state for %d/%d replicas" , len (s ), len (s ))
533+
523534 sl := make ([]Replica , 0 , len (s ))
524535 for _ , repl := range s {
525536 sl = append (sl , repl )
0 commit comments