<commit_before>package docker

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"
	"time"
)

type Builder struct {
	runtime      *Runtime
	repositories *TagStore
	graph        *Graph
}

func NewBuilder(runtime *Runtime) *Builder {
	return &Builder{
		runtime:      runtime,
		graph:        runtime.graph,
		repositories: runtime.repositories,
	}
}

func (builder *Builder) mergeConfig(userConf, imageConf *Config) {
	if userConf.Hostname != "" {
		userConf.Hostname = imageConf.Hostname
	}
	if userConf.User != "" {
		userConf.User = imageConf.User
	}
	if userConf.Memory == 0 {
		userConf.Memory = imageConf.Memory
	}
	if userConf.MemorySwap == 0 {
		userConf.MemorySwap = imageConf.MemorySwap
	}
	if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
		userConf.PortSpecs = imageConf.PortSpecs
	}
	if !userConf.Tty {
		userConf.Tty = userConf.Tty
	}
	if !userConf.OpenStdin {
		userConf.OpenStdin = imageConf.OpenStdin
	}
	if !userConf.StdinOnce {
		userConf.StdinOnce = imageConf.StdinOnce
	}
	if userConf.Env == nil || len(userConf.Env) == 0 {
		userConf.Env = imageConf.Env
	}
	if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
		userConf.Cmd = imageConf.Cmd
	}
	if userConf.Dns == nil || len(userConf.Dns) == 0 {
		userConf.Dns = imageConf.Dns
	}
}

func (builder *Builder) Create(config *Config) (*Container, error) {
	// Lookup image
	img, err := builder.repositories.LookupImage(config.Image)
	if err != nil {
		return nil, err
	}

	if img.Config != nil {
		builder.mergeConfig(config, img.Config)
	}

	if config.Cmd == nil {
		return nil, fmt.Errorf("No command specified")
	}

	// Generate id
	id := GenerateId()
	// Generate default hostname
	// FIXME: the lxc template no longer needs to set a default hostname
	if config.Hostname == "" {
		config.Hostname = id[:12]
	}

	container := &Container{
		// FIXME: we should generate the ID here instead of receiving it as an argument
		Id:              id,
		Created:         time.Now(),
		Path:            config.Cmd[0],
		Args:            config.Cmd[1:], //FIXME: de-duplicate from config
		Config:          config,
		Image:           img.Id, // Always use the resolved image id
		NetworkSettings: &NetworkSettings{},
		// FIXME: do we need to store this in the container?
		SysInitPath: sysInitPath,
	}
	container.root = builder.runtime.containerRoot(container.Id)
	// Step 1: create the container directory.
	// This doubles as a barrier to avoid race conditions.
	if err := os.Mkdir(container.root, 0700); err != nil {
		return nil, err
	}

	// If custom dns exists, then create a resolv.conf for the container
	if len(config.Dns) > 0 {
		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
		f, err := os.Create(container.ResolvConfPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		for _, dns := range config.Dns {
			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
				return nil, err
			}
		}
	} else {
		container.ResolvConfPath = "/etc/resolv.conf"
	}

	// Step 2: save the container json
	if err := container.ToDisk(); err != nil {
		return nil, err
	}
	// Step 3: register the container
	if err := builder.runtime.Register(container); err != nil {
		return nil, err
	}
	return container, nil
}

// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (builder *Builder) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
	// FIXME: freeze the container before copying it to avoid data corruption?
	// FIXME: this shouldn't be in commands.
	rwTar, err := container.ExportRw()
	if err != nil {
		return nil, err
	}
	// Create a new image from the container's base layers + a new layer from container changes
	img, err := builder.graph.Create(rwTar, container, comment, author, config)
	if err != nil {
		return nil, err
	}
	// Register the image if needed
	if repository != "" {
		if err := builder.repositories.Set(repository, tag, img.Id, true); err != nil {
			return img, err
		}
	}
	return img, nil
}

func (builder *Builder) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := builder.runtime.Get(c)
		builder.runtime.Destroy(tmp)
		Debugf("Removing container %s", c)
	}
	for i := range images {
		builder.runtime.graph.Delete(i)
		Debugf("Removing image %s", i)
	}
}

func (builder *Builder) getCachedImage(image *Image, config *Config) (*Image, error) {
	// Retrieve all images
	images, err := builder.graph.All()
	if err != nil {
		return nil, err
	}

	// Store the tree in a map of map (map[parentId][childId])
	imageMap := make(map[string]map[string]struct{})
	for _, img := range images {
		if _, exists := imageMap[img.Parent]; !exists {
			imageMap[img.Parent] = make(map[string]struct{})
		}
		imageMap[img.Parent][img.Id] = struct{}{}
	}

	// Loop on the children of the given image and check the config
	for elem := range imageMap[image.Id] {
		img, err := builder.graph.Get(elem)
		if err != nil {
			return nil, err
		}
		if CompareConfig(&img.ContainerConfig, config) {
			return img, nil
		}
	}
	return nil, nil
}

func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) (*Image, error) {
	var (
		image, base   *Image
		config        *Config
		maintainer    string
		tmpContainers map[string]struct{} = make(map[string]struct{})
		tmpImages     map[string]struct{} = make(map[string]struct{})
	)
	defer builder.clearTmp(tmpContainers, tmpImages)

	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		line = strings.Replace(strings.TrimSpace(line), "	", " ", 1)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, " ", 2)
		if len(tmp) != 2 {
			return nil, fmt.Errorf("Invalid Dockerfile format")
		}
		instruction := strings.Trim(tmp[0], " ")
		arguments := strings.Trim(tmp[1], " ")
		switch strings.ToLower(instruction) {
		case "from":
			fmt.Fprintf(stdout, "FROM %s\n", arguments)
			image, err = builder.runtime.repositories.LookupImage(arguments)
			if err != nil {
				if builder.runtime.graph.IsNotExist(err) {

					var tag, remote string
					if strings.Contains(arguments, ":") {
						remoteParts := strings.Split(arguments, ":")
						tag = remoteParts[1]
						remote = remoteParts[0]
					} else {
						remote = arguments
					}

					if err := builder.runtime.graph.PullRepository(stdout, remote, tag, builder.runtime.repositories, builder.runtime.authConfig); err != nil {
						return nil, err
					}

					image, err = builder.runtime.repositories.LookupImage(arguments)
					if err != nil {
						return nil, err
					}
				} else {
					return nil, err
				}
			}
			config = &Config{}

			break
		case "maintainer":
			fmt.Fprintf(stdout, "MAINTAINER %s\n", arguments)
			maintainer = arguments
			break
		case "run":
			fmt.Fprintf(stdout, "RUN %s\n", arguments)
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
			}
			config, err := ParseRun([]string{image.Id, "/bin/sh", "-c", arguments}, nil, builder.runtime.capabilities)
			if err != nil {
				return nil, err
			}

			if cache, err := builder.getCachedImage(image, config); err != nil {
				return nil, err
			} else if cache != nil {
				image = cache
				fmt.Fprintf(stdout, "===> %s\n", image.ShortId())
				break
			}
			config, err := ParseRun([]string{image.Id, "/bin/sh", "-c", tmp[1]}, nil, builder.runtime.capabilities)
			if err != nil {
				return err
			}

			// Create the container and start it
			c, err := builder.Create(config)
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return err
			}
			tmpContainers[c.Id] = struct{}{}

			// Wait for it to finish
			if result := c.Wait(); result != 0 {
				return nil, fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", arguments, result)
			}

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, nil)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())

			// use the base as the new image
			image = base

			break
		case "cmd":
			fmt.Fprintf(stdout, "CMD %s\n", arguments)

			// Create the container and start it
			c, err := builder.Create(&Config{Image: image.Id, Cmd: []string{"", ""}})
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			tmpContainers[c.Id] = struct{}{}

			cmd := []string{}
			if err := json.Unmarshal([]byte(arguments), &cmd); err != nil {
				return nil, err
			}
			config.Cmd = cmd

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, config)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			image = base
			break
		case "expose":
			ports := strings.Split(arguments, " ")

			fmt.Fprintf(stdout, "EXPOSE %v\n", ports)
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to copy")
			}

			// Create the container and start it
			c, err := builder.Create(&Config{Image: image.Id, Cmd: []string{"", ""}})
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			tmpContainers[c.Id] = struct{}{}

			config.PortSpecs = append(ports, config.PortSpecs...)

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, config)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			image = base
			break
		case "insert":
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to copy")
			}
			tmp = strings.SplitN(arguments, " ", 2)
			if len(tmp) != 2 {
				return nil, fmt.Errorf("Invalid INSERT format")
			}
			sourceUrl := strings.Trim(tmp[0], " ")
			destPath := strings.Trim(tmp[1], " ")
			fmt.Fprintf(stdout, "COPY %s to %s in %s\n", sourceUrl, destPath, base.ShortId())

			file, err := Download(sourceUrl, stdout)
			if err != nil {
				return nil, err
			}
			defer file.Body.Close()

			config, err := ParseRun([]string{base.Id, "echo", "insert", sourceUrl, destPath}, nil, builder.runtime.capabilities)
			if err != nil {
				return nil, err
			}
			c, err := builder.Create(config)
			if err != nil {
				return nil, err
			}

			if err := c.Start(); err != nil {
				return nil, err
			}

			// Wait for echo to finish
			if result := c.Wait(); result != 0 {
				return nil, fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", arguments, result)
			}

			if err := c.Inject(file.Body, destPath); err != nil {
				return nil, err
			}

			base, err = builder.Commit(c, "", "", "", maintainer, nil)
			if err != nil {
				return nil, err
			}
			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())

			image = base

			break
		default:
			fmt.Fprintf(stdout, "Skipping unknown instruction %s\n", strings.ToUpper(instruction))
		}
	}
	if image != nil {
		// The build is successful, keep the temporary containers and images
		for i := range tmpImages {
			delete(tmpImages, i)
		}
		for i := range tmpContainers {
			delete(tmpContainers, i)
		}
		fmt.Fprintf(stdout, "Build finished. image id: %s\n", image.ShortId())
		return image, nil
	}
	return nil, fmt.Errorf("An error occured during the build\n")
}
<commit_msg>Rebase fix<commit_after>package docker

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"strings"
	"time"
)

type Builder struct {
	runtime      *Runtime
	repositories *TagStore
	graph        *Graph
}

func NewBuilder(runtime *Runtime) *Builder {
	return &Builder{
		runtime:      runtime,
		graph:        runtime.graph,
		repositories: runtime.repositories,
	}
}

func (builder *Builder) mergeConfig(userConf, imageConf *Config) {
	if userConf.Hostname != "" {
		userConf.Hostname = imageConf.Hostname
	}
	if userConf.User != "" {
		userConf.User = imageConf.User
	}
	if userConf.Memory == 0 {
		userConf.Memory = imageConf.Memory
	}
	if userConf.MemorySwap == 0 {
		userConf.MemorySwap = imageConf.MemorySwap
	}
	if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
		userConf.PortSpecs = imageConf.PortSpecs
	}
	if !userConf.Tty {
		userConf.Tty = userConf.Tty
	}
	if !userConf.OpenStdin {
		userConf.OpenStdin = imageConf.OpenStdin
	}
	if !userConf.StdinOnce {
		userConf.StdinOnce = imageConf.StdinOnce
	}
	if userConf.Env == nil || len(userConf.Env) == 0 {
		userConf.Env = imageConf.Env
	}
	if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
		userConf.Cmd = imageConf.Cmd
	}
	if userConf.Dns == nil || len(userConf.Dns) == 0 {
		userConf.Dns = imageConf.Dns
	}
}

func (builder *Builder) Create(config *Config) (*Container, error) {
	// Lookup image
	img, err := builder.repositories.LookupImage(config.Image)
	if err != nil {
		return nil, err
	}

	if img.Config != nil {
		builder.mergeConfig(config, img.Config)
	}

	if config.Cmd == nil {
		return nil, fmt.Errorf("No command specified")
	}

	// Generate id
	id := GenerateId()
	// Generate default hostname
	// FIXME: the lxc template no longer needs to set a default hostname
	if config.Hostname == "" {
		config.Hostname = id[:12]
	}

	container := &Container{
		// FIXME: we should generate the ID here instead of receiving it as an argument
		Id:              id,
		Created:         time.Now(),
		Path:            config.Cmd[0],
		Args:            config.Cmd[1:], //FIXME: de-duplicate from config
		Config:          config,
		Image:           img.Id, // Always use the resolved image id
		NetworkSettings: &NetworkSettings{},
		// FIXME: do we need to store this in the container?
		SysInitPath: sysInitPath,
	}
	container.root = builder.runtime.containerRoot(container.Id)
	// Step 1: create the container directory.
	// This doubles as a barrier to avoid race conditions.
	if err := os.Mkdir(container.root, 0700); err != nil {
		return nil, err
	}

	// If custom dns exists, then create a resolv.conf for the container
	if len(config.Dns) > 0 {
		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
		f, err := os.Create(container.ResolvConfPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		for _, dns := range config.Dns {
			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
				return nil, err
			}
		}
	} else {
		container.ResolvConfPath = "/etc/resolv.conf"
	}

	// Step 2: save the container json
	if err := container.ToDisk(); err != nil {
		return nil, err
	}
	// Step 3: register the container
	if err := builder.runtime.Register(container); err != nil {
		return nil, err
	}
	return container, nil
}

// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (builder *Builder) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
	// FIXME: freeze the container before copying it to avoid data corruption?
	// FIXME: this shouldn't be in commands.
	rwTar, err := container.ExportRw()
	if err != nil {
		return nil, err
	}
	// Create a new image from the container's base layers + a new layer from container changes
	img, err := builder.graph.Create(rwTar, container, comment, author, config)
	if err != nil {
		return nil, err
	}
	// Register the image if needed
	if repository != "" {
		if err := builder.repositories.Set(repository, tag, img.Id, true); err != nil {
			return img, err
		}
	}
	return img, nil
}

func (builder *Builder) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := builder.runtime.Get(c)
		builder.runtime.Destroy(tmp)
		Debugf("Removing container %s", c)
	}
	for i := range images {
		builder.runtime.graph.Delete(i)
		Debugf("Removing image %s", i)
	}
}

func (builder *Builder) getCachedImage(image *Image, config *Config) (*Image, error) {
	// Retrieve all images
	images, err := builder.graph.All()
	if err != nil {
		return nil, err
	}

	// Store the tree in a map of map (map[parentId][childId])
	imageMap := make(map[string]map[string]struct{})
	for _, img := range images {
		if _, exists := imageMap[img.Parent]; !exists {
			imageMap[img.Parent] = make(map[string]struct{})
		}
		imageMap[img.Parent][img.Id] = struct{}{}
	}

	// Loop on the children of the given image and check the config
	for elem := range imageMap[image.Id] {
		img, err := builder.graph.Get(elem)
		if err != nil {
			return nil, err
		}
		if CompareConfig(&img.ContainerConfig, config) {
			return img, nil
		}
	}
	return nil, nil
}

func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) (*Image, error) {
	var (
		image, base   *Image
		config        *Config
		maintainer    string
		tmpContainers map[string]struct{} = make(map[string]struct{})
		tmpImages     map[string]struct{} = make(map[string]struct{})
	)
	defer builder.clearTmp(tmpContainers, tmpImages)

	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		line = strings.Replace(strings.TrimSpace(line), "	", " ", 1)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, " ", 2)
		if len(tmp) != 2 {
			return nil, fmt.Errorf("Invalid Dockerfile format")
		}
		instruction := strings.Trim(tmp[0], " ")
		arguments := strings.Trim(tmp[1], " ")
		switch strings.ToLower(instruction) {
		case "from":
			fmt.Fprintf(stdout, "FROM %s\n", arguments)
			image, err = builder.runtime.repositories.LookupImage(arguments)
			if err != nil {
				if builder.runtime.graph.IsNotExist(err) {

					var tag, remote string
					if strings.Contains(arguments, ":") {
						remoteParts := strings.Split(arguments, ":")
						tag = remoteParts[1]
						remote = remoteParts[0]
					} else {
						remote = arguments
					}

					if err := builder.runtime.graph.PullRepository(stdout, remote, tag, builder.runtime.repositories, builder.runtime.authConfig); err != nil {
						return nil, err
					}

					image, err = builder.runtime.repositories.LookupImage(arguments)
					if err != nil {
						return nil, err
					}
				} else {
					return nil, err
				}
			}
			config = &Config{}

			break
		case "maintainer":
			fmt.Fprintf(stdout, "MAINTAINER %s\n", arguments)
			maintainer = arguments
			break
		case "run":
			fmt.Fprintf(stdout, "RUN %s\n", arguments)
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
			}
			config, err := ParseRun([]string{image.Id, "/bin/sh", "-c", arguments}, nil, builder.runtime.capabilities)
			if err != nil {
				return nil, err
			}

			if cache, err := builder.getCachedImage(image, config); err != nil {
				return nil, err
			} else if cache != nil {
				image = cache
				fmt.Fprintf(stdout, "===> %s\n", image.ShortId())
				break
			}

			// Create the container and start it
			c, err := builder.Create(config)
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			tmpContainers[c.Id] = struct{}{}

			// Wait for it to finish
			if result := c.Wait(); result != 0 {
				return nil, fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", arguments, result)
			}

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, nil)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())

			// use the base as the new image
			image = base

			break
		case "cmd":
			fmt.Fprintf(stdout, "CMD %s\n", arguments)

			// Create the container and start it
			c, err := builder.Create(&Config{Image: image.Id, Cmd: []string{"", ""}})
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			tmpContainers[c.Id] = struct{}{}

			cmd := []string{}
			if err := json.Unmarshal([]byte(arguments), &cmd); err != nil {
				return nil, err
			}
			config.Cmd = cmd

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, config)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			image = base
			break
		case "expose":
			ports := strings.Split(arguments, " ")

			fmt.Fprintf(stdout, "EXPOSE %v\n", ports)
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to copy")
			}

			// Create the container and start it
			c, err := builder.Create(&Config{Image: image.Id, Cmd: []string{"", ""}})
			if err != nil {
				return nil, err
			}
			if err := c.Start(); err != nil {
				return nil, err
			}
			tmpContainers[c.Id] = struct{}{}

			config.PortSpecs = append(ports, config.PortSpecs...)

			// Commit the container
			base, err = builder.Commit(c, "", "", "", maintainer, config)
			if err != nil {
				return nil, err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			image = base
			break
		case "insert":
			if image == nil {
				return nil, fmt.Errorf("Please provide a source image with `from` prior to copy")
			}
			tmp = strings.SplitN(arguments, " ", 2)
			if len(tmp) != 2 {
				return nil, fmt.Errorf("Invalid INSERT format")
			}
			sourceUrl := strings.Trim(tmp[0], " ")
			destPath := strings.Trim(tmp[1], " ")
			fmt.Fprintf(stdout, "COPY %s to %s in %s\n", sourceUrl, destPath, base.ShortId())

			file, err := Download(sourceUrl, stdout)
			if err != nil {
				return nil, err
			}
			defer file.Body.Close()

			config, err := ParseRun([]string{base.Id, "echo", "insert", sourceUrl, destPath}, nil, builder.runtime.capabilities)
			if err != nil {
				return nil, err
			}
			c, err := builder.Create(config)
			if err != nil {
				return nil, err
			}

			if err := c.Start(); err != nil {
				return nil, err
			}

			// Wait for echo to finish
			if result := c.Wait(); result != 0 {
				return nil, fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", arguments, result)
			}

			if err := c.Inject(file.Body, destPath); err != nil {
				return nil, err
			}

			base, err = builder.Commit(c, "", "", "", maintainer, nil)
			if err != nil {
				return nil, err
			}
			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())

			image = base

			break
		default:
			fmt.Fprintf(stdout, "Skipping unknown instruction %s\n", strings.ToUpper(instruction))
		}
	}
	if image != nil {
		// The build is successful, keep the temporary containers and images
		for i := range tmpImages {
			delete(tmpImages, i)
		}
		for i := range tmpContainers {
			delete(tmpContainers, i)
		}
		fmt.Fprintf(stdout, "Build finished. image id: %s\n", image.ShortId())
		return image, nil
	}
	return nil, fmt.Errorf("An error occured during the build\n")
}
<|endoftext|>


<commit_before>package main

import (
	//"fmt"
	"log"
)

type BuildQueue struct {
	queue chan string
}

func MakeBuildQueue() *BuildQueue {
	bq := BuildQueue{}
	bq.queue = make(chan string, 100)
	go builder(bq.queue)
	return &bq
}

func (bq *BuildQueue) EnQueue(pkg string) {
	bq.queue <- pkg
}

func builder(queue <-chan string) {
	for {
		pkg := <-queue

		log.Println("Processing Package: ", pkg)

		var err error
		err = goget(pkg, "build.log")
		if err == nil {
			log.Println(" Running Tests on: ", pkg)
			err = gotest(pkg, "test.log")
		}
		if err == nil {
			log.Println(" Processing Coverage on: ", pkg)
			err = gocover(pkg, "cover.log")
		}

		if err == nil {
			log.Println(" Done")
		} else {
			log.Println(" Error: ", err)
		}
	}
}
<commit_msg>trying something different with error handling<commit_after>package main

import (
	//"fmt"
	"log"
)

type BuildQueue struct {
	queue chan string
}

func MakeBuildQueue() *BuildQueue {
	bq := BuildQueue{}
	bq.queue = make(chan string, 100)
	go builder(bq.queue)
	return &bq
}

func (bq *BuildQueue) EnQueue(pkg string) {
	bq.queue <- pkg
}

func builder(queue <-chan string) {
	for {
		pkg := <-queue
		var err error

		run := func(f func(pkg, logfile string) error, logfile, logmsg string) {
			if err == nil {
				err = f(pkg, logfile)
				log.Println(logmsg, pkg)
			}
		}

		run(goget, "build.log", "Processing Package:")
		run(gotest, "test.log", " Running Tests on:")
		run(gocover, "cover.log", " Processing Coverage on:")

		if err == nil {
			log.Println(" Done")
		} else {
			log.Println(" Error: ", err)
		}
	}
}
<|endoftext|>


<commit_before>// This is Free Software covered by the terms of the MIT license.
// See LICENSE file for details.
// Copyright 2017 by Intevation GmbH
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/s-l-teichmann/creoleto/parser"
)

type builder struct {
	*parser.BaseCreole10Listener
	current *node

	stack []interface{}
}

type headingBuilder struct {
	depth      int
	hasContent bool
}

func newBuilder() *builder {
	return &builder{
		current: &node{},
	}
}

func (b *builder) push(x interface{}) {
	b.stack = append(b.stack, x)
}

func (b *builder) pop() interface{} {
	l := len(b.stack)
	x := b.stack[l-1]
	b.stack[l-1] = nil
	b.stack = b.stack[:l-1]
	return x
}

func (b *builder) top() interface{} {
	return b.stack[len(b.stack)-1]
}

func (b *builder) EnterHeading(c *parser.HeadingContext) {
	b.push(&headingBuilder{})
}

func (b *builder) EnterHeading_markup(c *parser.Heading_markupContext) {
	if hb := b.top().(*headingBuilder); !hb.hasContent {
		hb.depth++
	}
}

func (b *builder) ExitHeading_content(c *parser.Heading_contentContext) {
	b.top().(*headingBuilder).hasContent = true
}

func (b *builder) ExitHeading(c *parser.HeadingContext) {

	hb := b.pop().(*headingBuilder)

	trim := strings.Repeat("=", hb.depth)
	content := strings.TrimSpace(c.GetText())
	content = strings.TrimSuffix(strings.TrimPrefix(content, trim), trim)
	content = strings.TrimSpace(content)

	var typ nodeType
	switch hb.depth {
	case 1:
		typ = heading1Node
	case 2:
		typ = heading2Node
	case 3:
		typ = heading3Node
	case 4:
		typ = heading4Node
	case 5:
		typ = heading5Node
	default:
		typ = heading6Node
	}

	n := &node{
		nodeType: typ,
		parent:   b.current,
		value:    content,
	}
	b.current.children = append(b.current.children, n)
}

func (b *builder) EnterParagraph(c *parser.ParagraphContext) {
	b.current = ndp(paragraphNode, b.current)
}

func (b *builder) ExitParagraph(c *parser.ParagraphContext) {
	if b.current != nil && b.current.nodeType == paragraphNode && b.current.parent != nil {
		b.current = b.current.parent
	}
}

func (b *builder) EnterText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "EnterText_unformattedelement")
}

func (b *builder) ExitText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintf(os.Stderr, "ExitText_unformattedelement '%s'\n", c.GetText())
}

func (b *builder) EnterText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "EnterText_line")
}

func (b *builder) ExitText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "ExitText_line:", c.GetText())
}

func (b *builder) EnterText_formattedelement(c *parser.Text_formattedelementContext) {
	fmt.Fprintln(os.Stderr, "***EnterText_formattedelement")
}

func (b *builder) ExitText_formattedelement(c *parser.Text_formattedelementContext) {
	fmt.Fprintln(os.Stderr, "***ExitText_formattedelement")
}

func (b *builder) EnterItal_markup(c *parser.Ital_markupContext) {
	fmt.Fprintln(os.Stderr, "//EnterItal_markup")
}

func (b *builder) parse(data string) (*document, error) {

	input := antlr.NewInputStream(data)
	lexer := parser.NewCreole10Lexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	pa := parser.NewCreole10Parser(stream)
	pa.AddParseListener(b)
	//pa.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
	//pa.BuildParseTrees = true
	pa.Start()
	//antlr.ParseTreeWalkerDefault.Walk(p, tree)

	// TODO: Write own ErrorListener.

	doc := &document{root: b.current}

	return doc, nil
}
<commit_msg>Removed paranoid check.<commit_after>// This is Free Software covered by the terms of the MIT license.
// See LICENSE file for details.
// Copyright 2017 by Intevation GmbH
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/s-l-teichmann/creoleto/parser"
)

type builder struct {
	*parser.BaseCreole10Listener
	current *node

	stack []interface{}
}

type headingBuilder struct {
	depth      int
	hasContent bool
}

func newBuilder() *builder {
	return &builder{
		current: &node{},
	}
}

func (b *builder) push(x interface{}) {
	b.stack = append(b.stack, x)
}

func (b *builder) pop() interface{} {
	l := len(b.stack)
	x := b.stack[l-1]
	b.stack[l-1] = nil
	b.stack = b.stack[:l-1]
	return x
}

func (b *builder) top() interface{} {
	return b.stack[len(b.stack)-1]
}

func (b *builder) EnterHeading(c *parser.HeadingContext) {
	b.push(&headingBuilder{})
}

func (b *builder) EnterHeading_markup(c *parser.Heading_markupContext) {
	if hb := b.top().(*headingBuilder); !hb.hasContent {
		hb.depth++
	}
}

func (b *builder) ExitHeading_content(c *parser.Heading_contentContext) {
	b.top().(*headingBuilder).hasContent = true
}

func (b *builder) ExitHeading(c *parser.HeadingContext) {

	hb := b.pop().(*headingBuilder)

	trim := strings.Repeat("=", hb.depth)
	content := strings.TrimSpace(c.GetText())
	content = strings.TrimSuffix(strings.TrimPrefix(content, trim), trim)
	content = strings.TrimSpace(content)

	var typ nodeType
	switch hb.depth {
	case 1:
		typ = heading1Node
	case 2:
		typ = heading2Node
	case 3:
		typ = heading3Node
	case 4:
		typ = heading4Node
	case 5:
		typ = heading5Node
	default:
		typ = heading6Node
	}

	n := &node{
		nodeType: typ,
		parent:   b.current,
		value:    content,
	}
	b.current.children = append(b.current.children, n)
}

func (b *builder) EnterParagraph(c *parser.ParagraphContext) {
	b.current = ndp(paragraphNode, b.current)
}

func (b *builder) ExitParagraph(c *parser.ParagraphContext) {
	if b.current != nil && b.current.nodeType == paragraphNode {
		b.current = b.current.parent
	}
}

func (b *builder) EnterText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "EnterText_unformattedelement")
}

func (b *builder) ExitText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintf(os.Stderr, "ExitText_unformattedelement '%s'\n", c.GetText())
}

func (b *builder) EnterText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "EnterText_line")
}

func (b *builder) ExitText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "ExitText_line:", c.GetText())
}

func (b *builder) EnterText_formattedelement(c *parser.Text_formattedelementContext) {
	fmt.Fprintln(os.Stderr, "***EnterText_formattedelement")
}

func (b *builder) ExitText_formattedelement(c *parser.Text_formattedelementContext) {
	fmt.Fprintln(os.Stderr, "***ExitText_formattedelement")
}

func (b *builder) EnterItal_markup(c *parser.Ital_markupContext) {
	fmt.Fprintln(os.Stderr, "//EnterItal_markup")
}

func (b *builder) parse(data string) (*document, error) {

	input := antlr.NewInputStream(data)
	lexer := parser.NewCreole10Lexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	pa := parser.NewCreole10Parser(stream)
	pa.AddParseListener(b)
	//pa.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
	//pa.BuildParseTrees = true
	pa.Start()
	//antlr.ParseTreeWalkerDefault.Walk(p, tree)

	// TODO: Write own ErrorListener.

	doc := &document{root: b.current}

	return doc, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Maarten Everts. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gabi

import (
	"crypto/sha256"
	"encoding/asn1"
	"errors"
	"math/big"
)

// IssueCommitmentMessage encapsulates the messages sent by the receiver to the
// issuer in the second step of the issuance protocol.
type IssueCommitmentMessage struct {
	U         *big.Int  `json:"U"`
	Nonce2    *big.Int  `json:"n_2"`
	Proofs    ProofList `json:"combinedProofs"`
	ProofPjwt string    `json:"proofPJwt"`
}

// IssueSignatureMessage encapsulates the messages sent from the issuer to the
// reciver in the final step of the issuance protocol.
type IssueSignatureMessage struct {
	Proof     *ProofS      `json:"proof"`
	Signature *CLSignature `json:"signature"`
}

// commitmentToSecret produces a commitment to the provided secret
func commitmentToSecret(pk *PublicKey, secret *big.Int) (vPrime, U *big.Int) {
	vPrime, _ = RandomBigInt(pk.Params.LvPrime)
	// U = S^{vPrime} * R_0^{s}
	Sv := new(big.Int).Exp(pk.S, vPrime, pk.N)
	R0s := new(big.Int).Exp(pk.R[0], secret, pk.N)
	U = new(big.Int).Mul(Sv, R0s)
	U.Mod(U, pk.N)
	return
}

// NewCredentialBuilder creates a new credential builder. The resulting credential builder
// is already committed to the provided secret.
func NewCredentialBuilder(pk *PublicKey, context, secret *big.Int, nonce2 *big.Int) *CredentialBuilder {
	vPrime, U := commitmentToSecret(pk, secret)

	return &CredentialBuilder{
		pk:      pk,
		context: context,
		secret:  secret,
		vPrime:  vPrime,
		u:       U,
		uCommit: big.NewInt(1),
		nonce2:  nonce2,
	}
}

// CommitToSecretAndProve creates the response to the initial challenge nonce
// nonce1 sent by the issuer. The response consists of a commitment to the
// secret (set on creation of the builder, see NewBuilder) and a proof of
// correctness of this commitment.
func (b *CredentialBuilder) CommitToSecretAndProve(nonce1 *big.Int) *IssueCommitmentMessage {
	proofU := b.proveCommitment(b.u, nonce1)

	return &IssueCommitmentMessage{U: b.u, Proofs: ProofList{proofU}, Nonce2: b.nonce2}
}

// CreateIssueCommitmentMessage creates the IssueCommitmentMessage based on the
// provided prooflist, to be sent to the issuer.
func (b *CredentialBuilder) CreateIssueCommitmentMessage(proofs ProofList) *IssueCommitmentMessage {
	return &IssueCommitmentMessage{U: b.u, Proofs: proofs, Nonce2: b.nonce2}
}

var (
	// ErrIncorrectProofOfSignatureCorrectness is issued when the the proof of
	// correctness on the signature does not verify.
	ErrIncorrectProofOfSignatureCorrectness = errors.New("Proof of correctness on signature does not verify.")
	// ErrIncorrectAttributeSignature is issued when the signature on the
	// attributes is not correct.
	ErrIncorrectAttributeSignature = errors.New("The Signature on the attributes is not correct.")
)

// ConstructCredential creates a credential using the IssueSignatureMessage from
// the issuer and the content of the attributes.
func (b *CredentialBuilder) ConstructCredential(msg *IssueSignatureMessage, attributes []*big.Int) (*Credential, error) {
	if !msg.Proof.Verify(b.pk, msg.Signature, b.context, b.nonce2) {
		return nil, ErrIncorrectProofOfSignatureCorrectness
	}

	// Construct actual signature
	signature := &CLSignature{
		A: msg.Signature.A,
		E: msg.Signature.E,
		V: new(big.Int).Add(msg.Signature.V, b.vPrime),
	}
	if b.proofPcomm != nil {
		signature.KeyshareP = b.proofPcomm.P
	}

	// Verify signature
	exponents := make([]*big.Int, len(attributes)+1)
	exponents[0] = b.secret
	copy(exponents[1:], attributes)

	if !signature.Verify(b.pk, exponents) {
		return nil, ErrIncorrectAttributeSignature
	}
	return &Credential{Pk: b.pk, Signature: signature, Attributes: exponents}, nil
}

// intHashSha256 is a utility function compute the sha256 hash over a byte array
// and return this hash as a big.Int.
func intHashSha256(input []byte) *big.Int {
	h := sha256.New()
	h.Write(input)
	return new(big.Int).SetBytes(h.Sum(nil))
}

// hashCommit computes the sha256 hash over the asn1 representation of a slice
// of big integers and returns a positive big integer that can be represented
// with that hash.
func hashCommit(values []*big.Int, issig bool) *big.Int {
	// The first element is the number of elements
	var tmp []interface{}
	offset := 0
	if issig {
		tmp = make([]interface{}, len(values)+2)
		tmp[0] = true
		offset++
	} else {
		tmp = make([]interface{}, len(values)+1)
	}
	tmp[offset] = big.NewInt(int64(len(values)))
	offset++
	for i, v := range values {
		tmp[i+offset] = v
	}
	r, _ := asn1.Marshal(tmp)

	h := sha256.New()
	_, _ = h.Write(r)
	return new(big.Int).SetBytes(h.Sum(nil))
}

func (b *CredentialBuilder) proveCommitment(U, nonce1 *big.Int) *ProofU {
	sCommit, _ := RandomBigInt(b.pk.Params.LsCommit)
	vPrimeCommit, _ := RandomBigInt(b.pk.Params.LvPrimeCommit)

	// Ucommit = S^{vPrimeCommit} * R_0^{sCommit}
	Sv := new(big.Int).Exp(b.pk.S, vPrimeCommit, b.pk.N)
	R0s := new(big.Int).Exp(b.pk.R[0], sCommit, b.pk.N)
	Ucommit := new(big.Int).Mul(Sv, R0s)
	Ucommit.Mod(Ucommit, b.pk.N)

	c := hashCommit([]*big.Int{b.context, U, Ucommit, nonce1}, false)
	sResponse := new(big.Int).Mul(c, b.secret)
	sResponse.Add(sResponse, sCommit)

	vPrimeResponse := new(big.Int).Mul(c, b.vPrime)
	vPrimeResponse.Add(vPrimeResponse, vPrimeCommit)

	return &ProofU{U: U, C: c, VPrimeResponse: vPrimeResponse, SResponse: sResponse}
}

// CredentialBuilder is a temporary object to hold some state for the protocol
// that is used to create (build) a credential. It also implements the
// ProofBuilder interface.
type CredentialBuilder struct {
	secret       *big.Int
	vPrime       *big.Int
	vPrimeCommit *big.Int
	nonce2       *big.Int
	u            *big.Int
	uCommit      *big.Int
	skRandomizer *big.Int

	pk         *PublicKey
	context    *big.Int
	proofPcomm *ProofPCommitment
}

func (b *CredentialBuilder) MergeProofPCommitment(commitment *ProofPCommitment) {
	b.proofPcomm = commitment
	b.uCommit.Mod(
		b.uCommit.Mul(b.uCommit, commitment.Pcommit),
		b.pk.N,
	)
}

// PublicKey returns the Idemix public key against which the credential will verify.
func (b *CredentialBuilder) PublicKey() *PublicKey {
	return b.pk
}

// Commit commits to the secret (first) attribute using the provided randomizer.
func (b *CredentialBuilder) Commit(skRandomizer *big.Int) []*big.Int {
	b.skRandomizer = skRandomizer
	// vPrimeCommit
	b.vPrimeCommit, _ = RandomBigInt(b.pk.Params.LvPrimeCommit)

	// U_commit = U_commit * S^{v_prime_commit} * R_0^{s_commit}
	sv := new(big.Int).Exp(b.pk.S, b.vPrimeCommit, b.pk.N)
	r0s := new(big.Int).Exp(b.pk.R[0], b.skRandomizer, b.pk.N)
	b.uCommit.Mul(b.uCommit, sv).Mul(b.uCommit, r0s).Mod(b.uCommit, b.pk.N)

	ucomm := new(big.Int).Set(b.u)
	if b.proofPcomm != nil {
		ucomm.Mul(ucomm, b.proofPcomm.P).Mod(ucomm, b.pk.N)
	}
	return []*big.Int{ucomm, b.uCommit}
}

// CreateProof creates a (ProofU) Proof using the provided challenge.
func (b *CredentialBuilder) CreateProof(challenge *big.Int) Proof {
	sResponse := new(big.Int).Add(b.skRandomizer, new(big.Int).Mul(challenge, b.secret))
	vPrimeResponse := new(big.Int).Add(b.vPrimeCommit, new(big.Int).Mul(challenge, b.vPrime))

	return &ProofU{U: b.u, C: challenge, VPrimeResponse: vPrimeResponse, SResponse: sResponse}
}
<commit_msg>Implement json.Unmarshaler for ProofList<commit_after>// Copyright 2016 Maarten Everts. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gabi

import (
	"crypto/sha256"
	"encoding/asn1"
	"encoding/json"
	"errors"
	"math/big"
)

// IssueCommitmentMessage encapsulates the messages sent by the receiver to the
// issuer in the second step of the issuance protocol.
type IssueCommitmentMessage struct {
	U         *big.Int  `json:"U"`
	Nonce2    *big.Int  `json:"n_2"`
	Proofs    ProofList `json:"combinedProofs"`
	ProofPjwt string    `json:"proofPJwt"`
}

// UnmarshalJSON implements json.Unmarshaler (json's default unmarshaler
// is unable to handle a list of interfaces).
func (pl *ProofList) UnmarshalJSON(bytes []byte) error {
	if pl == nil || *pl == nil {
		*pl = []Proof{}
	}
	proofs := []Proof{}
	temp := []json.RawMessage{}
	if err := json.Unmarshal(bytes, &temp); err != nil {
		return err
	}
	for _, proofbytes := range temp {
		proofd := &ProofD{}
		if err := json.Unmarshal(proofbytes, proofd); err != nil {
			return err
		}
		if proofd.A != nil {
			proofs = append(proofs, proofd)
			continue
		}
		proofu := &ProofU{}
		if err := json.Unmarshal(proofbytes, proofu); err != nil {
			return err
		}
		if proofu.U != nil {
			proofs = append(proofs, proofu)
			continue
		}
		return errors.New("Unknown proof type found in ProofList")
	}
	return nil
}

// IssueSignatureMessage encapsulates the messages sent from the issuer to the
// reciver in the final step of the issuance protocol.
type IssueSignatureMessage struct {
	Proof     *ProofS      `json:"proof"`
	Signature *CLSignature `json:"signature"`
}

// commitmentToSecret produces a commitment to the provided secret
func commitmentToSecret(pk *PublicKey, secret *big.Int) (vPrime, U *big.Int) {
	vPrime, _ = RandomBigInt(pk.Params.LvPrime)
	// U = S^{vPrime} * R_0^{s}
	Sv := new(big.Int).Exp(pk.S, vPrime, pk.N)
	R0s := new(big.Int).Exp(pk.R[0], secret, pk.N)
	U = new(big.Int).Mul(Sv, R0s)
	U.Mod(U, pk.N)
	return
}

// NewCredentialBuilder creates a new credential builder. The resulting credential builder
// is already committed to the provided secret.
func NewCredentialBuilder(pk *PublicKey, context, secret *big.Int, nonce2 *big.Int) *CredentialBuilder {
	vPrime, U := commitmentToSecret(pk, secret)

	return &CredentialBuilder{
		pk:      pk,
		context: context,
		secret:  secret,
		vPrime:  vPrime,
		u:       U,
		uCommit: big.NewInt(1),
		nonce2:  nonce2,
	}
}

// CommitToSecretAndProve creates the response to the initial challenge nonce
// nonce1 sent by the issuer. The response consists of a commitment to the
// secret (set on creation of the builder, see NewBuilder) and a proof of
// correctness of this commitment.
func (b *CredentialBuilder) CommitToSecretAndProve(nonce1 *big.Int) *IssueCommitmentMessage {
	proofU := b.proveCommitment(b.u, nonce1)

	return &IssueCommitmentMessage{U: b.u, Proofs: ProofList{proofU}, Nonce2: b.nonce2}
}

// CreateIssueCommitmentMessage creates the IssueCommitmentMessage based on the
// provided prooflist, to be sent to the issuer.
func (b *CredentialBuilder) CreateIssueCommitmentMessage(proofs ProofList) *IssueCommitmentMessage {
	return &IssueCommitmentMessage{U: b.u, Proofs: proofs, Nonce2: b.nonce2}
}

var (
	// ErrIncorrectProofOfSignatureCorrectness is issued when the the proof of
	// correctness on the signature does not verify.
	ErrIncorrectProofOfSignatureCorrectness = errors.New("Proof of correctness on signature does not verify.")
	// ErrIncorrectAttributeSignature is issued when the signature on the
	// attributes is not correct.
	ErrIncorrectAttributeSignature = errors.New("The Signature on the attributes is not correct.")
)

// ConstructCredential creates a credential using the IssueSignatureMessage from
// the issuer and the content of the attributes.
func (b *CredentialBuilder) ConstructCredential(msg *IssueSignatureMessage, attributes []*big.Int) (*Credential, error) {
	if !msg.Proof.Verify(b.pk, msg.Signature, b.context, b.nonce2) {
		return nil, ErrIncorrectProofOfSignatureCorrectness
	}

	// Construct actual signature
	signature := &CLSignature{
		A: msg.Signature.A,
		E: msg.Signature.E,
		V: new(big.Int).Add(msg.Signature.V, b.vPrime),
	}
	if b.proofPcomm != nil {
		signature.KeyshareP = b.proofPcomm.P
	}

	// Verify signature
	exponents := make([]*big.Int, len(attributes)+1)
	exponents[0] = b.secret
	copy(exponents[1:], attributes)

	if !signature.Verify(b.pk, exponents) {
		return nil, ErrIncorrectAttributeSignature
	}
	return &Credential{Pk: b.pk, Signature: signature, Attributes: exponents}, nil
}

// intHashSha256 is a utility function compute the sha256 hash over a byte array
// and return this hash as a big.Int.
func intHashSha256(input []byte) *big.Int {
	h := sha256.New()
	h.Write(input)
	return new(big.Int).SetBytes(h.Sum(nil))
}

// hashCommit computes the sha256 hash over the asn1 representation of a slice
// of big integers and returns a positive big integer that can be represented
// with that hash.
func hashCommit(values []*big.Int, issig bool) *big.Int {
	// The first element is the number of elements
	var tmp []interface{}
	offset := 0
	if issig {
		tmp = make([]interface{}, len(values)+2)
		tmp[0] = true
		offset++
	} else {
		tmp = make([]interface{}, len(values)+1)
	}
	tmp[offset] = big.NewInt(int64(len(values)))
	offset++
	for i, v := range values {
		tmp[i+offset] = v
	}
	r, _ := asn1.Marshal(tmp)

	h := sha256.New()
	_, _ = h.Write(r)
	return new(big.Int).SetBytes(h.Sum(nil))
}

func (b *CredentialBuilder) proveCommitment(U, nonce1 *big.Int) *ProofU {
	sCommit, _ := RandomBigInt(b.pk.Params.LsCommit)
	vPrimeCommit, _ := RandomBigInt(b.pk.Params.LvPrimeCommit)

	// Ucommit = S^{vPrimeCommit} * R_0^{sCommit}
	Sv := new(big.Int).Exp(b.pk.S, vPrimeCommit, b.pk.N)
	R0s := new(big.Int).Exp(b.pk.R[0], sCommit, b.pk.N)
	Ucommit := new(big.Int).Mul(Sv, R0s)
	Ucommit.Mod(Ucommit, b.pk.N)

	c := hashCommit([]*big.Int{b.context, U, Ucommit, nonce1}, false)
	sResponse := new(big.Int).Mul(c, b.secret)
	sResponse.Add(sResponse, sCommit)

	vPrimeResponse := new(big.Int).Mul(c, b.vPrime)
	vPrimeResponse.Add(vPrimeResponse, vPrimeCommit)

	return &ProofU{U: U, C: c, VPrimeResponse: vPrimeResponse, SResponse: sResponse}
}

// CredentialBuilder is a temporary object to hold some state for the protocol
// that is used to create (build) a credential. It also implements the
// ProofBuilder interface.
type CredentialBuilder struct {
	secret       *big.Int
	vPrime       *big.Int
	vPrimeCommit *big.Int
	nonce2       *big.Int
	u            *big.Int
	uCommit      *big.Int
	skRandomizer *big.Int

	pk         *PublicKey
	context    *big.Int
	proofPcomm *ProofPCommitment
}

func (b *CredentialBuilder) MergeProofPCommitment(commitment *ProofPCommitment) {
	b.proofPcomm = commitment
	b.uCommit.Mod(
		b.uCommit.Mul(b.uCommit, commitment.Pcommit),
		b.pk.N,
	)
}

// PublicKey returns the Idemix public key against which the credential will verify.
func (b *CredentialBuilder) PublicKey() *PublicKey {
	return b.pk
}

// Commit commits to the secret (first) attribute using the provided randomizer.
func (b *CredentialBuilder) Commit(skRandomizer *big.Int) []*big.Int {
	b.skRandomizer = skRandomizer
	// vPrimeCommit
	b.vPrimeCommit, _ = RandomBigInt(b.pk.Params.LvPrimeCommit)

	// U_commit = U_commit * S^{v_prime_commit} * R_0^{s_commit}
	sv := new(big.Int).Exp(b.pk.S, b.vPrimeCommit, b.pk.N)
	r0s := new(big.Int).Exp(b.pk.R[0], b.skRandomizer, b.pk.N)
	b.uCommit.Mul(b.uCommit, sv).Mul(b.uCommit, r0s).Mod(b.uCommit, b.pk.N)

	ucomm := new(big.Int).Set(b.u)
	if b.proofPcomm != nil {
		ucomm.Mul(ucomm, b.proofPcomm.P).Mod(ucomm, b.pk.N)
	}
	return []*big.Int{ucomm, b.uCommit}
}

// CreateProof creates a (ProofU) Proof using the provided challenge.
func (b *CredentialBuilder) CreateProof(challenge *big.Int) Proof {
	sResponse := new(big.Int).Add(b.skRandomizer, new(big.Int).Mul(challenge, b.secret))
	vPrimeResponse := new(big.Int).Add(b.vPrimeCommit, new(big.Int).Mul(challenge, b.vPrime))

	return &ProofU{U: b.u, C: challenge, VPrimeResponse: vPrimeResponse, SResponse: sResponse}
}
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"io"
	"strings"

	"github.com/glycerine/rbuf"
	"github.com/orktes/orlang/parser/ast"
	"github.com/orktes/orlang/parser/parser"
)

type HistoryReader struct {
	io.Reader
	column int
	line   int
	buf    *rbuf.FixedSizeRingBuf
}

func NewHistoryReader(in io.Reader) (r *HistoryReader) {
	r = &HistoryReader{
		buf: rbuf.NewFixedSizeRingBuf(1024 * 5), // TODO figure out proper size
	}
	r.Reader = io.TeeReader(in, r)
	return
}

func (hr *HistoryReader) Write(p []byte) (n int, err error) {
	for _, b := range p {
		hr.column++
		if b == byte('\n') {
			hr.line++
			hr.column = 0
		}
	}

	return hr.buf.Write(p)
}

func (hr *HistoryReader) FindLineForPosition(pos ast.Position) string {
	line := hr.line
	bytes := hr.buf.Bytes()
	correctLine := false
	correctLineEndIndex := 0

	for i := len(bytes) - 1; i >= 0; i-- {
		b := bytes[i]
		if correctLine == false && line == pos.Line {
			correctLineEndIndex = i + 1
			correctLine = true
		}
		if b == '\n' || i == 0 {
			if correctLine {
				if i != 0 {
					i++
				}
				return string(bytes[i:correctLineEndIndex])
			}
			line--
		}
	}

	return ""
}

func (hr *HistoryReader) FormatParseError(filePath string, pos ast.Position, err string) string {
	line := hr.FindLineForPosition(pos)
	if line != "" {
		return fmt.Sprintf(
			`%s:%d:%d
----------------------------------------------------------
%s
%s
%s
----------------------------------------------------------`, filePath, pos.Line+1, pos.Column+1, strings.Replace(line, "\t", " ", -1), pointer(pos.Column), pad(pos.Column-int(len(err)/2), err))
	}
	return fmt.Sprintf("%s %#v %s", filePath, pos, err)
}

func (hr *HistoryReader) FormatError(filePath string, err error) string {
	if posErr, ok := err.(*parser.PosError); ok && hr != nil {
		return hr.FormatParseError(filePath, posErr.Position, posErr.Message)
	}
	return fmt.Sprintf("%s:%s", filePath, err.Error())
}

func pad(padding int, str string) (res string) {
	if padding < 0 {
		padding = 0
	}
	res = strings.Repeat(" ", padding)
	return res + str
}

func pointer(padding int) (res string) {
	return pad(padding, "^")
}
<commit_msg>Smaller ring buffer size<commit_after>package util

import (
	"fmt"
	"io"
	"strings"

	"github.com/glycerine/rbuf"
	"github.com/orktes/orlang/parser/ast"
	"github.com/orktes/orlang/parser/parser"
)

type HistoryReader struct {
	io.Reader
	column int
	line   int
	buf    *rbuf.FixedSizeRingBuf
}

func NewHistoryReader(in io.Reader) (r *HistoryReader) {
	r = &HistoryReader{
		buf: rbuf.NewFixedSizeRingBuf(1024), // TODO figure out proper size
	}
	r.Reader = io.TeeReader(in, r)
	return
}

func (hr *HistoryReader) Write(p []byte) (n int, err error) {
	for _, b := range p {
		hr.column++
		if b == byte('\n') {
			hr.line++
			hr.column = 0
		}
	}

	return hr.buf.Write(p)
}

func (hr *HistoryReader) FindLineForPosition(pos ast.Position) string {
	line := hr.line
	bytes := hr.buf.Bytes()
	correctLine := false
	correctLineEndIndex := 0

	for i := len(bytes) - 1; i >= 0; i-- {
		b := bytes[i]
		if correctLine == false && line == pos.Line {
			correctLineEndIndex = i + 1
			correctLine = true
		}
		if b == '\n' || i == 0 {
			if correctLine {
				if i != 0 {
					i++
				}
				return string(bytes[i:correctLineEndIndex])
			}
			line--
		}
	}

	return ""
}

func (hr *HistoryReader) FormatParseError(filePath string, pos ast.Position, err string) string {
	line := hr.FindLineForPosition(pos)
	if line != "" {
		return fmt.Sprintf(
			`%s:%d:%d
----------------------------------------------------------
%s
%s
%s
----------------------------------------------------------`, filePath, pos.Line+1, pos.Column+1, strings.Replace(line, "\t", " ", -1), pointer(pos.Column), pad(pos.Column-int(len(err)/2), err))
	}
	return fmt.Sprintf("%s %#v %s", filePath, pos, err)
}

func (hr *HistoryReader) FormatError(filePath string, err error) string {
	if posErr, ok := err.(*parser.PosError); ok && hr != nil {
		return hr.FormatParseError(filePath, posErr.Position, posErr.Message)
	}
	return fmt.Sprintf("%s:%s", filePath, err.Error())
}

func pad(padding int, str string) (res string) {
	if padding < 0 {
		padding = 0
	}
	res = strings.Repeat(" ", padding)
	return res + str
}

func pointer(padding int) (res string) {
	return pad(padding, "^")
}
<|endoftext|>


<commit_before>package board

import (
	"color"
	"errors"
	"fmt"
	"matrix"
	"piece"
	"point"
)

type Board struct {
	matrix matrix.Matrix
	first  [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board *Board) Print() {
	fmt.Print(" ")
	for i := 0; i < 8; i++ {
		fmt.Printf(" %c", 'a'+i)
	}
	fmt.Println()

	for i := 0; i < 8; i++ {
		fmt.Print(" +")
		for j := 0; j < 8; j++ {
			fmt.Print("-+")
		}
		fmt.Println()
		fmt.Printf("%d|", 8-i)
		for j := 0; j < 8; j++ {
			fmt.Printf("%c|", board.matrix[i][j])
		}
		fmt.Println(8 - i)
	}
	fmt.Print(" +")
	for i := 0; i < 8; i++ {
		fmt.Print("-+")
	}
	fmt.Println()

	fmt.Print(" ")
	for i := 0; i < 8; i++ {
		fmt.Printf(" %c", 'a'+i)
	}
	fmt.Println()
}

func (board *Board) Move(from, to point.Point, c color.Color) error {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return errors.New("out of board")
	}

	fsymbol := board.matrix[from.Y][from.X]
	// tsymbol := board.matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.matrix[to.Y][to.X])
	diff := point.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return errors.New("cannot move this piece")
	}

	fpiece := piece.WhichPiece(fsymbol)
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X])
	existBarrier := board.matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return errors.New("cannot move this piece to that point")
	}

	board.matrix[to.Y][to.X] = board.matrix[from.Y][from.X]
	board.matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false

	return nil
}
<commit_msg>Check castling can be done<commit_after>package board

import (
	"color"
	"errors"
	"fmt"
	"matrix"
	"piece"
	"point"
)

type Board struct {
	matrix matrix.Matrix
	first  [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board *Board) Print() {
	fmt.Print(" ")
	for i := 0; i < 8; i++ {
		fmt.Printf(" %c", 'a'+i)
	}
	fmt.Println()

	for i := 0; i < 8; i++ {
		fmt.Print(" +")
		for j := 0; j < 8; j++ {
			fmt.Print("-+")
		}
		fmt.Println()
		fmt.Printf("%d|", 8-i)
		for j := 0; j < 8; j++ {
			fmt.Printf("%c|", board.matrix[i][j])
		}
		fmt.Println(8 - i)
	}
	fmt.Print(" +")
	for i := 0; i < 8; i++ {
		fmt.Print("-+")
	}
	fmt.Println()

	fmt.Print(" ")
	for i := 0; i < 8; i++ {
		fmt.Printf(" %c", 'a'+i)
	}
	fmt.Println()
}

func (board *Board) CanCastling(from, to point.Point) bool {
	diff := from.Diff(to)
	rfrom := from
	rto := to

	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}
	fsymbol := board.matrix[rfrom.Y][rfrom.X]
	if piece.Rook.IsSymbol(fsymbol) == false {
		return false
	} else if board.first[rfrom.Y][rfrom.X] == false {
		return false
	} else if board.matrix.ExistBarrier(rfrom, rto) == false {
		return false
	}
	return true
}

func (board *Board) Move(from, to point.Point, c color.Color) error {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return errors.New("out of board")
	}

	fsymbol := board.matrix[from.Y][from.X]
	// tsymbol := board.matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.matrix[to.Y][to.X])
	diff := point.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return errors.New("cannot move this piece")
	}

	fpiece := piece.WhichPiece(fsymbol)
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X])
	existBarrier := board.matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return errors.New("cannot move this piece to that point")
	} else if piece.King.IsSymbol(fsymbol) && board.CanCastling(from, to) == false {
		return errors.New("cannot move this piece to that point")
	}

	board.matrix[to.Y][to.X] = board.matrix[from.Y][from.X]
	board.matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false

	return nil
}
<|endoftext|>


<commit_before>package test

import (
	"encoding/base64"
	"io/ioutil"
	"os"
	"testing"

	_ "image/png"

	"github.com/signintech/pdft"
)

func TestInsertImg(t *testing.T) {

	//source := "./pdf/pdf_from_docx_with_f.pdf"
	source := "./pdf/pdf_from_docx.pdf"
	//source := "./pdf/pdf_from_gopdf.pdf"
	//signature := "./img/gopher.png"
	signature := "./img/gopher2.jpg"
	target := "./out/pdf_from_docx_out.pdf"

	var ipdf pdft.PDFt
	err := ipdf.Open(source)
	if err != nil {
		t.Error("Couldn't open pdf.")
	}

	encoded, data, err := readImg(signature)
	if err != nil {
		t.Error("Couldn't read image")
	}

	/*err = ipdf.InsertImgBase64(encoded, 1, 100, 200, 100, 100)
	if err != nil {
		t.Error("Couldn't insert image base64")
	}

	*/
	_ = data
	_ = encoded
	err = ipdf.InsertImg(data, 1, 100.0, 100.0, 100, 100)
	if err != nil {
		t.Error("Couldn't insert image")
	}

	err = ipdf.Save(target)
	if err != nil {
		t.Error("Couldn't save pdf.")
	}
}

func readImg(path string) (string, []byte, error) {

	f, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return "", nil, err
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	if err != nil {
		return "", nil, err
	}

	encoded := base64.StdEncoding.EncodeToString(data)
	return encoded, data, nil
}
<commit_msg>add test case<commit_after>package test

import (
	"encoding/base64"
	"io/ioutil"
	"os"
	"testing"

	_ "image/png"

	"github.com/signintech/pdft"
)

func TestInsertImgDocx(t *testing.T) {
	testWriteImg(t, "./pdf/pdf_from_docx.pdf", "./out/pdf_from_docx_out.pdf")
}

func TestInsertImgChromePdf(t *testing.T) {
	testWriteImg(t, "./pdf/pdf_from_chrome_50_linux64.pdf", "./out/pdf_from_chrome_50_linux64_out.pdf")
}

func testWriteImg(t *testing.T, source string, target string) {
	//source := "./pdf/pdf_from_docx_with_f.pdf"
	//source := "./pdf/pdf_from_gopdf.pdf"
	//signature := "./img/gopher.png"
	signature := "./img/gopher2.jpg"

	var ipdf pdft.PDFt
	err := ipdf.Open(source)
	if err != nil {
		t.Error("Couldn't open pdf.")
		return
	}

	encoded, data, err := readImg(signature)
	if err != nil {
		t.Error("Couldn't read image")
		return
	}

	/*err = ipdf.InsertImgBase64(encoded, 1, 100, 200, 100, 100)
	if err != nil {
		t.Error("Couldn't insert image base64")
	}

	*/
	_ = data
	_ = encoded
	err = ipdf.InsertImg(data, 1, 100.0, 100.0, 100, 100)
	if err != nil {
		t.Errorf("Couldn't insert image %+v", err)
		return
	}

	err = ipdf.Save(target)
	if err != nil {
		t.Errorf("Couldn't save pdf. %+v", err)
		return
	}
}

func readImg(path string) (string, []byte, error) {

	f, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return "", nil, err
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	if err != nil {
		return "", nil, err
	}

	encoded := base64.StdEncoding.EncodeToString(data)
	return encoded, data, nil
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"log"
	"time"
)

type mockLoader struct {
	data map[string]interface{}
}

func NewMockLoader(data map[string]interface{}) Loader {
	return &mockLoader{data}
}
func (m *mockLoader) Import(data []byte) error {
	return nil
}
func (m *mockLoader) Initialize() error {
	return nil
}
func (m *mockLoader) Get(key string) ([]byte, error) {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.([]byte); ok {
			return result, nil
		}
	}
	return nil, fmt.Errorf("Key (%s) not set in mock.", key)
}

func (m *mockLoader) MustGetString(key string) string {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(string); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return ""
}

func (m *mockLoader) MustGetBool(key string) bool {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(bool); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return false
}

func (m *mockLoader) MustGetInt(key string) int {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(int); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return 0
}

func (m *mockLoader) MustGetDuration(key string) time.Duration {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(time.Duration); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return 0
}
<commit_msg>fixing mock<commit_after>package client

import (
	"fmt"
	"log"
	"time"

	"github.com/divideandconquer/go-consul-client/src/config"
)

type mockLoader struct {
	data map[string]interface{}
}

func NewMockLoader(data map[string]interface{}) config.Loader {
	return &mockLoader{data}
}
func (m *mockLoader) Import(data []byte) error {
	return nil
}
func (m *mockLoader) Initialize() error {
	return nil
}
func (m *mockLoader) Get(key string) ([]byte, error) {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.([]byte); ok {
			return result, nil
		}
	}
	return nil, fmt.Errorf("Key (%s) not set in mock.", key)
}

func (m *mockLoader) MustGetString(key string) string {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(string); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return ""
}

func (m *mockLoader) MustGetBool(key string) bool {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(bool); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return false
}

func (m *mockLoader) MustGetInt(key string) int {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(int); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return 0
}

func (m *mockLoader) MustGetDuration(key string) time.Duration {
	if ret, ok := m.data[key]; ok {
		if result, ok := ret.(time.Duration); ok {
			return result
		}
	}
	log.Fatalf("Key (%s) not set in mock", key)
	return 0
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt";
	"go/ast";
	"go/printer";
	"os";
	"strings";
)

func creat(name string) *os.File {
	f, err := os.Open(name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0666);
	if err != nil {
		fatal("%s", err);
	}
	return f;
}

// writeOutput creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Prog) writeOutput(srcfile string) {
	pkgroot := os.Getenv("GOROOT") + "/pkg/" + os.Getenv("GOOS") + "_" + os.Getenv("GOARCH");

	base := srcfile;
	if strings.HasSuffix(base, ".go") {
		base = base[0 : len(base)-3];
	}
	fgo1 := creat(base + ".cgo1.go");
	fgo2 := creat(base + ".cgo2.go");
	fc := creat(base + ".cgo3.c");
	fgcc := creat(base + ".cgo4.c");

	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n");
	fmt.Fprintf(fgo1, "//line %s:1\n", srcfile);
	printer.Fprint(fgo1, p.AST);

	// Write second Go output: definitions of _C_xxx.
	// In a separate file so that the import of "unsafe" does not
	// pollute the original file.
	fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n");
	fmt.Fprintf(fgo2, "package %s\n\n", p.Package);
	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n");

	for name, def := range p.Typedef {
		fmt.Fprintf(fgo2, "type %s ", name);
		printer.Fprint(fgo2, def);
		fmt.Fprintf(fgo2, "\n");
	}
	fmt.Fprintf(fgo2, "type _C_void [0]byte\n");

	// While we process the vars and funcs, also write 6c and gcc output.
	// Gcc output starts with the preamble.
	fmt.Fprintf(fgcc, "%s\n", p.Preamble);
	fmt.Fprintf(fgcc, "%s\n", gccProlog);

	fmt.Fprintf(fc, cProlog, pkgroot, pkgroot, pkgroot, pkgroot, p.Package, p.Package);

	for name, def := range p.Vardef {
		fmt.Fprintf(fc, "#pragma dynld %s·_C_%s %s \"%s/%s_%s.so\"\n", p.Package, name, name, pkgroot, p.PackagePath, base);
		fmt.Fprintf(fgo2, "var _C_%s ", name);
		printer.Fprint(fgo2, &ast.StarExpr{X: def.Go});
		fmt.Fprintf(fgo2, "\n");
	}
	fmt.Fprintf(fc, "\n");

	for name, def := range p.Funcdef {
		// Go func declaration.
		d := &ast.FuncDecl{
			Name: &ast.Ident{Value: "_C_"+name},
			Type: def.Go,
		};
		printer.Fprint(fgo2, d);
		fmt.Fprintf(fgo2, "\n");

		if name == "CString" || name == "GoString" {
			// The builtins are already defined in the C prolog.
			continue;
		}

		// Construct a gcc struct matching the 6c argument frame.
		// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
		// These assumptions are checked by the gccProlog.
		// Also assumes that 6c convention is to word-align the
		// input and output parameters.
		structType := "struct {\n";
		off := int64(0);
		npad := 0;
		for i, t := range def.Params {
			if off % t.Align != 0 {
				pad := t.Align - off % t.Align;
				structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
				off += pad;
				npad++;
			}
			structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i);
			off += t.Size;
		}
		if off % p.PtrSize != 0 {
			pad := p.PtrSize - off % p.PtrSize;
			structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
			off += pad;
			npad++;
		}
		if t := def.Result; t != nil {
			if off % t.Align != 0 {
				pad := t.Align - off % t.Align;
				structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
				off += pad;
				npad++;
			}
			structType += fmt.Sprintf("\t\t%s r;\n", t.C);
			off += t.Size;
		}
		if off % p.PtrSize != 0 {
			pad := p.PtrSize - off % p.PtrSize;
			structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
			off += pad;
			npad++;
		}
		if len(def.Params) == 0 && def.Result == nil {
			structType += "\t\tchar unused;\n";	// avoid empty struct
			off++;
		}
		structType += "\t}";
		argSize := off;

		// C wrapper calls into gcc, passing a pointer to the argument frame.
		// Also emit #pragma to get a pointer to the gcc wrapper.
		fmt.Fprintf(fc, "#pragma dynld _cgo_%s _cgo_%s \"%s/%s_%s.so\"\n", name, name, pkgroot, p.PackagePath, base);
		fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name);
		fmt.Fprintf(fc, "\n");
		fmt.Fprintf(fc, "void\n");
		fmt.Fprintf(fc, "%s·_C_%s(struct{uint8 x[%d];}p)\n", p.Package, name, argSize);
		fmt.Fprintf(fc, "{\n");
		fmt.Fprintf(fc, "\tcgocall(_cgo_%s, &p);\n", name);
		fmt.Fprintf(fc, "}\n");
		fmt.Fprintf(fc, "\n");

		// Gcc wrapper unpacks the C argument struct
		// and calls the actual C function.
		fmt.Fprintf(fgcc, "void\n");
		fmt.Fprintf(fgcc, "_cgo_%s(void *v)\n", name);
		fmt.Fprintf(fgcc, "{\n");
		fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType);
		fmt.Fprintf(fgcc, "\t");
		if def.Result != nil {
			fmt.Fprintf(fgcc, "a->r = ");
		}
		fmt.Fprintf(fgcc, "%s(", name);
		for i := range def.Params {
			if i > 0 {
				fmt.Fprintf(fgcc, ", ");
			}
			fmt.Fprintf(fgcc, "a->p%d", i);
		}
		fmt.Fprintf(fgcc, ");\n");
		fmt.Fprintf(fgcc, "}\n");
		fmt.Fprintf(fgcc, "\n");
	}

	fgo1.Close();
	fgo2.Close();
	fc.Close();
	fgcc.Close();
}

const gccProlog = `
// Usual nonsense: if x and y are not equal, the type will be invalid
// (have a negative array count) and an inscrutable error will come
// out of the compiler and hopefully mention "name".
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];

// Check at compile time that the sizes we use match our expectations.
#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)

__cgo_size_assert(char, 1)
__cgo_size_assert(short, 2)
__cgo_size_assert(int, 4)
typedef long long __cgo_long_long;
__cgo_size_assert(__cgo_long_long, 8)
__cgo_size_assert(float, 4)
__cgo_size_assert(double, 8)
`

const builtinProlog = `
typedef struct { char *p; int n; } _GoString_;
_GoString_ GoString(char *p);
char *CString(_GoString_);
`

const cProlog = `
#include "runtime.h"
#include "cgocall.h"

#pragma dynld initcgo initcgo "%s/libcgo.so"
#pragma dynld libcgo_thread_start libcgo_thread_start "%s/libcgo.so"
#pragma dynld _cgo_malloc _cgo_malloc "%s/libcgo.so"
#pragma dynld _cgo_free free "%s/libcgo.so"

void
%s·_C_GoString(int8 *p, String s)
{
	s = gostring((byte*)p);
	FLUSH(&s);
}

void
%s·_C_CString(String s, int8 *p)
{
	p = cmalloc(s.len+1);
	mcpy((byte*)p, s.str, s.len);
	p[s.len] = 0;
	FLUSH(&p);
}
`
<commit_msg>Hack to make cgo's generated go code compile when there are no unsafe.Pointer references inside the C declarations.<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt";
	"go/ast";
	"go/printer";
	"os";
	"strings";
)

func creat(name string) *os.File {
	f, err := os.Open(name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0666);
	if err != nil {
		fatal("%s", err);
	}
	return f;
}

// writeOutput creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Prog) writeOutput(srcfile string) {
	pkgroot := os.Getenv("GOROOT") + "/pkg/" + os.Getenv("GOOS") + "_" + os.Getenv("GOARCH");

	base := srcfile;
	if strings.HasSuffix(base, ".go") {
		base = base[0 : len(base)-3];
	}
	fgo1 := creat(base + ".cgo1.go");
	fgo2 := creat(base + ".cgo2.go");
	fc := creat(base + ".cgo3.c");
	fgcc := creat(base + ".cgo4.c");

	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n");
	fmt.Fprintf(fgo1, "//line %s:1\n", srcfile);
	printer.Fprint(fgo1, p.AST, 0, 8, nil);

	// Write second Go output: definitions of _C_xxx.
	// In a separate file so that the import of "unsafe" does not
	// pollute the original file.
	fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n");
	fmt.Fprintf(fgo2, "package %s\n\n", p.Package);
	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n");
	fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n");

	for name, def := range p.Typedef {
		fmt.Fprintf(fgo2, "type %s ", name);
		printer.Fprint(fgo2, def, 0, 8, nil);
		fmt.Fprintf(fgo2, "\n");
	}
	fmt.Fprintf(fgo2, "type _C_void [0]byte\n");

	// While we process the vars and funcs, also write 6c and gcc output.
	// Gcc output starts with the preamble.
	fmt.Fprintf(fgcc, "%s\n", p.Preamble);
	fmt.Fprintf(fgcc, "%s\n", gccProlog);

	fmt.Fprintf(fc, cProlog, pkgroot, pkgroot, pkgroot, pkgroot, p.Package, p.Package);

	for name, def := range p.Vardef {
		fmt.Fprintf(fc, "#pragma dynld %s·_C_%s %s \"%s/%s_%s.so\"\n", p.Package, name, name, pkgroot, p.PackagePath, base);
		fmt.Fprintf(fgo2, "var _C_%s ", name);
		printer.Fprint(fgo2, &ast.StarExpr{X: def.Go}, 0, 8, nil);
		fmt.Fprintf(fgo2, "\n");
	}
	fmt.Fprintf(fc, "\n");

	for name, def := range p.Funcdef {
		// Go func declaration.
		d := &ast.FuncDecl{
			Name: &ast.Ident{Value: "_C_"+name},
			Type: def.Go,
		};
		printer.Fprint(fgo2, d, 0, 8, nil);
		fmt.Fprintf(fgo2, "\n");

		if name == "CString" || name == "GoString" {
			// The builtins are already defined in the C prolog.
			continue;
		}

		// Construct a gcc struct matching the 6c argument frame.
		// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
		// These assumptions are checked by the gccProlog.
		// Also assumes that 6c convention is to word-align the
		// input and output parameters.
		structType := "struct {\n";
		off := int64(0);
		npad := 0;
		for i, t := range def.Params {
			if off % t.Align != 0 {
				pad := t.Align - off % t.Align;
				structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
				off += pad;
				npad++;
			}
			structType += fmt.Sprintf("\t\t%s p%d;\n", t.C, i);
			off += t.Size;
		}
		if off % p.PtrSize != 0 {
			pad := p.PtrSize - off % p.PtrSize;
			structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
			off += pad;
			npad++;
		}
		if t := def.Result; t != nil {
			if off % t.Align != 0 {
				pad := t.Align - off % t.Align;
				structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
				off += pad;
				npad++;
			}
			structType += fmt.Sprintf("\t\t%s r;\n", t.C);
			off += t.Size;
		}
		if off % p.PtrSize != 0 {
			pad := p.PtrSize - off % p.PtrSize;
			structType += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad);
			off += pad;
			npad++;
		}
		if len(def.Params) == 0 && def.Result == nil {
			structType += "\t\tchar unused;\n";	// avoid empty struct
			off++;
		}
		structType += "\t}";
		argSize := off;

		// C wrapper calls into gcc, passing a pointer to the argument frame.
		// Also emit #pragma to get a pointer to the gcc wrapper.
		fmt.Fprintf(fc, "#pragma dynld _cgo_%s _cgo_%s \"%s/%s_%s.so\"\n", name, name, pkgroot, p.PackagePath, base);
		fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name);
		fmt.Fprintf(fc, "\n");
		fmt.Fprintf(fc, "void\n");
		fmt.Fprintf(fc, "%s·_C_%s(struct{uint8 x[%d];}p)\n", p.Package, name, argSize);
		fmt.Fprintf(fc, "{\n");
		fmt.Fprintf(fc, "\tcgocall(_cgo_%s, &p);\n", name);
		fmt.Fprintf(fc, "}\n");
		fmt.Fprintf(fc, "\n");

		// Gcc wrapper unpacks the C argument struct
		// and calls the actual C function.
		fmt.Fprintf(fgcc, "void\n");
		fmt.Fprintf(fgcc, "_cgo_%s(void *v)\n", name);
		fmt.Fprintf(fgcc, "{\n");
		fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType);
		fmt.Fprintf(fgcc, "\t");
		if def.Result != nil {
			fmt.Fprintf(fgcc, "a->r = ");
		}
		fmt.Fprintf(fgcc, "%s(", name);
		for i := range def.Params {
			if i > 0 {
				fmt.Fprintf(fgcc, ", ");
			}
			fmt.Fprintf(fgcc, "a->p%d", i);
		}
		fmt.Fprintf(fgcc, ");\n");
		fmt.Fprintf(fgcc, "}\n");
		fmt.Fprintf(fgcc, "\n");
	}

	fgo1.Close();
	fgo2.Close();
	fc.Close();
	fgcc.Close();
}

const gccProlog = `
// Usual nonsense: if x and y are not equal, the type will be invalid
// (have a negative array count) and an inscrutable error will come
// out of the compiler and hopefully mention "name".
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];

// Check at compile time that the sizes we use match our expectations.
#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)

__cgo_size_assert(char, 1)
__cgo_size_assert(short, 2)
__cgo_size_assert(int, 4)
typedef long long __cgo_long_long;
__cgo_size_assert(__cgo_long_long, 8)
__cgo_size_assert(float, 4)
__cgo_size_assert(double, 8)
`

const builtinProlog = `
typedef struct { char *p; int n; } _GoString_;
_GoString_ GoString(char *p);
char *CString(_GoString_);
`

const cProlog = `
#include "runtime.h"
#include "cgocall.h"

#pragma dynld initcgo initcgo "%s/libcgo.so"
#pragma dynld libcgo_thread_start libcgo_thread_start "%s/libcgo.so"
#pragma dynld _cgo_malloc _cgo_malloc "%s/libcgo.so"
#pragma dynld _cgo_free free "%s/libcgo.so"

void
%s·_C_GoString(int8 *p, String s)
{
	s = gostring((byte*)p);
	FLUSH(&s);
}

void
%s·_C_CString(String s, int8 *p)
{
	p = cmalloc(s.len+1);
	mcpy((byte*)p, s.str, s.len);
	p[s.len] = 0;
	FLUSH(&p);
}
`
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/gorilla/mux"
	"github.com/vmihailenco/redis/v2"
)

var config Config
var client *redis.Client

type Config struct {
	Port      string
	RedisURL  string
	Retention int64
}

type Check struct {
	Id  string `json:"id"`
	Url string `json:"url"`
}

type Measurement struct {
	Check             Check   `json:"check"`
	Id                string  `json:"id"`
	Location          string  `json:"location"`
	T                 int     `json:"t"`
	ExitStatus        int     `json:"exit_status"`
	HttpStatus        int     `json:"http_status,omitempty"`
	LocalIp           string  `json:"local_ip,omitempty"`
	PrimaryIp         string  `json:"primary_ip,omitempty"`
	NameLookupTime    float64 `json:"namelookup_time,omitempty"`
	ConnectTime       float64 `json:"connect_time,omitempty"`
	StartTransferTime float64 `json:"starttransfer_time,omitempty"`
	TotalTime         float64 `json:"total_time,omitempty"`
	SizeDownload      float64 `json:"size_download,omitempty"`
}

func (m *Measurement) record() {
	s, _ := json.Marshal(m)
	z := redis.Z{Score: float64(m.T), Member: string(s)}
	r := client.ZAdd(getRedisKey(m.Check.Id), z)
	if r.Err() != nil {
		log.Fatalf("Error while recording measuremnt %s: %v\n", m.Id, r.Err())
	}
}

func trimMeasurements(check_id string, seconds int64) {
	now := time.Now()
	epoch := now.Unix() - seconds
	r := client.ZRemRangeByScore(getRedisKey(check_id), "-inf", strconv.FormatInt(epoch, 10))
	if r.Err() != nil {
		log.Fatalf("Error while trimming check_id %s: %v\n", check_id, r.Err())
	}
}

func getRedisKey(check_id string) string {
	return "measurements:" + check_id
}

func getMeasurementsByRange(check_id string, r int64) []Measurement {
	now := time.Now()
	from := now.Unix() - r

	return getMeasurementsFrom(check_id, from)
}

func getMeasurementsFrom(check_id string, from int64) []Measurement {
	vals, err := client.ZRevRangeByScore(getRedisKey(check_id), redis.ZRangeByScore{
		Min: strconv.FormatInt(from, 10),
		Max: "+inf",
	}).Result()

	if err != nil {
		panic(err)
	}

	measurements := make([]Measurement, 0, 100)

	for _, v := range vals {
		var m Measurement
		json.Unmarshal([]byte(v), &m)
		measurements = append(measurements, m)
	}

	return measurements
}

func getFormValueWithDefault(req *http.Request, key string, def string) string {
	s := req.FormValue(key)
	if s != "" {
		return s
	} else {
		return def
	}
}

func getMeasurementsHandler(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	check_id := vars["check_id"]
	r_s := getFormValueWithDefault(req, "range", "10")

	r, err := strconv.ParseInt(r_s, 10, 64)
	if err != nil {
		panic(nil)
	}
	res.Header().Set("Content-Type", "application/json")
	json.NewEncoder(res).Encode(getMeasurementsByRange(check_id, r))
}

func postMeasurementsHandler(res http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)
	measurements := make([]Measurement, 0, 100)

	err := decoder.Decode(&measurements)
	if err != nil {
		panic(err)
	}

	for _, m := range measurements {
		m.record()
		trimMeasurements(m.Check.Id, config.Retention)
	}

	log.Printf("fn=post_measurements count=%d\n", len(measurements))
}

func connectToRedis(config Config) {
	u, err := url.Parse(config.RedisURL)
	if err != nil {
		panic(err)
	}

	client = redis.NewTCPClient(&redis.Options{
		Addr:     u.Host,
		Password: "", // no password set
		DB:       0,  // use default DB
	})
}

func main() {
	config = Config{}
	flag.StringVar(&config.Port, "port", "5000", "port the HTTP server should bind to")
	flag.StringVar(&config.RedisURL, "redis_url", "redis://localhost:6379", "redis url")
	flag.Int64Var(&config.Retention, "retention", 60, "second of each measurement to keep")
	flag.Parse()

	connectToRedis(config)

	r := mux.NewRouter()

	r.HandleFunc("/checks/{check_id}/measurements", getMeasurementsHandler).Methods("GET")
	r.HandleFunc("/measurements", postMeasurementsHandler).Methods("POST")
	http.Handle("/", r)

	log.Printf("fn=main listening=true port=%s\n", config.Port)

	err := http.ListenAndServe(":"+config.Port, nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Favor checkID over check_id.<commit_after>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/gorilla/mux"
	"github.com/vmihailenco/redis/v2"
)

var config Config
var client *redis.Client

type Config struct {
	Port      string
	RedisURL  string
	Retention int64
}

type Check struct {
	Id  string `json:"id"`
	Url string `json:"url"`
}

type Measurement struct {
	Check             Check   `json:"check"`
	Id                string  `json:"id"`
	Location          string  `json:"location"`
	T                 int     `json:"t"`
	ExitStatus        int     `json:"exit_status"`
	HttpStatus        int     `json:"http_status,omitempty"`
	LocalIp           string  `json:"local_ip,omitempty"`
	PrimaryIp         string  `json:"primary_ip,omitempty"`
	NameLookupTime    float64 `json:"namelookup_time,omitempty"`
	ConnectTime       float64 `json:"connect_time,omitempty"`
	StartTransferTime float64 `json:"starttransfer_time,omitempty"`
	TotalTime         float64 `json:"total_time,omitempty"`
	SizeDownload      float64 `json:"size_download,omitempty"`
}

func (m *Measurement) record() {
	s, _ := json.Marshal(m)
	z := redis.Z{Score: float64(m.T), Member: string(s)}
	r := client.ZAdd(getRedisKey(m.Check.Id), z)
	if r.Err() != nil {
		log.Fatalf("Error while recording measuremnt %s: %v\n", m.Id, r.Err())
	}
}

func trimMeasurements(checkID string, seconds int64) {
	now := time.Now()
	epoch := now.Unix() - seconds
	r := client.ZRemRangeByScore(getRedisKey(checkID), "-inf", strconv.FormatInt(epoch, 10))
	if r.Err() != nil {
		log.Fatalf("Error while trimming check_id %s: %v\n", checkID, r.Err())
	}
}

func getRedisKey(checkID string) string {
	return "measurements:" + checkID
}

func getMeasurementsByRange(checkID string, r int64) []Measurement {
	now := time.Now()
	from := now.Unix() - r

	return getMeasurementsFrom(checkID, from)
}

func getMeasurementsFrom(checkID string, from int64) []Measurement {
	vals, err := client.ZRevRangeByScore(getRedisKey(checkID), redis.ZRangeByScore{
		Min: strconv.FormatInt(from, 10),
		Max: "+inf",
	}).Result()

	if err != nil {
		panic(err)
	}

	measurements := make([]Measurement, 0, 100)

	for _, v := range vals {
		var m Measurement
		json.Unmarshal([]byte(v), &m)
		measurements = append(measurements, m)
	}

	return measurements
}

func getFormValueWithDefault(req *http.Request, key string, def string) string {
	s := req.FormValue(key)
	if s != "" {
		return s
	} else {
		return def
	}
}

func getMeasurementsHandler(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	checkID := vars["check_id"]
	r_s := getFormValueWithDefault(req, "range", "10")

	r, err := strconv.ParseInt(r_s, 10, 64)
	if err != nil {
		panic(nil)
	}
	res.Header().Set("Content-Type", "application/json")
	json.NewEncoder(res).Encode(getMeasurementsByRange(checkID, r))
}

func postMeasurementsHandler(res http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)
	measurements := make([]Measurement, 0, 100)

	err := decoder.Decode(&measurements)
	if err != nil {
		panic(err)
	}

	for _, m := range measurements {
		m.record()
		trimMeasurements(m.Check.Id, config.Retention)
	}

	log.Printf("fn=post_measurements count=%d\n", len(measurements))
}

func connectToRedis(config Config) {
	u, err := url.Parse(config.RedisURL)
	if err != nil {
		panic(err)
	}

	client = redis.NewTCPClient(&redis.Options{
		Addr:     u.Host,
		Password: "", // no password set
		DB:       0,  // use default DB
	})
}

func main() {
	config = Config{}
	flag.StringVar(&config.Port, "port", "5000", "port the HTTP server should bind to")
	flag.StringVar(&config.RedisURL, "redis_url", "redis://localhost:6379", "redis url")
	flag.Int64Var(&config.Retention, "retention", 60, "second of each measurement to keep")
	flag.Parse()

	connectToRedis(config)

	r := mux.NewRouter()

	r.HandleFunc("/checks/{check_id}/measurements", getMeasurementsHandler).Methods("GET")
	r.HandleFunc("/measurements", postMeasurementsHandler).Methods("POST")
	http.Handle("/", r)

	log.Printf("fn=main listening=true port=%s\n", config.Port)

	err := http.ListenAndServe(":"+config.Port, nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 Intel Corporation. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import (
	"bufio"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
)

const (
	cgroupTasks     = "tasks"
	cpusetCgroupDir = "/sys/fs/cgroup/cpuset/"
)

// GetContainerCgroupDir finds container path in one specified subsystem directory
func GetContainerCgroupDir(subsystemDir, containerID string) string {
	var containerDir string

	filepath.Walk(subsystemDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}
		if !info.IsDir() {
			return nil
		}
		// Assume directory name contains containerID is what we want
		if strings.Contains(filepath.Base(path), containerID) {
			containerDir = path
		}
		return nil
	})

	return containerDir
}

// isProcess finds out whether the task is a process or a thread.
func isProcess(processID string) bool {
	file, err := os.Open("/proc/" + processID + "/status")
	if err != nil {
		return true
	}
	defer file.Close()

	tgid := ""
	pid := ""

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		entry := scanner.Text()
		if strings.HasPrefix(entry, "Tgid:") {
			tgid = strings.TrimSpace(entry[len("Tgid:"):])
			if len(pid) > 0 {
				return tgid == pid
			}
		} else if strings.HasPrefix(entry, "Pid:") {
			pid = strings.TrimSpace(entry[len("Pid:"):])
			if len(tgid) > 0 {
				return tgid == pid
			}
		}
	}
	return true
}

func getTasksInContainer(cgroupParentDir, containerID string, onlyProcesses bool) ([]string, error) {
	var entries []string

	// Find Cpuset sub-cgroup directory of this container
	containerDir := ""
	// Probe known per-container directories
	if cgroupParentDir != "" {
		dirs := []string{
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "cri-containerd-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "crio-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "docker-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, containerID),
		}
		for _, d := range dirs {
			info, err := os.Stat(d)
			if err == nil && info.IsDir() {
				containerDir = d
				break
			}
		}
	}

	// Try generic way to search container directory under one cgroups subsytem directory
	if containerDir == "" {
		containerDir = GetContainerCgroupDir(cpusetCgroupDir, containerID)
		if containerDir == "" {
			return nil, fmt.Errorf("failed to find corresponding cgroups directory for container %s", containerID)
		}
	}

	// Find all processes listed in cgroup tasks file and apply to RDT CLOS
	cgroupTasksFileName := path.Join(containerDir, cgroupTasks)

	file, err := os.Open(cgroupTasksFileName)
	if err != nil {
		return nil, fmt.Errorf("failed to open file %s", cgroupTasksFileName)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		entry := scanner.Text()
		if !onlyProcesses || isProcess(entry) {
			entries = append(entries, entry)
		}
	}
	return entries, nil
}

// GetProcessesInContainer gets the IDs of all processes in the container.
func GetProcessesInContainer(cgroupParentDir, containerID string) ([]string, error) {
	return getTasksInContainer(cgroupParentDir, containerID, true)
}

// GetTasksInContainer gets the IDs of all tasks in the container.
func GetTasksInContainer(cgroupParentDir, containerID string) ([]string, error) {
	return getTasksInContainer(cgroupParentDir, containerID, false)
}
<commit_msg>utils: stop searching for container cgroup dir once it's found.<commit_after>// Copyright 2019 Intel Corporation. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import (
	"bufio"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
)

const (
	cgroupTasks     = "tasks"
	cpusetCgroupDir = "/sys/fs/cgroup/cpuset/"
)

// GetContainerCgroupDir brute-force searches for a container directory under parentDir.
func GetContainerCgroupDir(parentDir, containerID string) string {
	var containerDir string

	filepath.Walk(parentDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}
		if !info.IsDir() {
			return nil
		}
		if containerDir != "" {
			return filepath.SkipDir
		}
		// Assume any directory that contains containerID is the one we look for.
		if strings.Contains(filepath.Base(path), containerID) {
			containerDir = path
		}
		return nil
	})
	return containerDir
}

// isProcess finds out whether the task is a process or a thread.
func isProcess(processID string) bool {
	file, err := os.Open("/proc/" + processID + "/status")
	if err != nil {
		return true
	}
	defer file.Close()

	tgid := ""
	pid := ""

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		entry := scanner.Text()
		if strings.HasPrefix(entry, "Tgid:") {
			tgid = strings.TrimSpace(entry[len("Tgid:"):])
			if len(pid) > 0 {
				return tgid == pid
			}
		} else if strings.HasPrefix(entry, "Pid:") {
			pid = strings.TrimSpace(entry[len("Pid:"):])
			if len(tgid) > 0 {
				return tgid == pid
			}
		}
	}
	return true
}

func getTasksInContainer(cgroupParentDir, containerID string, onlyProcesses bool) ([]string, error) {
	var entries []string

	// Find Cpuset sub-cgroup directory of this container
	containerDir := ""
	// Probe known per-container directories
	if cgroupParentDir != "" {
		dirs := []string{
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "cri-containerd-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "crio-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, "docker-"+containerID+".scope"),
			filepath.Join(cpusetCgroupDir, cgroupParentDir, containerID),
		}
		for _, d := range dirs {
			info, err := os.Stat(d)
			if err == nil && info.IsDir() {
				containerDir = d
				break
			}
		}
	}

	// Try generic way to search container directory under one cgroups subsytem directory
	if containerDir == "" {
		containerDir = GetContainerCgroupDir(cpusetCgroupDir, containerID)
		if containerDir == "" {
			return nil, fmt.Errorf("failed to find corresponding cgroups directory for container %s", containerID)
		}
	}

	// Find all processes listed in cgroup tasks file and apply to RDT CLOS
	cgroupTasksFileName := path.Join(containerDir, cgroupTasks)

	file, err := os.Open(cgroupTasksFileName)
	if err != nil {
		return nil, fmt.Errorf("failed to open file %s", cgroupTasksFileName)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		entry := scanner.Text()
		if !onlyProcesses || isProcess(entry) {
			entries = append(entries, entry)
		}
	}
	return entries, nil
}

// GetProcessesInContainer gets the IDs of all processes in the container.
func GetProcessesInContainer(cgroupParentDir, containerID string) ([]string, error) {
	return getTasksInContainer(cgroupParentDir, containerID, true)
}

// GetTasksInContainer gets the IDs of all tasks in the container.
func GetTasksInContainer(cgroupParentDir, containerID string) ([]string, error) {
	return getTasksInContainer(cgroupParentDir, containerID, false)
}
<|endoftext|>