<commit_before>package docker

import (
	"github.com/json-iterator/go"
	"github.com/pkg/errors"
	"io"
	"strings"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
)

//StatsChannel is a container and its stats channel.
//If the container is not running stats and done channel are nil.
type StatsChannel struct {
	Container *Container
	Stats     <-chan *Stats
	refresh   chan<- struct{}
	done      chan<- struct{}
}

func (s *StatsChannel) Stop() {
	if s.done == nil {
		return
	}
	s.done <- struct{}{}
}

func (s *StatsChannel) Refresh() {
	if s.refresh == nil {
		return
	}
	select {
	case s.refresh <- struct{}{}:
	default:
	}

}

//NewStatsChannel creates a channel on which to receive the runtime stats of the given container
func NewStatsChannel(daemon *DockerDaemon, container *Container) *StatsChannel {
	if IsContainerRunning(container) {
		stats := make(chan *Stats)
		done := make(chan struct{})
		refresh := make(chan struct{})

		go func() {
			ctx, cancel := context.WithCancel(context.Background())
			containerStats, err := daemon.client.ContainerStats(ctx, container.Names[0], true)
			responseBody := containerStats.Body
			defer responseBody.Close()
			defer close(refresh)
			defer close(stats)
			if err != nil {
				stats <- &Stats{
					Error: errors.Wrapf(err, "Error creating stats stream for container %s", container.ID)}
				return
			}

			var statsJSON types.StatsJSON
			dec := jsoniter.NewDecoder(responseBody)

			for {
				select {
				case <-refresh:
					if err := dec.Decode(&statsJSON); err != nil {
						if err == io.EOF {
							return
						}
						continue
					}

					if top, err := daemon.Top(ctx, container.ID); err == nil {
						stats <- buildStats(daemon.version, container, &statsJSON, &top)
					}
				case <-ctx.Done():
					return
				case <-done:
					cancel()
					return
				}
			}
		}()

		return &StatsChannel{
			Container: container,
			Stats:     stats,
			refresh:   refresh,
			done:      done}
	}
	return &StatsChannel{Container: container}

}

//buildStats builds Stats with the given information
func buildStats(version *types.Version, container *Container, stats *types.StatsJSON, topResult *container.ContainerTopOKBody) *Stats {
	s := &Stats{
		CID:         TruncateID(container.ID),<commit_msg>Use non-blocking send to send stats on the channel<commit_after>package docker

import (
	"github.com/json-iterator/go"
	"github.com/pkg/errors"
	"io"
	"strings"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
)

//StatsChannel is a container and its stats channel.
//If the container is not running stats and done channel are nil.
type StatsChannel struct {
	Container *Container
	Stats     <-chan *Stats
	refresh   chan<- struct{}
	done      chan<- struct{}
}

func (s *StatsChannel) Stop() {
	if s.done == nil {
		return
	}
	s.done <- struct{}{}
}

func (s *StatsChannel) Refresh() {
	if s.refresh == nil {
		return
	}
	select {
	case s.refresh <- struct{}{}:
	default:
	}

}

//NewStatsChannel creates a channel on which to receive the runtime stats of the given container
func NewStatsChannel(daemon *DockerDaemon, container *Container) *StatsChannel {
	if IsContainerRunning(container) {
		stats := make(chan *Stats)
		done := make(chan struct{})
		refresh := make(chan struct{})

		go func() {
			ctx, cancel := context.WithCancel(context.Background())
			containerStats, err := daemon.client.ContainerStats(ctx, container.Names[0], true)
			responseBody := containerStats.Body
			defer responseBody.Close()
			defer close(refresh)
			defer close(stats)
			if err != nil {
				stats <- &Stats{
					Error: errors.Wrapf(err, "Error creating stats stream for container %s", container.ID)}
				return
			}

			var statsJSON types.StatsJSON
			dec := jsoniter.NewDecoder(responseBody)

			for {
				select {
				case <-refresh:
					if err := dec.Decode(&statsJSON); err != nil {
						if err == io.EOF {
							return
						}
						continue
					}

					if top, err := daemon.Top(ctx, container.ID); err == nil {
						select {
						case stats <- buildStats(daemon.version, container, &statsJSON, &top):
						default:
						}
					}
				case <-ctx.Done():
					return
				case <-done:
					cancel()
					return
				}
			}
		}()

		return &StatsChannel{
			Container: container,
			Stats:     stats,
			refresh:   refresh,
			done:      done}
	}
	return &StatsChannel{Container: container}

}

//buildStats builds Stats with the given information
func buildStats(version *types.Version, container *Container, stats *types.StatsJSON, topResult *container.ContainerTopOKBody) *Stats {
	s := &Stats{
		CID:         TruncateID(container.ID),
{'fraction_non_alphanumeric': 0.12428782443553492, 'fraction_numerical': 0.00042202996412745304, 'mean_word_length': 3.1253263707571803, 'pattern_counts': {'":': 0, '<': 23, '<?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': '864687', 'n_tokens_mistral': 1783, 'n_tokens_neox': 1470, 'n_words': 420}