<commit_before>// Copyright (c) 2014 Datacratic. All rights reserved.

package meter

import (
	"sync"
	"time"
)

// DefaultPollingRate will be used as the value for PollingRate in Poller if no
// values are provided.
const DefaultPollingRate = 1 * time.Second

// Poller periodically calls ReadMeter on all the meters registered via the Add
// function and forwards the aggregated values to all the configured handlers.
type Poller struct {

	// Meters contains the initial list of meters to be polled. Should not be
	// read or modified after calling Init.
	Meters map[string]Meter

	// Handlers contains the initial list of handlers. Should not be read or
	// modified after calling init.
	Handlers []Handler

	// PollingRate is the frequency at which meters will be polled.
	PollingRate time.Duration

	// KeyPrefix is a prefix applied to all polled keys.
	KeyPrefix string

	initialize sync.Once

	addC    chan msgMeter
	removeC chan string
	handleC chan Handler
}

type msgMeter struct {
	Key   string
	Meter Meter
}

// Init can be optionally used to initialize the poller.
func (poller *Poller) Init() {
	poller.initialize.Do(poller.init)
}

// Add registers the given meter which will be polled periodically and
// associates it with the given key. If the key is already registered then the
// old meter will be replaced by the given meter.
func (poller *Poller) Add(key string, meter Meter) {
	poller.Init()
	poller.addC <- msgMeter{key, meter}
}

// Remove unregisters the given meter which will no longer be polled
// periodically.
func (poller *Poller) Remove(key string) {
	poller.Init()
	poller.removeC <- key
}

// Handle adds the given handler to the list of handler to execute.
func (poller *Poller) Handle(handler Handler) {
	poller.Init()
	poller.handleC <- handler
}

func (poller *Poller) init() {
	if poller.Meters == nil {
		poller.Meters = make(map[string]Meter)
	}

	if poller.PollingRate == 0 {
		poller.PollingRate = DefaultPollingRate
	}

	poller.addC = make(chan msgMeter)
	poller.removeC = make(chan string)
	poller.handleC = make(chan Handler)

	go poller.run()
}

func (poller *Poller) run() {
	tickC := time.Tick(poller.PollingRate)

	for {
		select {
		case msg := <-poller.addC:
			poller.add(msg.Key, msg.Meter)

		case key := <-poller.removeC:
			poller.remove(key)

		case handler := <-poller.handleC:
			poller.handle(handler)

		case <-tickC:
			poller.poll()
		}
	}
}

func (poller *Poller) add(key string, meter Meter) {
	poller.Meters[key] = meter

	// Discard any stale values.
	meter.ReadMeter(poller.PollingRate)
}

func (poller *Poller) remove(key string) {
	delete(poller.Meters, key)
}

func (poller *Poller) handle(handler Handler) {
	poller.Handlers = append(poller.Handlers, handler)
}

func (poller *Poller) poll() {
	result := make(map[string]float64)

	for prefix, meter := range poller.Meters {
		for suffix, value := range meter.ReadMeter(poller.PollingRate) {
			result[Join(poller.KeyPrefix, prefix, suffix)] = value
		}
	}

	for _, handler := range poller.Handlers {
		handler.HandleMeters(result)
	}
}

// DefaultPoller is the Poller object used by the global Add, Remove and Handle
// functions.
var DefaultPoller Poller

// Add associates the given meter with the given key and begins to periodically
// poll the meter.
func Add(key string, meter Meter) {
	DefaultPoller.Add(key, meter)
}

// Remove removes any meters associated with the key which will no longer be
// polled.
func Remove(key string) {
	DefaultPoller.Remove(key)
}

// Handle adds the given handler to the list of handlers to be executed after
// polling the meters.
func Handle(handler Handler) {
	DefaultPoller.Handle(handler)
}<commit_msg>Poller's KeyPrefix can now be modified after calling init.<commit_after>// Copyright (c) 2014 Datacratic. All rights reserved.

package meter

import (
	"sync"
	"time"
)

// DefaultPollingRate will be used as the value for PollingRate in Poller if no
// values are provided.
const DefaultPollingRate = 1 * time.Second

// Poller periodically calls ReadMeter on all the meters registered via the Add
// function and forwards the aggregated values to all the configured handlers.
type Poller struct {

	// Meters contains the initial list of meters to be polled. Should not be
	// read or modified after calling Init.
	Meters map[string]Meter

	// Handlers contains the initial list of handlers. Should not be read or
	// modified after calling init.
	Handlers []Handler

	// PollingRate is the frequency at which meters will be polled.
	PollingRate time.Duration

	// KeyPrefix is a prefix applied to all polled keys.
	KeyPrefix string

	initialize sync.Once

	addC    chan msgMeter
	removeC chan string
	handleC chan Handler
	prefixC chan string
}

type msgMeter struct {
	Key   string
	Meter Meter
}

// Init can be optionally used to initialize the poller.
func (poller *Poller) Init() {
	poller.initialize.Do(poller.init)
}

// Add registers the given meter which will be polled periodically and
// associates it with the given key. If the key is already registered then the
// old meter will be replaced by the given meter.
func (poller *Poller) Add(key string, meter Meter) {
	poller.Init()
	poller.addC <- msgMeter{key, meter}
}

// Remove unregisters the given meter which will no longer be polled
// periodically.
func (poller *Poller) Remove(key string) {
	poller.Init()
	poller.removeC <- key
}

// Handle adds the given handler to the list of handler to execute.
func (poller *Poller) Handle(handler Handler) {
	poller.Init()
	poller.handleC <- handler
}

// SetKeyPrefix changes the prefix applied to all keys.
func (poller *Poller) SetKeyPrefix(prefix string) {
	poller.Init()
	poller.prefixC <- prefix
}

func (poller *Poller) init() {
	if poller.Meters == nil {
		poller.Meters = make(map[string]Meter)
	}

	if poller.PollingRate == 0 {
		poller.PollingRate = DefaultPollingRate
	}

	poller.addC = make(chan msgMeter)
	poller.removeC = make(chan string)
	poller.handleC = make(chan Handler)
	poller.prefixC = make(chan string)

	go poller.run()
}

func (poller *Poller) run() {
	tickC := time.Tick(poller.PollingRate)

	for {
		select {
		case msg := <-poller.addC:
			poller.add(msg.Key, msg.Meter)

		case key := <-poller.removeC:
			poller.remove(key)

		case handler := <-poller.handleC:
			poller.handle(handler)

		case prefix := <-poller.prefixC:
			poller.KeyPrefix = prefix

		case <-tickC:
			poller.poll()
		}
	}
}

func (poller *Poller) add(key string, meter Meter) {
	poller.Meters[key] = meter

	// Discard any stale values.
	meter.ReadMeter(poller.PollingRate)
}

func (poller *Poller) remove(key string) {
	delete(poller.Meters, key)
}

func (poller *Poller) handle(handler Handler) {
	poller.Handlers = append(poller.Handlers, handler)
}

func (poller *Poller) poll() {
	result := make(map[string]float64)

	for prefix, meter := range poller.Meters {
		for suffix, value := range meter.ReadMeter(poller.PollingRate) {
			result[Join(poller.KeyPrefix, prefix, suffix)] = value
		}
	}

	for _, handler := range poller.Handlers {
		handler.HandleMeters(result)
	}
}

// DefaultPoller is the Poller object used by the global Add, Remove and Handle
// functions.
var DefaultPoller Poller

// SetKeyPrefix changes the key prefix of the global poller.
func SetKeyPrefix(prefix string) {
	DefaultPoller.SetKeyPrefix(prefix)
}

// Add associates the given meter with the given key and begins to periodically
// poll the meter.
func Add(key string, meter Meter) {
	DefaultPoller.Add(key, meter)
}

// Remove removes any meters associated with the key which will no longer be
// polled.
func Remove(key string) {
	DefaultPoller.Remove(key)
}

// Handle adds the given handler to the list of handlers to be executed after
// polling the meters.
func Handle(handler Handler) {
	DefaultPoller.Handle(handler)
}
{'fraction_non_alphanumeric': 0.09612919764163035, 'fraction_numerical': 0.002050756216354781, 'mean_word_length': 3.807763401109057, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5955138', 'n_tokens_mistral': 2686, 'n_tokens_neox': 2483, 'n_words': 888}