func parseAggregateRequest(r *http.Request) (*aggregator.Aggregator, *handlerError) { var request struct { Fun string OutFmt string Interval uint Wait uint Regex string } if err := json.NewDecoder(r.Body).Decode(&request); err != nil { return nil, &handlerError{err, "Couldn't parse json", http.StatusBadRequest} } aggregate, err := aggregator.New(request.Fun, request.Regex, request.OutFmt, request.Interval, request.Wait, table.In) if err != nil { return nil, &handlerError{err, "Couldn't create aggregator", http.StatusBadRequest} } return aggregate, nil }
func readAddAgg(s *toki.Scanner, table *Table) error { t := s.Next() if t.Token != sumFn && t.Token != avgFn { return errors.New("invalid function. need sum/avg") } fun := string(t.Value) if t = s.Next(); t.Token != word { return errors.New("need a regex string") } regex := string(t.Value) if t = s.Next(); t.Token != word { return errors.New("need a format string") } outFmt := string(t.Value) if t = s.Next(); t.Token != num { return errors.New("need an interval number") } interval, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } if t = s.Next(); t.Token != num { return errors.New("need a wait number") } wait, err := strconv.Atoi(strings.TrimSpace(string(t.Value))) if err != nil { return err } agg, err := aggregator.New(fun, regex, outFmt, uint(interval), uint(wait), table.In) if err != nil { return err } table.AddAggregator(agg) return nil }
func applyCommand(table *Table, cmd string) error { inputs := strings.Split(cmd, " ") s := toki.NewScanner(tokenDefGlobal) s.SetInput(inputs[0]) t := s.Next() if t.Token == addBlack { inputs = strings.Fields(cmd) prefix_pat := "" sub_pat := "" regex_pat := "" if len(inputs) == 2 { // The fallback case to support the default substring method sub_pat = inputs[1] } else if len(inputs) == 3 { // New case supporting prefix, sub and regex patterns match_method := inputs[1] pattern := inputs[2] if match_method == "prefix" { prefix_pat = pattern } else if match_method == "sub" { sub_pat = pattern } else if match_method == "regex" { regex_pat = pattern } else { return errors.New("addBlack [prefix|sub|regex] <pattern> (invalid match type)") } } else { return errors.New("addBlack [prefix|sub|regex] <pattern>") } m, err := NewMatcher(prefix_pat, sub_pat, regex_pat) if err != nil { return err } table.AddBlacklist(m) } else if t.Token == addAgg { inputs = strings.Fields(cmd) if len(inputs) != 6 { return errors.New("addAgg <func> <match> <key> <interval> <wait>") } fun := inputs[1] regex := inputs[2] outFmt := inputs[3] interval, err := strconv.Atoi(inputs[4]) if err != nil { return err } wait, err := strconv.Atoi(inputs[5]) if err != nil { return err } agg, err := aggregator.New(fun, regex, outFmt, uint(interval), uint(wait), table.In) if err != nil { return err } table.AddAggregator(agg) } else if t.Token == addRouteSendAllMatch { split := strings.Split(string(t.Value), " ") key := split[2] if len(inputs) < 2 { return fmt.Errorf("must get at least 1 destination for route '%s'", key) } prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } destinations, err := readDestinations(inputs[1:], table, true) if err != nil { return err } route, err := NewRouteSendAllMatch(key, prefix, sub, regex, destinations) if err != nil { return err } table.AddRoute(route) } else if t.Token == addRouteSendFirstMatch { split := strings.Split(string(t.Value), " ") key := split[2] if len(inputs) < 2 { return fmt.Errorf("must get at least 1 destination for route '%s'", key) } prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } destinations, err := readDestinations(inputs[1:], table, true) if err != nil { return err } route, err := NewRouteSendFirstMatch(key, prefix, sub, regex, destinations) if err != nil { return err } table.AddRoute(route) } else if t.Token == addRouteConsistentHashing { split := strings.Split(string(t.Value), " ") key := split[2] if len(inputs) < 3 { return fmt.Errorf("must get at least 2 destinations for consistent hashing route '%s'", key) } prefix, sub, regex, err := readRouteOpts(s) if err != nil { return err } destinations, err := readDestinations(inputs[1:], table, false) if err != nil { return err } route, err := NewRouteConsistentHashing(key, prefix, sub, regex, destinations) if err != nil { return err } table.AddRoute(route) } else if t.Token == addDest { //split := strings.Split(string(t.Value), " ") //key := split[2] fmt.Println("val", t.Value) fmt.Println("inputs", inputs[0]) } else if t.Token == modDest { split := strings.Split(string(t.Value), " ") if len(split) < 4 { return errors.New("need a key, index and at least one option") } key := split[1] index, err := strconv.Atoi(split[2]) if err != nil { return err } opts := make(map[string]string) for _, str := range split[3:] { opt := strings.Split(str, "=") if len(opt) != 2 { return fmt.Errorf("bad option format at '%s'", str) } opts[opt[0]] = opt[1] } return table.UpdateDestination(key, index, opts) } else if t.Token == modRoute { split := strings.Split(string(t.Value), " ") if len(split) < 3 { return errors.New("need a key and at least one option") } key := split[1] opts := make(map[string]string) for _, str := range split[2:] { opt := strings.Split(str, "=") if len(opt) != 2 { return fmt.Errorf("bad option format at '%s'", str) } opts[opt[0]] = opt[1] } return table.UpdateRoute(key, opts) } else { return fmt.Errorf("unrecognized command '%s'", t.Value) } if t = s.Next(); t.Token != toki.EOF { //fmt.Println("h") return fmt.Errorf("extraneous input '%s'", t.Value) } return nil }