Chromium Code Reviews| Index: golden/go/types/ignorestore.go |
| diff --git a/golden/go/types/ignorestore.go b/golden/go/types/ignorestore.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ee915dc7186aab928d5bf7663fbc71c0d4d0ed43 |
| --- /dev/null |
| +++ b/golden/go/types/ignorestore.go |
| @@ -0,0 +1,149 @@ |
| +package types |
| + |
| +import ( |
| + "net/url" |
| + "time" |
| + |
| + "skia.googlesource.com/buildbot.git/go/database" |
| +) |
| + |
| +// RuleMatcher returns a list of rules in the IgnoreStore that match the given |
| +// set of parameters. |
| +type RuleMatcher func(map[string]string) ([]*IgnoreRule, bool) |
| + |
| +// IgnoreStore stores and matches ignore rules. |
| +type IgnoreStore interface { |
| + // Create adds a new rule to the ignore store. |
| + Create(*IgnoreRule) error |
| + |
| + // List returns all ignore rules in the ignore store. |
| + List() ([]*IgnoreRule, error) |
| + |
| + // Removes an IgnoreRule from the store. |
| + Delete(id int, userId string) (int, error) |
| + |
| + // BuildRuleMatcher returns a RuleMatcher based on the current content |
| + // of the ignore store. |
| + BuildRuleMatcher() (RuleMatcher, error) |
| +} |
| + |
| +// IgnoreRule is the GUI struct for dealing with Ignore rules. |
| +type IgnoreRule struct { |
| + ID int `json:"id"` |
| + Name string `json:"name"` |
| + Expires time.Time `json:"expires"` |
| + Query string `json:"query"` |
| + Note string `json:"note"` |
| + Count int `json:"count"` |
| +} |
| + |
| +func NewIgnoreRule(name string, expires time.Time, queryStr string, note string) *IgnoreRule { |
| + return &IgnoreRule{ |
| + Name: name, |
| + Expires: expires, |
| + Query: queryStr, |
| + Note: note, |
| + } |
| +} |
| + |
| +// MemIgnoreStore is an in-memory implementation of IgnoreStore. |
| +type MemIgnoreStore []*IgnoreRule |
| + |
| +func NewMemIgnoreStore() IgnoreStore { |
| + return new(MemIgnoreStore) |
| +} |
| + |
| +// Create, see IgnoreStore interface. |
| +func (m *MemIgnoreStore) Create(rule *IgnoreRule) error { |
| + rule.ID = len(*m) |
| + *m = append(*m, rule) |
| + return nil |
| +} |
| + |
| +// List, see IgnoreStore interface. |
| +func (m *MemIgnoreStore) List() ([]*IgnoreRule, error) { |
| + result := make([]*IgnoreRule, 0, len(*m)) |
| + for _, r := range *m { |
| + if r != nil { |
| + result = append(result, r) |
| + } |
| + } |
| + return result, nil |
| +} |
| + |
| +// Delete, see IgnoreStore interface. |
| +func (m *MemIgnoreStore) Delete(id int, userId string) (int, error) { |
| + for idx := range *m { |
| + if ((*m)[idx] != nil) && ((*m)[idx].ID == id) { |
| + (*m)[idx] = nil |
| + return 1, nil |
| + } |
| + } |
| + return 0, nil |
| +} |
| + |
| +// BuildRuleMatcher, see IgnoreStore interface. |
|
jcgregorio
2015/01/30 17:37:28
RuleMatcher seems excessively complex. Why not:
stephana
2015/01/30 20:27:45
I choose map[string]string instead of trace as an
|
| +func (m *MemIgnoreStore) BuildRuleMatcher() (RuleMatcher, error) { |
| + rulesList, err := m.List() |
| + if err != nil { |
| + return noopRuleMatcher, err |
| + } |
| + |
| + ignoreRules := make([]map[string]map[string]bool, len(rulesList)) |
| + for idx, rawRule := range rulesList { |
| + ignoreRules[idx], err = compileRule(rawRule.Query) |
| + if err != nil { |
| + return noopRuleMatcher, err |
| + } |
| + } |
| + |
| + return func(params map[string]string) ([]*IgnoreRule, bool) { |
| + result := []*IgnoreRule{} |
| + |
| + Loop: |
| + for ruleIdx, rule := range ignoreRules { |
| + // All elements in the rules are AND connected. If the list is |
| + // longer than available parameters the result will be false. |
| + if len(rule) > len(params) { |
| + continue Loop |
| + } |
| + |
| + // Check if the parameters match the rule. |
| + for ruleKey, ruleValues := range rule { |
| + if _, ok := params[ruleKey]; !ok { |
| + continue Loop |
| + } |
| + if !ruleValues[params[ruleKey]] { |
| + continue Loop |
| + } |
| + } |
| + result = append(result, rulesList[ruleIdx]) |
| + } |
| + |
| + return result, len(result) > 0 |
| + }, nil |
| +} |
| + |
| +func compileRule(query string) (map[string]map[string]bool, error) { |
| + v, err := url.ParseQuery(query) |
| + if err != nil { |
| + return nil, err |
| + } |
| + |
| + ret := make(map[string]map[string]bool, len(v)) |
| + for k, paramValues := range v { |
| + ret[k] = make(map[string]bool, len(paramValues)) |
| + for _, oneVal := range paramValues { |
| + ret[k][oneVal] = true |
| + } |
| + } |
| + return ret, nil |
| +} |
| + |
| +func noopRuleMatcher(p map[string]string) ([]*IgnoreRule, bool) { |
| + return nil, false |
| +} |
| + |
| +func NewSQLIgnoreStore(vdb *database.VersionedDB) IgnoreStore { |
| + return NewMemIgnoreStore() |
| +} |