// 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} } expr := timeutil.UnixNanoToTime(r.Expiration) refresh, _ := pbutil.GetBool(r.Refresh) ttlOptions := store.TTLOptionSet{ExpireTime: expr, Refresh: refresh} 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: // TODO (yicheng): cluster should be the owner of cluster prefix store // we should not modify cluster store here. if storeMemberAttributeRegexp.MatchString(r.Path) { id := mustParseMemberIDFromKey(path.Dir(r.Path)) var attr Attributes if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { plog.Panicf("unmarshal %s should never fail: %v", r.Val, err) } ok := s.cluster.UpdateAttributes(id, attr) if !ok { return Response{} } } if r.Path == path.Join(StoreClusterPrefix, "version") { s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val))) } 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} } }
// 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} } expr := timeutil.UnixNanoToTime(r.Expiration) switch r.Method { case "POST": return f(s.store.Create(r.Path, r.Dir, r.Val, true, expr)) 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, expr)) } else { return f(s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, expr)) } } return f(s.store.Create(r.Path, r.Dir, r.Val, false, expr)) case r.PrevIndex > 0 || r.PrevValue != "": return f(s.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, expr)) default: if storeMemberAttributeRegexp.MatchString(r.Path) { id := mustParseMemberIDFromKey(path.Dir(r.Path)) var attr Attributes if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { log.Panicf("unmarshal %s should never fail: %v", r.Val, err) } s.Cluster.UpdateAttributes(id, attr) } return f(s.store.Set(r.Path, r.Dir, r.Val, expr)) } 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} } }