func (ls *Stores) readBootstrapInfoLocked(bi *gossip.BootstrapInfo) error { latestTS := roachpb.ZeroTimestamp timestamps := map[roachpb.StoreID]roachpb.Timestamp{} // Find the most recent bootstrap info, collecting timestamps for // each store along the way. for id, s := range ls.storeMap { var storeBI gossip.BootstrapInfo ok, err := engine.MVCCGetProto(s.engine, keys.StoreGossipKey(), roachpb.ZeroTimestamp, true, nil, &storeBI) if err != nil { return err } timestamps[id] = storeBI.Timestamp if ok && latestTS.Less(storeBI.Timestamp) { latestTS = storeBI.Timestamp *bi = storeBI } } // Update all stores with an earlier timestamp. for id, s := range ls.storeMap { if timestamps[id].Less(latestTS) { if err := engine.MVCCPutProto(s.engine, nil, keys.StoreGossipKey(), roachpb.ZeroTimestamp, nil, bi); err != nil { return err } log.Infof("updated gossip bootstrap info to %s", s) } } ls.biLatestTS = latestTS return nil }
// WriteBootstrapInfo implements the gossip.Storage interface. Write // persists the supplied bootstrap info to every known store. Returns // nil on success; otherwise returns first error encountered writing // to the stores. func (ls *Stores) WriteBootstrapInfo(bi *gossip.BootstrapInfo) error { ls.mu.RLock() defer ls.mu.RUnlock() ls.biLatestTS = ls.clock.Now() bi.Timestamp = ls.biLatestTS for _, s := range ls.storeMap { if err := engine.MVCCPutProto(s.engine, nil, keys.StoreGossipKey(), roachpb.ZeroTimestamp, nil, bi); err != nil { return err } log.Infof("wrote gossip bootstrap info to %s", s) } return nil }
func (ls *Stores) updateBootstrapInfo(bi *gossip.BootstrapInfo) error { if bi.Timestamp.Less(ls.biLatestTS) { return nil } // Update the latest timestamp and set cached version. ls.biLatestTS = bi.Timestamp ls.latestBI = protoutil.Clone(bi).(*gossip.BootstrapInfo) // Update all stores. for _, s := range ls.storeMap { if err := engine.MVCCPutProto(context.Background(), s.engine, nil, keys.StoreGossipKey(), hlc.ZeroTimestamp, nil, bi); err != nil { return err } } return nil }
// ReadBootstrapInfo implements the gossip.Storage interface. Read // attempts to read gossip bootstrap info from every known store and // finds the most recent from all stores to initialize the bootstrap // info argument. Returns an error on any issues reading data for the // stores (but excluding the case in which no data has been persisted // yet). func (ls *Stores) ReadBootstrapInfo(bi *gossip.BootstrapInfo) error { ls.mu.RLock() defer ls.mu.RUnlock() latestTS := hlc.ZeroTimestamp // Find the most recent bootstrap info. for _, s := range ls.storeMap { var storeBI gossip.BootstrapInfo ok, err := engine.MVCCGetProto(context.Background(), s.engine, keys.StoreGossipKey(), hlc.ZeroTimestamp, true, nil, &storeBI) if err != nil { return err } if ok && latestTS.Less(storeBI.Timestamp) { latestTS = storeBI.Timestamp *bi = storeBI } } log.Infof("read %d node addresses from persistent storage", len(bi.Addresses)) return ls.updateBootstrapInfo(bi) }