Ejemplo n.º 1
0
func (g *group) save(rdsv readySaved) error {
	glog.V(3).Infof("%v saving state", g)
	if rdsv.ready.SoftState != nil && rdsv.ready.SoftState.Lead != 0 {
		g.node.notifyElection(g.id)
	}

	// Apply snapshot to storage if it is more updated than current snapped.
	if !etcdraft.IsEmptySnap(rdsv.ready.Snapshot) {
		if err := g.diskStorage.SaveSnap(rdsv.ready.Snapshot); err != nil {
			glog.Fatalf("err in save snapshot: %v", err)
		}
		g.raftStorage.ApplySnapshot(rdsv.ready.Snapshot)
		glog.Infof("%v saved incoming snapshot at index %d", g,
			rdsv.ready.Snapshot.Metadata.Index)
	}

	err := g.diskStorage.Save(rdsv.ready.HardState, rdsv.ready.Entries)
	if err != nil {
		glog.Fatalf("err in raft storage save: %v", err)
	}
	glog.V(3).Infof("%v saved state on disk", g)

	g.raftStorage.Append(rdsv.ready.Entries)
	glog.V(3).Infof("%v appended entries in storage", g)

	// Apply config changes in the node as soon as possible
	// before applying other entries in the state machine.
	for _, e := range rdsv.ready.CommittedEntries {
		if e.Type != raftpb.EntryConfChange {
			continue
		}
		if e.Index <= g.saved {
			continue
		}
		g.saved = e.Index

		var cc raftpb.ConfChange
		pbutil.MustUnmarshal(&cc, e.Data)
		if glog.V(2) {
			glog.Infof("%v applies conf change %s: %s",
				g, formatConfChange(cc), formatEntry(e))
		}

		if err := g.validConfChange(cc); err != nil {
			glog.Errorf("%v received an invalid conf change for node %v: %v",
				g, cc.NodeID, err)
			cc.NodeID = etcdraft.None
			g.node.node.ApplyConfChange(g.id, cc)
			continue
		}

		cch := make(chan struct{})
		go func() {
			g.confState = *g.node.node.ApplyConfChange(g.id, cc)
			close(cch)
		}()

		select {
		case <-g.node.done:
			return ErrStopped
		case <-cch:
		}
	}

	glog.V(3).Infof("%v successfully saved ready", g)
	rdsv.saved <- struct{}{}

	select {
	case g.applyc <- rdsv.ready:
	case <-g.node.done:
	}

	return nil
}