better data structures for matches & actions maps
This commit is contained in:
		@ -111,12 +111,7 @@ func ActionsManager() {
 | 
				
			|||||||
				go action.exec(match)
 | 
									go action.exec(match)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				actionsLock.Lock()
 | 
									actionsLock.Lock()
 | 
				
			||||||
				// make sure map exists
 | 
									actions[PAT{match, action, then}] = struct{}{}
 | 
				
			||||||
				if actions[action] == nil {
 | 
					 | 
				
			||||||
					actions[action] = make(PatternTimes)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				// append() to nil is valid go
 | 
					 | 
				
			||||||
				actions[action][match] = append(actions[action][match], then)
 | 
					 | 
				
			||||||
				actionsLock.Unlock()
 | 
									actionsLock.Unlock()
 | 
				
			||||||
				go func(pat PAT, now time.Time) {
 | 
									go func(pat PAT, now time.Time) {
 | 
				
			||||||
					time.Sleep(pat.t.Sub(now))
 | 
										time.Sleep(pat.t.Sub(now))
 | 
				
			||||||
@ -124,23 +119,20 @@ func ActionsManager() {
 | 
				
			|||||||
				}(pat, now)
 | 
									}(pat, now)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case pat = <-pendingActionsC:
 | 
							case pat = <-pendingActionsC:
 | 
				
			||||||
			match = pat.p
 | 
								match, action, then = pat.p, pat.a, pat.t
 | 
				
			||||||
			action = pat.a
 | 
					 | 
				
			||||||
			actionsLock.Lock()
 | 
								actionsLock.Lock()
 | 
				
			||||||
			actions[action][match] = actions[action][match][1:]
 | 
								delete(actions, PAT{match, action, then})
 | 
				
			||||||
			actionsLock.Unlock()
 | 
								actionsLock.Unlock()
 | 
				
			||||||
			wgActions.Add(1)
 | 
								wgActions.Add(1)
 | 
				
			||||||
			go action.exec(match)
 | 
								go action.exec(match)
 | 
				
			||||||
		case _, _ = <-stopActions:
 | 
							case _, _ = <-stopActions:
 | 
				
			||||||
			actionsLock.Lock()
 | 
								actionsLock.Lock()
 | 
				
			||||||
			for action := range actions {
 | 
								for pat := range actions {
 | 
				
			||||||
				if action.OnExit {
 | 
									if pat.a.OnExit {
 | 
				
			||||||
					for match := range actions[action] {
 | 
					 | 
				
			||||||
					wgActions.Add(1)
 | 
										wgActions.Add(1)
 | 
				
			||||||
					go action.exec(match)
 | 
										go action.exec(match)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			actionsLock.Unlock()
 | 
								actionsLock.Unlock()
 | 
				
			||||||
			wgActions.Done()
 | 
								wgActions.Done()
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@ -156,7 +148,7 @@ func MatchesManager() {
 | 
				
			|||||||
	for !end {
 | 
						for !end {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case pf = <-cleanMatchesC:
 | 
							case pf = <-cleanMatchesC:
 | 
				
			||||||
			delete(matches[pf.f], pf.p)
 | 
								delete(matches, pf)
 | 
				
			||||||
		case pft, ok := <-startupMatchesC:
 | 
							case pft, ok := <-startupMatchesC:
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
				end = true
 | 
									end = true
 | 
				
			||||||
@ -170,7 +162,7 @@ func MatchesManager() {
 | 
				
			|||||||
		select {
 | 
							select {
 | 
				
			||||||
		case pf = <-cleanMatchesC:
 | 
							case pf = <-cleanMatchesC:
 | 
				
			||||||
			matchesLock.Lock()
 | 
								matchesLock.Lock()
 | 
				
			||||||
			delete(matches[pf.f], pf.p)
 | 
								delete(matches, pf)
 | 
				
			||||||
			matchesLock.Unlock()
 | 
								matchesLock.Unlock()
 | 
				
			||||||
		case pft = <-matchesC:
 | 
							case pft = <-matchesC:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -187,26 +179,25 @@ func MatchesManager() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func matchesManagerHandleMatch(pft PFT) bool {
 | 
					func matchesManagerHandleMatch(pft PFT) bool {
 | 
				
			||||||
	filter, match, then := pft.f, pft.p, pft.t
 | 
						filter, match, then := pft.f, pft.p, pft.t
 | 
				
			||||||
 | 
						pf := PF{pft.p, pft.f}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if filter.Retry > 1 {
 | 
						if filter.Retry > 1 {
 | 
				
			||||||
		// make sure map exists
 | 
							// make sure map exists
 | 
				
			||||||
		if matches[filter] == nil {
 | 
							if matches[pf] == nil {
 | 
				
			||||||
			matches[filter] = make(PatternTimes)
 | 
								matches[pf] = make(map[time.Time]struct{})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// clean old matches
 | 
							// clean old matches
 | 
				
			||||||
		newMatches := make([]time.Time, 0, len(matches[filter][match]))
 | 
							for old := range matches[pf] {
 | 
				
			||||||
		for _, old := range matches[filter][match] {
 | 
								if !old.Add(filter.retryDuration).After(then) {
 | 
				
			||||||
			if old.Add(filter.retryDuration).After(then) {
 | 
									delete(matches[pf], old)
 | 
				
			||||||
				newMatches = append(newMatches, old)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// add new match
 | 
							// add new match
 | 
				
			||||||
		newMatches = append(newMatches, then)
 | 
							matches[pf][then] = struct{}{}
 | 
				
			||||||
		matches[filter][match] = newMatches
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if filter.Retry <= 1 || len(matches[filter][match]) >= filter.Retry {
 | 
						if filter.Retry <= 1 || len(matches[pf]) >= filter.Retry {
 | 
				
			||||||
		delete(matches[filter], match)
 | 
							delete(matches, pf)
 | 
				
			||||||
		filter.sendActions(match, then)
 | 
							filter.sendActions(match, then)
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								app/pipe.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								app/pipe.go
									
									
									
									
									
								
							@ -14,45 +14,37 @@ func genClientStatus() ClientStatus {
 | 
				
			|||||||
	matchesLock.Lock()
 | 
						matchesLock.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Painful data manipulation
 | 
						// Painful data manipulation
 | 
				
			||||||
	for filter, filterMatches := range matches {
 | 
						for pf, times := range matches {
 | 
				
			||||||
 | 
							pattern, filter := pf.p, pf.f
 | 
				
			||||||
		if cs[filter.stream.name] == nil {
 | 
							if cs[filter.stream.name] == nil {
 | 
				
			||||||
			cs[filter.stream.name] = make(map[string]MapPatternStatus)
 | 
								cs[filter.stream.name] = make(map[string]MapPatternStatus)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if cs[filter.stream.name][filter.name] == nil {
 | 
							if cs[filter.stream.name][filter.name] == nil {
 | 
				
			||||||
			cs[filter.stream.name][filter.name] = make(MapPatternStatus)
 | 
								cs[filter.stream.name][filter.name] = make(MapPatternStatus)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for pattern, patternMatches := range filterMatches {
 | 
							cs[filter.stream.name][filter.name][pattern] = &PatternStatus{len(times), nil}
 | 
				
			||||||
			var ps PatternStatus
 | 
					 | 
				
			||||||
			cs[filter.stream.name][filter.name][pattern] = &ps
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			ps.Matches = len(patternMatches)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	matchesLock.Unlock()
 | 
						matchesLock.Unlock()
 | 
				
			||||||
	actionsLock.Lock()
 | 
						actionsLock.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Painful data manipulation
 | 
						// Painful data manipulation
 | 
				
			||||||
	for action, pendingActions := range actions {
 | 
						for pat := range actions {
 | 
				
			||||||
 | 
							pattern, action, then := pat.p, pat.a, pat.t
 | 
				
			||||||
		if cs[action.filter.stream.name] == nil {
 | 
							if cs[action.filter.stream.name] == nil {
 | 
				
			||||||
			cs[action.filter.stream.name] = make(map[string]MapPatternStatus)
 | 
								cs[action.filter.stream.name] = make(map[string]MapPatternStatus)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if cs[action.filter.stream.name][action.filter.name] == nil {
 | 
							if cs[action.filter.stream.name][action.filter.name] == nil {
 | 
				
			||||||
			cs[action.filter.stream.name][action.filter.name] = make(MapPatternStatus)
 | 
								cs[action.filter.stream.name][action.filter.name] = make(MapPatternStatus)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for pattern, patternPendingActions := range pendingActions {
 | 
					 | 
				
			||||||
		if cs[action.filter.stream.name][action.filter.name][pattern] == nil {
 | 
							if cs[action.filter.stream.name][action.filter.name][pattern] == nil {
 | 
				
			||||||
				var ps PatternStatus
 | 
								cs[action.filter.stream.name][action.filter.name][pattern] = new(PatternStatus)
 | 
				
			||||||
				cs[action.filter.stream.name][action.filter.name][pattern] = &ps
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			var ps *PatternStatus
 | 
							ps := cs[action.filter.stream.name][action.filter.name][pattern]
 | 
				
			||||||
			ps = cs[action.filter.stream.name][action.filter.name][pattern]
 | 
							if ps.Actions == nil {
 | 
				
			||||||
			ps.Actions = make(map[string][]string)
 | 
								ps.Actions = make(map[string][]string)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			for _, t := range patternPendingActions {
 | 
					 | 
				
			||||||
				ps.Actions[action.name] = append(ps.Actions[action.name], t.Format(time.DateTime))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							ps.Actions[action.name] = append(ps.Actions[action.name], then.Format(time.DateTime))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	actionsLock.Unlock()
 | 
						actionsLock.Unlock()
 | 
				
			||||||
	return cs
 | 
						return cs
 | 
				
			||||||
 | 
				
			|||||||
@ -75,13 +75,10 @@ type WriteDB struct {
 | 
				
			|||||||
	enc  *gob.Encoder
 | 
						enc  *gob.Encoder
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PatternTimes map[string][]time.Time
 | 
					type MatchesMap map[PF]map[time.Time]struct{}
 | 
				
			||||||
 | 
					type ActionsMap map[PAT]struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MatchesMap map[*Filter]PatternTimes
 | 
					// Helper structs made to carry information
 | 
				
			||||||
 | 
					 | 
				
			||||||
type ActionsMap map[*Action]PatternTimes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Helper structs made to carry information across channels
 | 
					 | 
				
			||||||
type SF struct{ s, f string }
 | 
					type SF struct{ s, f string }
 | 
				
			||||||
type PSF struct{ p, s, f string }
 | 
					type PSF struct{ p, s, f string }
 | 
				
			||||||
type PF struct {
 | 
					type PF struct {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user