func (a *applierV2store) Put(r *pb.Request) Response { ttlOptions := toTTLOptions(r) exists, existsSet := pbutil.GetBool(r.PrevExist) switch { case existsSet: if exists { if r.PrevIndex == 0 && r.PrevValue == "" { return toResponse(a.s.store.Update(r.Path, r.Val, ttlOptions)) } else { return toResponse(a.s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) } } return toResponse(a.s.store.Create(r.Path, r.Dir, r.Val, false, ttlOptions)) case r.PrevIndex > 0 || r.PrevValue != "": return toResponse(a.s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) default: if storeMemberAttributeRegexp.MatchString(r.Path) { id := membership.MustParseMemberIDFromKey(path.Dir(r.Path)) var attr membership.Attributes if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { plog.Panicf("unmarshal %s should never fail: %v", r.Val, err) } a.s.cluster.UpdateAttributes(id, attr) // return an empty response since there is no consumer. return Response{} } if r.Path == membership.StoreClusterVersionKey() { a.s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val))) // return an empty response since there is no consumer. return Response{} } return toResponse(a.s.store.Set(r.Path, r.Dir, r.Val, ttlOptions)) } }
func (s *EtcdServer) updateClusterVersion(ver string) { if s.cluster.Version() == nil { plog.Infof("setting up the initial cluster version to %s", version.Cluster(ver)) } else { plog.Infof("updating the cluster version from %s to %s", version.Cluster(s.cluster.Version().String()), version.Cluster(ver)) } req := pb.Request{ Method: "PUT", Path: membership.StoreClusterVersionKey(), Val: ver, } ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout()) _, err := s.Do(ctx, req) cancel() switch err { case nil: return case ErrStopped: plog.Infof("aborting update cluster version because server is stopped") return default: plog.Errorf("error updating cluster version (%v)", err) } }
// applyRequest interprets r as a call to store.X and returns a Response interpreted // from store.Event func (s *EtcdServer) applyRequest(r pb.Request) Response { f := func(ev *store.Event, err error) Response { return Response{Event: ev, err: err} } refresh, _ := pbutil.GetBool(r.Refresh) ttlOptions := store.TTLOptionSet{Refresh: refresh} if r.Expiration != 0 { ttlOptions.ExpireTime = time.Unix(0, r.Expiration) } switch r.Method { case "POST": return f(s.store.Create(r.Path, r.Dir, r.Val, true, ttlOptions)) case "PUT": exists, existsSet := pbutil.GetBool(r.PrevExist) switch { case existsSet: if exists { if r.PrevIndex == 0 && r.PrevValue == "" { return f(s.store.Update(r.Path, r.Val, ttlOptions)) } else { return f(s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) } } return f(s.store.Create(r.Path, r.Dir, r.Val, false, ttlOptions)) case r.PrevIndex > 0 || r.PrevValue != "": return f(s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) default: if storeMemberAttributeRegexp.MatchString(r.Path) { id := membership.MustParseMemberIDFromKey(path.Dir(r.Path)) var attr membership.Attributes if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { plog.Panicf("unmarshal %s should never fail: %v", r.Val, err) } s.cluster.UpdateAttributes(id, attr) // return an empty response since there is no consumer. return Response{} } if r.Path == membership.StoreClusterVersionKey() { s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val))) // return an empty response since there is no consumer. return Response{} } return f(s.store.Set(r.Path, r.Dir, r.Val, ttlOptions)) } case "DELETE": switch { case r.PrevIndex > 0 || r.PrevValue != "": return f(s.store.CompareAndDelete(r.Path, r.PrevValue, r.PrevIndex)) default: return f(s.store.Delete(r.Path, r.Dir, r.Recursive)) } case "QGET": return f(s.store.Get(r.Path, r.Recursive, r.Sorted)) case "SYNC": s.store.DeleteExpiredKeys(time.Unix(0, r.Time)) return Response{} default: // This should never be reached, but just in case: return Response{err: ErrUnknownMethod} } }