<commit_before>package integration_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("GCSclient", func() {
	var (
		err             error
		tempDir         string
		tempFile        *os.File
		tempVerDir      string
		tempVerFile     *os.File
		runtime         string
		directoryPrefix string
	)

	BeforeEach(func() {
		directoryPrefix = "gcsclient-tests"
		runtime = fmt.Sprintf("%d", time.Now().Unix())
	})

	Describe("with a non versioned bucket", func() {
		BeforeEach(func() {
			tempDir, err = ioutil.TempDir("", "gcs-upload-dir")
			Expect(err).ToNot(HaveOccurred())

			tempFile, err = ioutil.TempFile(tempDir, "file-to-upload")
			Expect(err).ToNot(HaveOccurred())

			tempFile.Write([]byte("hello-" + runtime))
		})

		AfterEach(func() {
			err := os.RemoveAll(tempDir)
			Expect(err).ToNot(HaveOccurred())

			err = gcsClient.DeleteObject(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())

			err = gcsClient.DeleteObject(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
		})

		It("can interact with buckets", func() {
			_, err := gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			_, err = gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			_, err = gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			files, err := gcsClient.BucketObjects(bucketName, directoryPrefix)
			Expect(err).ToNot(HaveOccurred())
			Expect(files).To(ConsistOf([]string{filepath.Join(directoryPrefix, "file-to-upload-1"), filepath.Join(directoryPrefix, "file-to-upload-2")}))

			_, err = gcsClient.ObjectGenerations(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("bucket is not versioned"))

			fileOneURL, err := gcsClient.URL(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURL).To(Equal(fmt.Sprintf("gs://%s/%s", bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))))

			_, err = gcsClient.ObjectGenerations(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("bucket is not versioned"))

			fileTwoURL, err := gcsClient.URL(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURL).To(Equal(fmt.Sprintf("gs://%s/%s", bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))))

			err = gcsClient.DownloadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0, filepath.Join(tempDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())

			read, err := ioutil.ReadFile(filepath.Join(tempDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())
			Expect(read).To(Equal([]byte("hello-" + runtime)))
		})
	})

	Describe("with a versioned bucket", func() {
		BeforeEach(func() {
			tempVerDir, err = ioutil.TempDir("", "gcs-versioned-upload-dir")
			Expect(err).ToNot(HaveOccurred())

			tempVerFile, err = ioutil.TempFile(tempVerDir, "file-to-upload")
			Expect(err).ToNot(HaveOccurred())

			tempVerFile.Write([]byte("hello-" + runtime))
		})

		AfterEach(func() {
			err := os.RemoveAll(tempVerDir)
			Expect(err).ToNot(HaveOccurred())

			fileOneGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).ToNot(HaveOccurred())

			for _, fileOneGeneration := range fileOneGenerations {
				err := gcsClient.DeleteObject(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)
				Expect(err).ToNot(HaveOccurred())
			}

			fileTwoGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).ToNot(HaveOccurred())

			for _, fileTwoGeneration := range fileTwoGenerations {
				err := gcsClient.DeleteObject(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration)
				Expect(err).ToNot(HaveOccurred())
			}
		})

		It("can interact with buckets", func() {
			fileOneGeneration, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			fileTwoGeneration1, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			fileTwoGeneration2, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			files, err := gcsClient.BucketObjects(versionedBucketName, directoryPrefix)
			Expect(err).ToNot(HaveOccurred())
			Expect(files).To(ConsistOf([]string{filepath.Join(directoryPrefix, "file-to-upload-1"), filepath.Join(directoryPrefix, "file-to-upload-2")}))

			fileOneGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneGenerations).To(ConsistOf([]int64{fileOneGeneration}))

			fileOneURL, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURL).To(Equal(fmt.Sprintf("gs://%s/%s", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))))

			fileOneURLGeneration, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURLGeneration).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)))

			fileTwoGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoGenerations).To(ConsistOf([]int64{fileTwoGeneration1, fileTwoGeneration2}))

			fileTwoURL, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURL).To(Equal(fmt.Sprintf("gs://%s/%s", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))))

			fileTwoURLGeneration1, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration1)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURLGeneration1).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration1)))

			fileTwoURLGeneration2, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration2)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURLGeneration2).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration2)))

			err = gcsClient.DownloadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0, filepath.Join(tempVerDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())

			read, err := ioutil.ReadFile(filepath.Join(tempVerDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())
			Expect(read).To(Equal([]byte("hello-" + runtime)))
		})
	})
})
<commit_msg>Fix temp dir<commit_after>package integration_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("GCSclient", func() {
	var (
		err             error
		tempDir         string
		tempFile        *os.File
		tempVerDir      string
		tempVerFile     *os.File
		runtime         string
		directoryPrefix string
	)

	BeforeEach(func() {
		directoryPrefix = "gcsclient-tests"
		runtime = fmt.Sprintf("%d", time.Now().Unix())
	})

	Describe("with a non versioned bucket", func() {
		BeforeEach(func() {
			tempDir, err = ioutil.TempDir("", "gcs_client_integration_test")
			Expect(err).ToNot(HaveOccurred())

			tempFile, err = ioutil.TempFile(tempDir, "file-to-upload")
			Expect(err).ToNot(HaveOccurred())

			tempFile.Write([]byte("hello-" + runtime))
		})

		AfterEach(func() {
			err := os.RemoveAll(tempDir)
			Expect(err).ToNot(HaveOccurred())

			err = gcsClient.DeleteObject(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())

			err = gcsClient.DeleteObject(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
		})

		It("can interact with buckets", func() {
			_, err := gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			_, err = gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			_, err = gcsClient.UploadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempFile.Name())
			Expect(err).ToNot(HaveOccurred())

			files, err := gcsClient.BucketObjects(bucketName, directoryPrefix)
			Expect(err).ToNot(HaveOccurred())
			Expect(files).To(ConsistOf([]string{filepath.Join(directoryPrefix, "file-to-upload-1"), filepath.Join(directoryPrefix, "file-to-upload-2")}))

			_, err = gcsClient.ObjectGenerations(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("bucket is not versioned"))

			fileOneURL, err := gcsClient.URL(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURL).To(Equal(fmt.Sprintf("gs://%s/%s", bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))))

			_, err = gcsClient.ObjectGenerations(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("bucket is not versioned"))

			fileTwoURL, err := gcsClient.URL(bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURL).To(Equal(fmt.Sprintf("gs://%s/%s", bucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))))

			err = gcsClient.DownloadFile(bucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0, filepath.Join(tempDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())

			read, err := ioutil.ReadFile(filepath.Join(tempDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())
			Expect(read).To(Equal([]byte("hello-" + runtime)))
		})
	})

	Describe("with a versioned bucket", func() {
		BeforeEach(func() {
			tempVerDir, err = ioutil.TempDir("", "gcs-versioned-upload-dir")
			Expect(err).ToNot(HaveOccurred())

			tempVerFile, err = ioutil.TempFile(tempVerDir, "file-to-upload")
			Expect(err).ToNot(HaveOccurred())

			tempVerFile.Write([]byte("hello-" + runtime))
		})

		AfterEach(func() {
			err := os.RemoveAll(tempVerDir)
			Expect(err).ToNot(HaveOccurred())

			fileOneGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).ToNot(HaveOccurred())

			for _, fileOneGeneration := range fileOneGenerations {
				err := gcsClient.DeleteObject(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)
				Expect(err).ToNot(HaveOccurred())
			}

			fileTwoGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).ToNot(HaveOccurred())

			for _, fileTwoGeneration := range fileTwoGenerations {
				err := gcsClient.DeleteObject(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration)
				Expect(err).ToNot(HaveOccurred())
			}
		})

		It("can interact with buckets", func() {
			fileOneGeneration, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			fileTwoGeneration1, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			fileTwoGeneration2, err := gcsClient.UploadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), tempVerFile.Name())
			Expect(err).ToNot(HaveOccurred())

			files, err := gcsClient.BucketObjects(versionedBucketName, directoryPrefix)
			Expect(err).ToNot(HaveOccurred())
			Expect(files).To(ConsistOf([]string{filepath.Join(directoryPrefix, "file-to-upload-1"), filepath.Join(directoryPrefix, "file-to-upload-2")}))

			fileOneGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneGenerations).To(ConsistOf([]int64{fileOneGeneration}))

			fileOneURL, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURL).To(Equal(fmt.Sprintf("gs://%s/%s", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"))))

			fileOneURLGeneration, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileOneURLGeneration).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), fileOneGeneration)))

			fileTwoGenerations, err := gcsClient.ObjectGenerations(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoGenerations).To(ConsistOf([]int64{fileTwoGeneration1, fileTwoGeneration2}))

			fileTwoURL, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), 0)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURL).To(Equal(fmt.Sprintf("gs://%s/%s", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"))))

			fileTwoURLGeneration1, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration1)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURLGeneration1).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration1)))

			fileTwoURLGeneration2, err := gcsClient.URL(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration2)
			Expect(err).ToNot(HaveOccurred())
			Expect(fileTwoURLGeneration2).To(Equal(fmt.Sprintf("gs://%s/%s#%d", versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-2"), fileTwoGeneration2)))

			err = gcsClient.DownloadFile(versionedBucketName, filepath.Join(directoryPrefix, "file-to-upload-1"), 0, filepath.Join(tempVerDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())

			read, err := ioutil.ReadFile(filepath.Join(tempVerDir, "downloaded-file"))
			Expect(err).ToNot(HaveOccurred())
			Expect(read).To(Equal([]byte("hello-" + runtime)))
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package script

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/control-center/serviced/commons"
	"github.com/control-center/serviced/commons/docker"
	"github.com/zenoss/glog"
)

var (
	cmdEval map[string]func(*runner, node) error
)

func init() {
	cmdEval = map[string]func(*runner, node) error{
		"":          evalEmpty,
		DESCRIPTION: evalEmpty,
		VERSION:     evalEmpty,
		SNAPSHOT:    evalSnapshot,
		USE:         evalUSE,
		SVC_RUN:     evalSvcRun,
		DEPENDENCY:  evalDependency,
		REQUIRE_SVC: evalRequireSvc,
	}
}

type Config struct {
	ServiceID      string
	DockerRegistry string            //docker registry being used for tagging images
	NoOp           bool              //Should commands modify the system
	TenantLookup   TenantIDLookup    //function for looking up a service
	Snapshot       Snapshot          //function for creating snapshots
	Restore        SnapshotRestore   //function to do the rollback to a snapshot
	SvcIDFromPath  ServiceIDFromPath // function to find a service id from a path
}

type Runner interface {
	Run() error
}

type runner struct {
	parseCtx       *parseContext
	config         *Config
	exitFunctions  []func(bool)      //each is called on exit of upgrade, bool denotes if upgrade exited with an error
	snapshotID     string            //the last snapshot taken
	env            map[string]string //context variables available to runner
	tenantIDLookup TenantIDLookup    //function for looking up a service
	snapshot       Snapshot          //function for creating snapshots
	restore        SnapshotRestore   //function to do the rollback to a snapshot
	svcFromPath    ServiceIDFromPath //function to find a service from a path and tenant
	findImage      findImage
	pullImage      pullImage
	execCommand    execCmd
	tagImage       tagImage
}

func NewRunnerFromFile(fileName string, config *Config) (Runner, error) {
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	r := bufio.NewReader(f)
	return NewRunner(r, config)
}

func NewRunner(r io.Reader, config *Config) (Runner, error) {
	pctx, err := parseDescriptor(r)
	if err != nil {
		return nil, err
	}
	if len(pctx.errors) > 0 {
		for _, e := range pctx.errors {
			glog.Errorf("%v", e)
		}

		return nil, errors.New("error parsing serviced runner file")
	}
	return newRunner(config, pctx), nil
}

func newRunner(config *Config, pctx *parseContext) *runner {
	if config.DockerRegistry == "" {
		config.DockerRegistry = "localhost:5000"
	}
	r := &runner{
		parseCtx:       pctx,
		config:         config,
		exitFunctions:  make([]func(bool), 0),
		env:            make(map[string]string),
		tenantIDLookup: config.TenantLookup,
		snapshot:       config.Snapshot,
		restore:        config.Restore,
		svcFromPath:    config.SvcIDFromPath,
		findImage:      docker.FindImage,
		pullImage:      docker.PullImage,
		execCommand:    defaultExec,
		tagImage:       defaultTagImage,
	}
	if config.NoOp {
		glog.Infof("creatng no op runner")
		r.execCommand = noOpExec
		r.tagImage = noOpTagImage
		r.restore = noOpRestore
		r.snapshot = noOpSnapshot
		r.pullImage = noOpPull
		r.findImage = noOpFindImage
	}

	return r
}

func (r *runner) Run() error {
	if err := r.evalNodes(r.parseCtx.nodes); err != nil {
		return err
	}
	return nil
}

func (r *runner) evalNodes(nodes []node) error {
	failed := true
	defer func() {
		for _, ef := range r.exitFunctions {
			ef(failed)
		}
	}()

	for i, n := range nodes {
		if f, found := cmdEval[n.cmd]; found {
			glog.Infof("executing step %d: %s", i, n.line)
			if err := f(r, n); err != nil {
				glog.Errorf("error executing step %d: %s: %s", i, n.cmd, err)
				return err
			}
		} else {
			glog.Infof("skipping step %d unknown function: %s", i, n.line)
		}
	}
	failed = false
	return nil
}
func (r *runner) addExitFunction(ef func(bool)) {
	r.exitFunctions = append(r.exitFunctions, ef)
}

func evalEmpty(r *runner, n node) error {
	glog.V(1).Infof("nothing to eval: %s", n.line)
	return nil
}
func evalSnapshot(r *runner, n node) error {
	glog.V(0).Info("performing snapshot")

	if r.snapshot == nil {
		return fmt.Errorf("no snapshot function provided for %s", SNAPSHOT)
	}
	if r.restore == nil {
		return fmt.Errorf("no restore function provided for %s", SNAPSHOT)
	}

	svcID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", SNAPSHOT)
	}

	mySnapshotID, err := r.snapshot(svcID)
	if err != nil {
		return err
	}
	r.snapshotID = mySnapshotID //keep track of the latest snapshot to rollback to
	glog.V(0).Infof("snapshot id: %s", mySnapshotID)

	exitFunc := func(failed bool) {
		if failed && r.snapshotID == mySnapshotID {
			glog.Infof("restoring snapshot %s", mySnapshotID)
			if err := r.restore(mySnapshotID); err != nil {
				glog.Errorf("failed restoring snapshot %s: %v", mySnapshotID, err)

			}
		}
	}
	r.addExitFunction(exitFunc)
	return nil
}

func evalUSE(r *runner, n node) error {
	imageName := n.args[0]
	glog.V(0).Infof("preparing to use image: %s", imageName)
	svcID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", USE)
	}

	imageID, err := commons.ParseImageID(imageName)
	if err != nil {
		return err
	}
	if imageID.Tag == "" {
		imageID.Tag = "latest"
	}
	glog.Infof("pulling image %s, this may take a while...", imageID)
	if err := r.pullImage(imageID.String()); err != nil {
		return fmt.Errorf("unable to pull image %s", imageID)
	}

	//verify image has been pulled
	img, err := r.findImage(imageID.String(), false)
	if err != nil {
		err = fmt.Errorf("could not look up image %s: %s. Check your docker login and retry service deployment.", imageID, err)
		return err
	}

	//Tag images to latest all images
	var newTag *commons.ImageID

	newTag, err = renameImageID(r.config.DockerRegistry, svcID, imageID.String(), "latest")
	if err != nil {
		return err
	}
	glog.Infof("tagging image %s to %s ", imageName, newTag)
	if _, err = r.tagImage(img, newTag.String()); err != nil {
		glog.Errorf("could not tag image: %s (%v)", imageName, err)
		return err
	}
	return nil
}

func evalSvcRun(r *runner, n node) error {
	if r.svcFromPath == nil {
		return fmt.Errorf("no service id lookup function for %s", SVC_RUN)
	}

	svcPath := n.args[0]
	tenantID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", SVC_RUN)
	}
	svcID, err := r.svcFromPath(tenantID, svcPath)
	if err != nil {
		return err
	}
	if svcID == "" {
		return fmt.Errorf("no service id found for %s", svcPath)
	}

	n.args[0] = svcID

	glog.V(0).Infof("running: serviced service run %s", strings.Join(n.args, " "))
	args := []string{"service", "run"}
	args = append(args, n.args...)
	if err := r.execCommand("serviced", args...); err != nil {
		return err
	}

	return nil
}
func evalDependency(r *runner, n node) error {
	glog.V(0).Infof("checking serviced dependency: %s", n.args[0])
	glog.V(0).Info("dependency check for serviced not implemented, skipping...")
	return nil
}

func evalRequireSvc(r *runner, n node) error {
	if r.tenantIDLookup == nil {
		return fmt.Errorf("no tenant lookup function provided for %s", REQUIRE_SVC)
	}
	glog.V(0).Infof("checking service requirement")
	if r.config.ServiceID == "" {
		return errors.New("no service id specified")
	}
	glog.V(0).Infof("verifying service %s", r.config.ServiceID)
	//lookup tenant id for service
	tID, err := r.tenantIDLookup(r.config.ServiceID)
	if err != nil {
		return err
	}
	glog.V(0).Infof("found %s tenant id for service %s", tID, r.config.ServiceID)
	r.env["TENANT_ID"] = tID
	return nil
}
<commit_msg>update parse error wording<commit_after>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

package script

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/control-center/serviced/commons"
	"github.com/control-center/serviced/commons/docker"
	"github.com/zenoss/glog"
)

var (
	cmdEval map[string]func(*runner, node) error
)

func init() {
	cmdEval = map[string]func(*runner, node) error{
		"":          evalEmpty,
		DESCRIPTION: evalEmpty,
		VERSION:     evalEmpty,
		SNAPSHOT:    evalSnapshot,
		USE:         evalUSE,
		SVC_RUN:     evalSvcRun,
		DEPENDENCY:  evalDependency,
		REQUIRE_SVC: evalRequireSvc,
	}
}

type Config struct {
	ServiceID      string
	DockerRegistry string            //docker registry being used for tagging images
	NoOp           bool              //Should commands modify the system
	TenantLookup   TenantIDLookup    //function for looking up a service
	Snapshot       Snapshot          //function for creating snapshots
	Restore        SnapshotRestore   //function to do the rollback to a snapshot
	SvcIDFromPath  ServiceIDFromPath // function to find a service id from a path
}

type Runner interface {
	Run() error
}

type runner struct {
	parseCtx       *parseContext
	config         *Config
	exitFunctions  []func(bool)      //each is called on exit of upgrade, bool denotes if upgrade exited with an error
	snapshotID     string            //the last snapshot taken
	env            map[string]string //context variables available to runner
	tenantIDLookup TenantIDLookup    //function for looking up a service
	snapshot       Snapshot          //function for creating snapshots
	restore        SnapshotRestore   //function to do the rollback to a snapshot
	svcFromPath    ServiceIDFromPath //function to find a service from a path and tenant
	findImage      findImage
	pullImage      pullImage
	execCommand    execCmd
	tagImage       tagImage
}

func NewRunnerFromFile(fileName string, config *Config) (Runner, error) {
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	r := bufio.NewReader(f)
	return NewRunner(r, config)
}

func NewRunner(r io.Reader, config *Config) (Runner, error) {
	pctx, err := parseDescriptor(r)
	if err != nil {
		return nil, err
	}
	if len(pctx.errors) > 0 {
		for _, e := range pctx.errors {
			glog.Errorf("%v", e)
		}

		return nil, errors.New("error parsing script")
	}
	return newRunner(config, pctx), nil
}

func newRunner(config *Config, pctx *parseContext) *runner {
	if config.DockerRegistry == "" {
		config.DockerRegistry = "localhost:5000"
	}
	r := &runner{
		parseCtx:       pctx,
		config:         config,
		exitFunctions:  make([]func(bool), 0),
		env:            make(map[string]string),
		tenantIDLookup: config.TenantLookup,
		snapshot:       config.Snapshot,
		restore:        config.Restore,
		svcFromPath:    config.SvcIDFromPath,
		findImage:      docker.FindImage,
		pullImage:      docker.PullImage,
		execCommand:    defaultExec,
		tagImage:       defaultTagImage,
	}
	if config.NoOp {
		glog.Infof("creatng no op runner")
		r.execCommand = noOpExec
		r.tagImage = noOpTagImage
		r.restore = noOpRestore
		r.snapshot = noOpSnapshot
		r.pullImage = noOpPull
		r.findImage = noOpFindImage
	}

	return r
}

func (r *runner) Run() error {
	if err := r.evalNodes(r.parseCtx.nodes); err != nil {
		return err
	}
	return nil
}

func (r *runner) evalNodes(nodes []node) error {
	failed := true
	defer func() {
		for _, ef := range r.exitFunctions {
			ef(failed)
		}
	}()

	for i, n := range nodes {
		if f, found := cmdEval[n.cmd]; found {
			glog.Infof("executing step %d: %s", i, n.line)
			if err := f(r, n); err != nil {
				glog.Errorf("error executing step %d: %s: %s", i, n.cmd, err)
				return err
			}
		} else {
			glog.Infof("skipping step %d unknown function: %s", i, n.line)
		}
	}
	failed = false
	return nil
}
func (r *runner) addExitFunction(ef func(bool)) {
	r.exitFunctions = append(r.exitFunctions, ef)
}

func evalEmpty(r *runner, n node) error {
	glog.V(1).Infof("nothing to eval: %s", n.line)
	return nil
}
func evalSnapshot(r *runner, n node) error {
	glog.V(0).Info("performing snapshot")

	if r.snapshot == nil {
		return fmt.Errorf("no snapshot function provided for %s", SNAPSHOT)
	}
	if r.restore == nil {
		return fmt.Errorf("no restore function provided for %s", SNAPSHOT)
	}

	svcID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", SNAPSHOT)
	}

	mySnapshotID, err := r.snapshot(svcID)
	if err != nil {
		return err
	}
	r.snapshotID = mySnapshotID //keep track of the latest snapshot to rollback to
	glog.V(0).Infof("snapshot id: %s", mySnapshotID)

	exitFunc := func(failed bool) {
		if failed && r.snapshotID == mySnapshotID {
			glog.Infof("restoring snapshot %s", mySnapshotID)
			if err := r.restore(mySnapshotID); err != nil {
				glog.Errorf("failed restoring snapshot %s: %v", mySnapshotID, err)

			}
		}
	}
	r.addExitFunction(exitFunc)
	return nil
}

func evalUSE(r *runner, n node) error {
	imageName := n.args[0]
	glog.V(0).Infof("preparing to use image: %s", imageName)
	svcID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", USE)
	}

	imageID, err := commons.ParseImageID(imageName)
	if err != nil {
		return err
	}
	if imageID.Tag == "" {
		imageID.Tag = "latest"
	}
	glog.Infof("pulling image %s, this may take a while...", imageID)
	if err := r.pullImage(imageID.String()); err != nil {
		return fmt.Errorf("unable to pull image %s", imageID)
	}

	//verify image has been pulled
	img, err := r.findImage(imageID.String(), false)
	if err != nil {
		err = fmt.Errorf("could not look up image %s: %s. Check your docker login and retry service deployment.", imageID, err)
		return err
	}

	//Tag images to latest all images
	var newTag *commons.ImageID

	newTag, err = renameImageID(r.config.DockerRegistry, svcID, imageID.String(), "latest")
	if err != nil {
		return err
	}
	glog.Infof("tagging image %s to %s ", imageName, newTag)
	if _, err = r.tagImage(img, newTag.String()); err != nil {
		glog.Errorf("could not tag image: %s (%v)", imageName, err)
		return err
	}
	return nil
}

func evalSvcRun(r *runner, n node) error {
	if r.svcFromPath == nil {
		return fmt.Errorf("no service id lookup function for %s", SVC_RUN)
	}

	svcPath := n.args[0]
	tenantID, found := r.env["TENANT_ID"]
	if !found {
		return fmt.Errorf("no service tenant id specified for %s", SVC_RUN)
	}
	svcID, err := r.svcFromPath(tenantID, svcPath)
	if err != nil {
		return err
	}
	if svcID == "" {
		return fmt.Errorf("no service id found for %s", svcPath)
	}

	n.args[0] = svcID

	glog.V(0).Infof("running: serviced service run %s", strings.Join(n.args, " "))
	args := []string{"service", "run"}
	args = append(args, n.args...)
	if err := r.execCommand("serviced", args...); err != nil {
		return err
	}

	return nil
}
func evalDependency(r *runner, n node) error {
	glog.V(0).Infof("checking serviced dependency: %s", n.args[0])
	glog.V(0).Info("dependency check for serviced not implemented, skipping...")
	return nil
}

func evalRequireSvc(r *runner, n node) error {
	if r.tenantIDLookup == nil {
		return fmt.Errorf("no tenant lookup function provided for %s", REQUIRE_SVC)
	}
	glog.V(0).Infof("checking service requirement")
	if r.config.ServiceID == "" {
		return errors.New("no service id specified")
	}
	glog.V(0).Infof("verifying service %s", r.config.ServiceID)
	//lookup tenant id for service
	tID, err := r.tenantIDLookup(r.config.ServiceID)
	if err != nil {
		return err
	}
	glog.V(0).Infof("found %s tenant id for service %s", tID, r.config.ServiceID)
	r.env["TENANT_ID"] = tID
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import (
	`bytes`
	`fmt`
	`regexp`
	`strings`
)

var tree [1024]Position
var node, rootNode int

type Position struct {
	game         *Game
	enpassant    int         // En-passant square caused by previous move.
	color        int         // Side to make next move.
	balance      int 	 // Material balance index.
	hash         uint64      // Polyglot hash value for the position.
	hashPawns    uint64      // Polyglot hash value for position's pawn structure.
	board        Bitmask     // Bitmask of all pieces on the board.
	king         [2]int      // King's square for both colors.
	count        [14]int     // Counts of each piece on the board.
	pieces       [64]Piece   // Array of 64 squares with pieces on them.
	outposts     [14]Bitmask // Bitmasks of each piece on the board; [0] all white, [1] all black.
	tally        Score       // Positional valuation score based on PST.
	reversible   bool        // Is this position reversible?
	castles      uint8       // Castle rights mask.
}

func NewPosition(game *Game, white, black string, color int) *Position {
	tree[node] = Position{game: game, color: color}
	p := &tree[node]

	p.setupSide(strings.Split(white, `,`), White)
	p.setupSide(strings.Split(black, `,`), Black)

	p.castles = castleKingside[White] | castleQueenside[White] | castleKingside[Black] | castleQueenside[Black]
	if p.pieces[E1] != King || p.pieces[H1] != Rook {
		p.castles &= ^castleKingside[White]
	}
	if p.pieces[E1] != King || p.pieces[A1] != Rook {
		p.castles &= ^castleQueenside[White]
	}
	if p.pieces[E8] != BlackKing || p.pieces[H8] != BlackRook {
		p.castles &= ^castleKingside[Black]
	}
	if p.pieces[E8] != BlackKing || p.pieces[A8] != BlackRook {
		p.castles &= ^castleQueenside[Black]
	}

	for square, piece := range p.pieces {
		if piece != 0 {
			p.outposts[piece].set(square)
			p.outposts[piece.color()].set(square)
			p.count[piece]++
			if piece.isKing() {
				p.king[piece.color()] = square
			}
			p.balance += materialBalance[piece]
		}
	}

	p.reversible = true
	p.board = p.outposts[White] | p.outposts[Black]
	p.hash, p.hashPawns = p.polyglot()
	p.tally = p.valuation()

	return p
}

func (p *Position) setupSide(moves []string, color int) *Position {
	re := regexp.MustCompile(`([KQRBN]?)([a-h])([1-8])`)

	for _, move := range moves {
		arr := re.FindStringSubmatch(move)
		if len(arr) == 0 {
			panic(fmt.Sprintf("Invalid notation '%s' for %s\n", move, C(color)))
		}
		name, col, row := arr[1], int(arr[2][0]-'a'), int(arr[3][0]-'1')

		var piece Piece
		switch name {
		case `K`: piece = king(color)
		case `Q`: piece = queen(color)
		case `R`: piece = rook(color)
		case `B`: piece = bishop(color)
		case `N`: piece = knight(color)
		default:  piece = pawn(color)
		}
		p.pieces[Square(row, col)] = piece
	}

	return p
}

func (p *Position) movePiece(piece Piece, from, to int) *Position {
	p.pieces[from], p.pieces[to] = 0, piece
	p.outposts[piece] ^= bit[from] | bit[to]
	p.outposts[piece.color()] ^= bit[from] | bit[to]

	// Update position's hash values.
	random := piece.polyglot(from) ^ piece.polyglot(to)
	p.hash ^= random
	if piece.isPawn() {
		p.hashPawns ^= random
	}

	// Update positional score.
	p.tally.subtract(pst[piece][from]).add(pst[piece][to])

	return p
}

func (p *Position) promotePawn(pawn Piece, from, to int, promo Piece) *Position {
	p.pieces[from], p.pieces[to] = 0, promo
	p.outposts[pawn] ^= bit[from]
	p.outposts[promo] ^= bit[to]
	p.outposts[pawn.color()] ^= bit[from] | bit[to]
	p.count[pawn]--

	// Update position's hash values, material balance and counts.
	random := pawn.polyglot(from)
	p.hash ^= random ^ promo.polyglot(to)
	p.hashPawns ^= random
	p.balance += materialBalance[promo] - materialBalance[pawn]
	p.count[promo]++

	// Update positional score.
	p.tally.subtract(pst[pawn][from]).add(pst[promo][to])

	return p
}

func (p *Position) capturePiece(capture Piece, from, to int) *Position {
	p.outposts[capture] ^= bit[to]
	p.outposts[capture.color()] ^= bit[to]
	p.count[capture]--

	// Update position's hash values and material balance.
	random := capture.polyglot(to)
	p.hash ^= random
	if capture.isPawn() {
		p.hashPawns ^= random
	}
	p.balance -= materialBalance[capture]

	// Update positional score.
	p.tally.subtract(pst[capture][to])

	return p
}

func (p *Position) captureEnpassant(capture Piece, from, to int) *Position {
	enpassant := to - eight[capture.color()^1]

	p.pieces[enpassant] = 0
	p.outposts[capture] ^= bit[enpassant]
	p.outposts[capture.color()] ^= bit[enpassant]
	p.count[capture]--

	// Update position's hash values and material balance.
	random := capture.polyglot(enpassant)
	p.hash ^= random
	p.hashPawns ^= random
	p.balance -= materialBalance[capture]

	// Update positional score.
	p.tally.subtract(pst[capture][enpassant])

	return p
}

func (p *Position) MakeMove(move Move) *Position {
	color := move.color()
	from, to, piece, capture := move.split()

	// Copy over the contents of previous tree node to the current one.
	node++
	tree[node] = *p // => tree[node] = tree[node - 1]
	pp := &tree[node]

	pp.enpassant, pp.reversible = 0, true

	if capture != 0 {
		pp.reversible = false
		if to != 0 && to == p.enpassant {
			pp.captureEnpassant(pawn(color^1), from, to)
			pp.hash ^= hashEnpassant[Col(p.enpassant)]
		} else {
			pp.capturePiece(capture, from, to)
		}
	}

	if promo := move.promo(); promo == 0 {
		pp.movePiece(piece, from, to)

		if piece.isKing() {
			pp.king[color] = to
			if move.isCastle() {
				pp.reversible = false
				switch to {
				case G1:
					pp.movePiece(Rook, H1, F1)
				case C1:
					pp.movePiece(Rook, A1, D1)
				case G8:
					pp.movePiece(BlackRook, H8, F8)
				case C8:
					pp.movePiece(BlackRook, A8, D8)
				}
			}
		} else if piece.isPawn() {
			pp.reversible = false
			if move.isEnpassant() {
				pp.enpassant = from + eight[color] // Save the en-passant square.
				pp.hash ^= hashEnpassant[Col(pp.enpassant)]
			}
		}
	} else {
		pp.reversible = false
		pp.promotePawn(piece, from, to, promo)
	}

	// Set up the board bitmask, update castle rights, finish off incremental
	// hash value, and flip the color.
	pp.board = pp.outposts[White] | pp.outposts[Black]
	pp.castles &= castleRights[from] & castleRights[to]
	pp.hash ^= hashCastle[p.castles] ^ hashCastle[pp.castles]
	pp.hash ^= polyglotRandomWhite
	pp.color ^= 1 // <-- Flip side to move.

	return &tree[node] // pp
}

// Makes "null" move by copying over previous node position (i.e. preserving all pieces
// intact) and flipping the color.
func (p *Position) MakeNullMove() *Position {
	node++
	tree[node] = *p // => tree[node] = tree[node - 1]
	pp := &tree[node]

	// Flipping side to move obviously invalidates the enpassant square.
	if pp.enpassant != 0 {
		pp.hash ^= hashEnpassant[Col(pp.enpassant)]
		pp.enpassant = 0
	}
	pp.hash ^= polyglotRandomWhite
	pp.color ^= 1 // <-- Flip side to move.

	return &tree[node] // pp
}

// Restores previous position effectively taking back the last move made.
func (p *Position) UndoLastMove() *Position {
	if node > 0 {
		node--
	}
	return &tree[node]
}

func (p *Position) UndoNullMove() *Position {
	p.hash ^= polyglotRandomWhite
	p.color ^= 1

	return p.UndoLastMove()
}

func (p *Position) isInCheck(color int) bool {
	return p.isAttacked(p.king[color], color^1)
}

func (p *Position) isNull() bool {
	return node > 0 && tree[node].board == tree[node-1].board
}

func (p *Position) isRepetition() bool {
	if !p.reversible {
		return false
	}
	for previous := node-1; previous >= 0; previous-- {
		if !tree[previous].reversible {
			return false
		}
		if tree[previous].hash == p.hash {
			return true
		}
	}
	return false
}

func (p *Position) isTripleRepetition() bool {
	if !p.reversible {
		return false
	}
	for previous, repetitions := node-1, 1; previous >= 0; previous-- {
		if !tree[previous].reversible {
			return false
		}
		if tree[previous].hash == p.hash {
			repetitions++
			if repetitions == 3 {
				return true
			}
		}
	}
	return false
}

func (p *Position) canCastle(color int) (kingside, queenside bool) {
	attacks := p.allAttacks(color ^ 1)
	kingside = p.castles & castleKingside[color] != 0 &&
		(gapKing[color] & p.board == 0) &&
		(castleKing[color] & attacks == 0)

	queenside = p.castles & castleQueenside[color] != 0 &&
		(gapQueen[color] & p.board == 0) &&
		(castleQueen[color] & attacks == 0)
	return
}

// Stub.
func (p *Position) isInsufficient() bool {
	return false
}

// Reports game status for current position or after the given move. The status
// help to determine whether to continue with search or if the game is over.
func (p *Position) status(move Move, blendedScore int) int {
	if move != Move(0) {
		p = p.MakeMove(move)
		defer func() { p = p.UndoLastMove() }()
	}

	switch ply, score := Ply(), Abs(blendedScore); score {
	case 0:
		if ply == 1 {
			if p.isTripleRepetition() {
				return Repetition
			} else if p.isInsufficient() {
				return Insufficient
			}
		}
		if !NewGen(p, ply+1).generateMoves().anyValid(p) {
			return Stalemate
		}
	case Checkmate - ply:
		if p.isInCheck(p.color) {
			if p.color == White {
				return BlackWon
			}
			return WhiteWon
		}
		return Stalemate
	default:
		if score > Checkmate-MaxDepth && (score+ply)/2 > 0 {
			if p.color == White {
				return BlackWinning
			}
			return WhiteWinning
		}
	}
	return InProgress
}

// Computes initial values of position's polyglot hash, pawn hash, and material
// hash. When making a move these values get updated incrementally.
func (p *Position) polyglot() (hash, hashPawns uint64) {
	board := p.board
	for board != 0 {
		square := board.pop()
		piece := p.pieces[square]
		random := piece.polyglot(square)
		hash ^= random
		if piece.isPawn() {
			hashPawns ^= random
		}
	}

	hash ^= hashCastle[p.castles]
	if p.enpassant != 0 {
		hash ^= hashEnpassant[Col(p.enpassant)]
	}
	if p.color == White {
		hash ^= polyglotRandomWhite
	}

	return
}

// Computes positional valuation score based on PST. When making a move the
// valuation tally gets updated incrementally.
func (p *Position) valuation() (score Score) {
	board := p.board
	for board != 0 {
		square := board.pop()
		piece := p.pieces[square]
		score.add(pst[piece][square])
	}
	return
}

func (p *Position) String() string {
	buffer := bytes.NewBufferString("  a b c d e f g h")
	if !p.isInCheck(p.color) {
		buffer.WriteString("\n")
	} else {
		buffer.WriteString("  Check to " + C(p.color) + "\n")
	}
	for row := 7; row >= 0; row-- {
		buffer.WriteByte('1' + byte(row))
		for col := 0; col <= 7; col++ {
			square := Square(row, col)
			buffer.WriteByte(' ')
			if piece := p.pieces[square]; piece != 0 {
				buffer.WriteString(piece.String())
			} else {
				buffer.WriteString("\u22C5")
			}
		}
		buffer.WriteByte('\n')
	}
	return buffer.String()
}
<commit_msg>Faster castling<commit_after>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import (
	`bytes`
	`fmt`
	`regexp`
	`strings`
)

var tree [1024]Position
var node, rootNode int

type Position struct {
	game         *Game
	enpassant    int         // En-passant square caused by previous move.
	color        int         // Side to make next move.
	balance      int 	 // Material balance index.
	hash         uint64      // Polyglot hash value for the position.
	hashPawns    uint64      // Polyglot hash value for position's pawn structure.
	board        Bitmask     // Bitmask of all pieces on the board.
	king         [2]int      // King's square for both colors.
	count        [14]int     // Counts of each piece on the board.
	pieces       [64]Piece   // Array of 64 squares with pieces on them.
	outposts     [14]Bitmask // Bitmasks of each piece on the board; [0] all white, [1] all black.
	tally        Score       // Positional valuation score based on PST.
	reversible   bool        // Is this position reversible?
	castles      uint8       // Castle rights mask.
}

func NewPosition(game *Game, white, black string, color int) *Position {
	tree[node] = Position{game: game, color: color}
	p := &tree[node]

	p.setupSide(strings.Split(white, `,`), White)
	p.setupSide(strings.Split(black, `,`), Black)

	p.castles = castleKingside[White] | castleQueenside[White] | castleKingside[Black] | castleQueenside[Black]
	if p.pieces[E1] != King || p.pieces[H1] != Rook {
		p.castles &= ^castleKingside[White]
	}
	if p.pieces[E1] != King || p.pieces[A1] != Rook {
		p.castles &= ^castleQueenside[White]
	}
	if p.pieces[E8] != BlackKing || p.pieces[H8] != BlackRook {
		p.castles &= ^castleKingside[Black]
	}
	if p.pieces[E8] != BlackKing || p.pieces[A8] != BlackRook {
		p.castles &= ^castleQueenside[Black]
	}

	for square, piece := range p.pieces {
		if piece != 0 {
			p.outposts[piece].set(square)
			p.outposts[piece.color()].set(square)
			p.count[piece]++
			if piece.isKing() {
				p.king[piece.color()] = square
			}
			p.balance += materialBalance[piece]
		}
	}

	p.reversible = true
	p.board = p.outposts[White] | p.outposts[Black]
	p.hash, p.hashPawns = p.polyglot()
	p.tally = p.valuation()

	return p
}

func (p *Position) setupSide(moves []string, color int) *Position {
	re := regexp.MustCompile(`([KQRBN]?)([a-h])([1-8])`)

	for _, move := range moves {
		arr := re.FindStringSubmatch(move)
		if len(arr) == 0 {
			panic(fmt.Sprintf("Invalid notation '%s' for %s\n", move, C(color)))
		}
		name, col, row := arr[1], int(arr[2][0]-'a'), int(arr[3][0]-'1')

		var piece Piece
		switch name {
		case `K`: piece = king(color)
		case `Q`: piece = queen(color)
		case `R`: piece = rook(color)
		case `B`: piece = bishop(color)
		case `N`: piece = knight(color)
		default:  piece = pawn(color)
		}
		p.pieces[Square(row, col)] = piece
	}

	return p
}

func (p *Position) movePiece(piece Piece, from, to int) *Position {
	p.pieces[from], p.pieces[to] = 0, piece
	p.outposts[piece] ^= bit[from] | bit[to]
	p.outposts[piece.color()] ^= bit[from] | bit[to]

	// Update position's hash values.
	random := piece.polyglot(from) ^ piece.polyglot(to)
	p.hash ^= random
	if piece.isPawn() {
		p.hashPawns ^= random
	}

	// Update positional score.
	p.tally.subtract(pst[piece][from]).add(pst[piece][to])

	return p
}

func (p *Position) promotePawn(pawn Piece, from, to int, promo Piece) *Position {
	p.pieces[from], p.pieces[to] = 0, promo
	p.outposts[pawn] ^= bit[from]
	p.outposts[promo] ^= bit[to]
	p.outposts[pawn.color()] ^= bit[from] | bit[to]
	p.count[pawn]--

	// Update position's hash values, material balance and counts.
	random := pawn.polyglot(from)
	p.hash ^= random ^ promo.polyglot(to)
	p.hashPawns ^= random
	p.balance += materialBalance[promo] - materialBalance[pawn]
	p.count[promo]++

	// Update positional score.
	p.tally.subtract(pst[pawn][from]).add(pst[promo][to])

	return p
}

func (p *Position) capturePiece(capture Piece, from, to int) *Position {
	p.outposts[capture] ^= bit[to]
	p.outposts[capture.color()] ^= bit[to]
	p.count[capture]--

	// Update position's hash values and material balance.
	random := capture.polyglot(to)
	p.hash ^= random
	if capture.isPawn() {
		p.hashPawns ^= random
	}
	p.balance -= materialBalance[capture]

	// Update positional score.
	p.tally.subtract(pst[capture][to])

	return p
}

func (p *Position) captureEnpassant(capture Piece, from, to int) *Position {
	enpassant := to - eight[capture.color()^1]

	p.pieces[enpassant] = 0
	p.outposts[capture] ^= bit[enpassant]
	p.outposts[capture.color()] ^= bit[enpassant]
	p.count[capture]--

	// Update position's hash values and material balance.
	random := capture.polyglot(enpassant)
	p.hash ^= random
	p.hashPawns ^= random
	p.balance -= materialBalance[capture]

	// Update positional score.
	p.tally.subtract(pst[capture][enpassant])

	return p
}

func (p *Position) MakeMove(move Move) *Position {
	color := move.color()
	from, to, piece, capture := move.split()

	// Copy over the contents of previous tree node to the current one.
	node++
	tree[node] = *p // => tree[node] = tree[node - 1]
	pp := &tree[node]

	pp.enpassant, pp.reversible = 0, true

	if capture != 0 {
		pp.reversible = false
		if to != 0 && to == p.enpassant {
			pp.captureEnpassant(pawn(color^1), from, to)
			pp.hash ^= hashEnpassant[Col(p.enpassant)]
		} else {
			pp.capturePiece(capture, from, to)
		}
	}

	if promo := move.promo(); promo == 0 {
		pp.movePiece(piece, from, to)

		if piece.isKing() {
			pp.king[color] = to
			if move.isCastle() {
				pp.reversible = false
				switch to {
				case G1:
					pp.movePiece(Rook, H1, F1)
				case C1:
					pp.movePiece(Rook, A1, D1)
				case G8:
					pp.movePiece(BlackRook, H8, F8)
				case C8:
					pp.movePiece(BlackRook, A8, D8)
				}
			}
		} else if piece.isPawn() {
			pp.reversible = false
			if move.isEnpassant() {
				pp.enpassant = from + eight[color] // Save the en-passant square.
				pp.hash ^= hashEnpassant[Col(pp.enpassant)]
			}
		}
	} else {
		pp.reversible = false
		pp.promotePawn(piece, from, to, promo)
	}

	// Set up the board bitmask, update castle rights, finish off incremental
	// hash value, and flip the color.
	pp.board = pp.outposts[White] | pp.outposts[Black]
	pp.castles &= castleRights[from] & castleRights[to]
	pp.hash ^= hashCastle[p.castles] ^ hashCastle[pp.castles]
	pp.hash ^= polyglotRandomWhite
	pp.color ^= 1 // <-- Flip side to move.

	return &tree[node] // pp
}

// Makes "null" move by copying over previous node position (i.e. preserving all pieces
// intact) and flipping the color.
func (p *Position) MakeNullMove() *Position {
	node++
	tree[node] = *p // => tree[node] = tree[node - 1]
	pp := &tree[node]

	// Flipping side to move obviously invalidates the enpassant square.
	if pp.enpassant != 0 {
		pp.hash ^= hashEnpassant[Col(pp.enpassant)]
		pp.enpassant = 0
	}
	pp.hash ^= polyglotRandomWhite
	pp.color ^= 1 // <-- Flip side to move.

	return &tree[node] // pp
}

// Restores previous position effectively taking back the last move made.
func (p *Position) UndoLastMove() *Position {
	if node > 0 {
		node--
	}
	return &tree[node]
}

func (p *Position) UndoNullMove() *Position {
	p.hash ^= polyglotRandomWhite
	p.color ^= 1

	return p.UndoLastMove()
}

func (p *Position) isInCheck(color int) bool {
	return p.isAttacked(p.king[color], color^1)
}

func (p *Position) isNull() bool {
	return node > 0 && tree[node].board == tree[node-1].board
}

func (p *Position) isRepetition() bool {
	if !p.reversible {
		return false
	}
	for previous := node-1; previous >= 0; previous-- {
		if !tree[previous].reversible {
			return false
		}
		if tree[previous].hash == p.hash {
			return true
		}
	}
	return false
}

func (p *Position) isTripleRepetition() bool {
	if !p.reversible {
		return false
	}
	for previous, repetitions := node-1, 1; previous >= 0; previous-- {
		if !tree[previous].reversible {
			return false
		}
		if tree[previous].hash == p.hash {
			repetitions++
			if repetitions == 3 {
				return true
			}
		}
	}
	return false
}

func (p *Position) canCastle(color int) (kingside, queenside bool) {

	// Start off with simple checks.
	kingside = (p.castles & castleKingside[color] != 0) && (gapKing[color] & p.board == 0)
	queenside = (p.castles & castleQueenside[color] != 0) && (gapQueen[color] & p.board == 0)

	// If it still looks like the castles are possible perform more expensive
	// final check.
	if kingside || queenside {
		attacks := p.allAttacks(color ^ 1)
		kingside = kingside && (castleKing[color] & attacks == 0)
		queenside = queenside && (castleQueen[color] & attacks == 0)
	}

	return
}

// Stub.
func (p *Position) isInsufficient() bool {
	return false
}

// Reports game status for current position or after the given move. The status
// help to determine whether to continue with search or if the game is over.
func (p *Position) status(move Move, blendedScore int) int {
	if move != Move(0) {
		p = p.MakeMove(move)
		defer func() { p = p.UndoLastMove() }()
	}

	switch ply, score := Ply(), Abs(blendedScore); score {
	case 0:
		if ply == 1 {
			if p.isTripleRepetition() {
				return Repetition
			} else if p.isInsufficient() {
				return Insufficient
			}
		}
		if !NewGen(p, ply+1).generateMoves().anyValid(p) {
			return Stalemate
		}
	case Checkmate - ply:
		if p.isInCheck(p.color) {
			if p.color == White {
				return BlackWon
			}
			return WhiteWon
		}
		return Stalemate
	default:
		if score > Checkmate-MaxDepth && (score+ply)/2 > 0 {
			if p.color == White {
				return BlackWinning
			}
			return WhiteWinning
		}
	}
	return InProgress
}

// Computes initial values of position's polyglot hash, pawn hash, and material
// hash. When making a move these values get updated incrementally.
func (p *Position) polyglot() (hash, hashPawns uint64) {
	board := p.board
	for board != 0 {
		square := board.pop()
		piece := p.pieces[square]
		random := piece.polyglot(square)
		hash ^= random
		if piece.isPawn() {
			hashPawns ^= random
		}
	}

	hash ^= hashCastle[p.castles]
	if p.enpassant != 0 {
		hash ^= hashEnpassant[Col(p.enpassant)]
	}
	if p.color == White {
		hash ^= polyglotRandomWhite
	}

	return
}

// Computes positional valuation score based on PST. When making a move the
// valuation tally gets updated incrementally.
func (p *Position) valuation() (score Score) {
	board := p.board
	for board != 0 {
		square := board.pop()
		piece := p.pieces[square]
		score.add(pst[piece][square])
	}
	return
}

func (p *Position) String() string {
	buffer := bytes.NewBufferString("  a b c d e f g h")
	if !p.isInCheck(p.color) {
		buffer.WriteString("\n")
	} else {
		buffer.WriteString("  Check to " + C(p.color) + "\n")
	}
	for row := 7; row >= 0; row-- {
		buffer.WriteByte('1' + byte(row))
		for col := 0; col <= 7; col++ {
			square := Square(row, col)
			buffer.WriteByte(' ')
			if piece := p.pieces[square]; piece != 0 {
				buffer.WriteString(piece.String())
			} else {
				buffer.WriteString("\u22C5")
			}
		}
		buffer.WriteByte('\n')
	}
	return buffer.String()
}
<|endoftext|>


<commit_before>package popular

import (
	"errors"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"
	"socialapi/workers/helper"
	"socialapi/workers/populartopic/populartopic"
	"strconv"
	"time"
)

func ListTopics(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	statisticName := u.Query().Get("statisticName")

	now := time.Now().UTC()
	// dateNumber is changing according to the statisticName
	// if it is monthly statistic, it will be month number March->3
	// if it is weekly statistic, it will be week number 48th week -> 48
	// if it is daily statistic, it will the day number of the year e.g last day-> 365+1
	var dateNumber int
	year, month, _ := now.Date()

	switch statisticName {
	case "daily":
		dateNumber = now.YearDay()
	case "weekly":
		_, dateNumber = now.ISOWeek()
	case "monthly":
		dateNumber = int(month)
	default:
		return helpers.NewBadRequestResponse(errors.New("Unknown statistic name"))
	}

	key := populartopic.PreparePopularTopicKey(
		query.GroupName,
		statisticName,
		year,
		dateNumber,
	)

	redisConn := helper.MustGetRedisConn()
	// limit-1 is important, because redis is using 0 based index
	topics, err := redisConn.SortedSetReverseRange(key, query.Skip, query.Skip+query.Limit-1)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	popularTopicIds := make([]int64, 0)
	for _, topic := range topics {
		val, err := strconv.ParseInt(string(topic.([]uint8)), 10, 64)
		if err == nil {
			popularTopicIds = append(popularTopicIds, val)
		}
	}

	popularTopicIds, err = extendPopularTopicsIfNeeded(query, popularTopicIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c := models.NewChannel()
	popularTopics, err := c.FetchByIds(popularTopicIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		models.PopulateChannelContainers(
			popularTopics,
			query.AccountId,
		),
	)
}

func extendPopularTopicsIfNeeded(query *models.Query, popularTopics []int64) ([]int64, error) {
	toBeAddedItemCount := query.Limit - len(popularTopics)

	if toBeAddedItemCount > 0 {
		normalChannels, err := fetchMoreChannels(query.GroupName, query.Limit)
		if err != nil {
			return popularTopics, err
		}

		for _, normalChannel := range normalChannels {
			exists := false
			for _, popularTopicId := range popularTopics {
				if normalChannel.Id == popularTopicId {
					exists = true
					break
				}
			}

			if !exists {
				popularTopics = append(popularTopics, normalChannel.Id)
				toBeAddedItemCount--
				if toBeAddedItemCount == 0 {
					break
				}
			}
		}
	}

	return popularTopics, nil
}

func fetchMoreChannels(group string, count int) ([]models.Channel, error) {
	q := models.NewQuery()
	q.GroupName = group
	q.Limit = count
	q.Type = models.Channel_TYPE_TOPIC
	q.SetDefaults()
	c := models.NewChannel()
	return c.List(q)
}
<commit_msg>Social: cleanup code to reuse it<commit_after>package popular

import (
	"errors"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"
	"socialapi/workers/helper"
	"socialapi/workers/populartopic/populartopic"
	"strconv"
	"time"
)

func getDateNumberAndYear(statisticName string) (int, int, error) {
	now := time.Now().UTC()
	// dateNumber is changing according to the statisticName
	// if it is monthly statistic, it will be month number March->3
	// if it is weekly statistic, it will be week number 48th week -> 48
	// if it is daily statistic, it will the day number of the year e.g last day-> 365+1
	switch statisticName {
	case "daily":
		return now.Year(), now.YearDay(), nil
	case "weekly":
		year, week := now.ISOWeek()
		return year, week, nil
	case "monthly":
		return now.Year(), int(now.Month()), nil
	default:
		return 0, 0, errors.New("Unknown statistic name")
	}
}

func getIds(key string, query *models.Query) ([]int64, error) {
	// limit-1 is important, because redis is using 0 based index
	popularIds := make([]int64, 0)
	listIds, err := helper.MustGetRedisConn().
		SortedSetReverseRange(
		key,
		query.Skip,
		query.Skip+query.Limit-1,
	)

	if err != nil {
		return popularIds, err
	}

	for _, listId := range listIds {
		val, err := strconv.ParseInt(string(listId.([]uint8)), 10, 64)
		if err == nil {
			popularIds = append(popularIds, val)
		}
	}

	return popularIds, nil
}

func ListTopics(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	statisticName := u.Query().Get("statisticName")

	year, dateNumber, err := getDateNumberAndYear(statisticName)
	if err != nil {
		return helpers.NewBadRequestResponse(errors.New("Unknown statistic name"))
	}

	key := populartopic.PreparePopularTopicKey(
		query.GroupName,
		statisticName,
		year,
		dateNumber,
	)

	popularTopicIds, err := getIds(key, query)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	popularTopicIds, err = extendPopularTopicsIfNeeded(query, popularTopicIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c := models.NewChannel()
	popularTopics, err := c.FetchByIds(popularTopicIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		models.PopulateChannelContainers(
			popularTopics,
			query.AccountId,
		),
	)
}

func extendPopularTopicsIfNeeded(query *models.Query, popularTopics []int64) ([]int64, error) {
	toBeAddedItemCount := query.Limit - len(popularTopics)

	if toBeAddedItemCount > 0 {
		normalChannels, err := fetchMoreChannels(query.GroupName, query.Limit)
		if err != nil {
			return popularTopics, err
		}

		for _, normalChannel := range normalChannels {
			exists := false
			for _, popularTopicId := range popularTopics {
				if normalChannel.Id == popularTopicId {
					exists = true
					break
				}
			}

			if !exists {
				popularTopics = append(popularTopics, normalChannel.Id)
				toBeAddedItemCount--
				if toBeAddedItemCount == 0 {
					break
				}
			}
		}
	}

	return popularTopics, nil
}

func fetchMoreChannels(group string, count int) ([]models.Channel, error) {
	q := models.NewQuery()
	q.GroupName = group
	q.Limit = count
	q.Type = models.Channel_TYPE_TOPIC
	q.SetDefaults()
	c := models.NewChannel()
	return c.List(q)
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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 main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strconv"
)

var port = flag.Int("port", 8000, "port number")

func init() {
	flag.Parse()
}

func main() {
	http.Handle("/", http.FileServer(http.Dir("public")))
	fmt.Printf("http://localhost:%d/\n", *port)
	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil))
}
<commit_msg>doc: Update license year in a new file<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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 main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strconv"
)

var port = flag.Int("port", 8000, "port number")

func init() {
	flag.Parse()
}

func main() {
	http.Handle("/", http.FileServer(http.Dir("public")))
	fmt.Printf("http://localhost:%d/\n", *port)
	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil))
}
<|endoftext|>


<commit_before>package integration_test

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"strings"
	"sync"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/myshkin5/effective-octo-garbanzo/api/handlers/octo"
	"github.com/myshkin5/effective-octo-garbanzo/logs"
)

var _ = Describe("API", func() {
	quickCreateOctos := func(count int, url string, errs chan error, wg *sync.WaitGroup) {
		defer wg.Done()

		for i := 0; i < count; i++ {
			body := fmt.Sprintf(`{
					"name": "stress_1_%d"
				}`, i)
			response, err := http.Post(url+"octos", "application/json", strings.NewReader(body))
			if err != nil {
				errs <- err
				continue
			}

			if response.StatusCode != http.StatusCreated {
				errs <- fmt.Errorf("create octos expecting status %d, got %d", http.StatusCreated, response.StatusCode)
				continue
			}
		}
	}

	quickDeleteRandomOctos := func(count int, url string, errs chan error, wg *sync.WaitGroup) {
		defer wg.Done()

		for i := 0; i < count; i++ {
			response, err := http.Get(url + "octos")
			if err != nil {
				errs <- err
				continue
			}

			if response.StatusCode != http.StatusOK {
				errs <- fmt.Errorf("getting octos expecting status %d, got %d", http.StatusOK, response.StatusCode)
				continue
			}

			var list []octo.Octo
			err = json.NewDecoder(response.Body).Decode(&list)
			if err != nil {
				errs <- err
				continue
			}

			if len(list) == 0 {
				continue
			}

			octo := list[rand.Intn(len(list))]

			request, err := http.NewRequest("DELETE", octo.Link, nil)
			if err != nil {
				errs <- err
				continue
			}
			response, err = http.DefaultClient.Do(request)
			if err != nil {
				errs <- err
				continue
			}
			if response.StatusCode != http.StatusNoContent {
				errs <- fmt.Errorf("deleting octos expecting status %d, got %d", http.StatusNoContent, response.StatusCode)
				continue
			}
		}
	}

	Measure("the standard suite of operations", func(b Benchmarker) {
		b.Time("runtime", func() {

			url := "http://localhost:8080/"
			errs := make(chan error, 2000)

			var wg sync.WaitGroup
			wg.Add(2)
			go quickCreateOctos(100, url, errs, &wg)
			go quickDeleteRandomOctos(100, url, errs, &wg)

			wg.Wait()
			close(errs)

			count := len(errs)

			for err := range errs {
				logs.Logger.Errorf("Test received error: %v", err)
			}

			Expect(count).To(BeZero())
		})
	}, 1)
})
<commit_msg>Reuse connects in test/use unique octo names<commit_after>package integration_test

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"strings"
	"sync"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/myshkin5/effective-octo-garbanzo/api/handlers/octo"
)

var _ = Describe("API", func() {
	quickCreateOctos := func(count int, url string, errs chan error, wg *sync.WaitGroup) {
		defer wg.Done()

		nanos := time.Now().UnixNano()

		for i := 0; i < count; i++ {
			body := fmt.Sprintf(`{
					"name": "stress_%d_%d"
				}`, nanos, i)
			response, err := http.Post(url+"octos", "application/json", strings.NewReader(body))
			if err != nil {
				errs <- err
				continue
			}

			if response.StatusCode != http.StatusCreated {
				errs <- fmt.Errorf("create octos expecting status %d, got %d", http.StatusCreated, response.StatusCode)
				continue
			}

			err = response.Body.Close()
			if err != nil {
				errs <- err
			}
		}
	}

	quickDeleteRandomOctos := func(count int, url string, errs chan error, wg *sync.WaitGroup) {
		defer wg.Done()

		for i := 0; i < count; i++ {
			response, err := http.Get(url + "octos")
			if err != nil {
				errs <- err
				continue
			}

			if response.StatusCode != http.StatusOK {
				errs <- fmt.Errorf("getting octos expecting status %d, got %d", http.StatusOK, response.StatusCode)
				continue
			}

			var list []octo.Octo
			err = json.NewDecoder(response.Body).Decode(&list)
			if err != nil {
				errs <- err
				continue
			}

			err = response.Body.Close()
			if err != nil {
				errs <- err
			}

			if len(list) == 0 {
				continue
			}

			octo := list[rand.Intn(len(list))]

			request, err := http.NewRequest("DELETE", octo.Link, nil)
			if err != nil {
				errs <- err
				continue
			}
			response, err = http.DefaultClient.Do(request)
			if err != nil {
				errs <- err
				continue
			}
			if response.StatusCode != http.StatusNoContent {
				errs <- fmt.Errorf("deleting octos expecting status %d, got %d", http.StatusNoContent, response.StatusCode)
				continue
			}

			err = response.Body.Close()
			if err != nil {
				errs <- err
			}
		}
	}

	Measure("the standard suite of operations", func(b Benchmarker) {
		b.Time("runtime", func() {
			url := "http://localhost:8080/"
			errs := make(chan error, 2000)

			var wg sync.WaitGroup
			wg.Add(2)
			go quickCreateOctos(100, url, errs, &wg)
			go quickDeleteRandomOctos(100, url, errs, &wg)

			wg.Wait()
			close(errs)

			count := len(errs)

			for err := range errs {
				fmt.Printf("Test received error: %v\n", err)
			}

			Expect(count).To(BeZero())
		})
	}, 3)
})
<|endoftext|>


<commit_before>package btn

import "github.com/oakmound/oak/v2/render"

//Text sets the text of the button to be generated
func Text(s string) Option {
	return func(g Generator) Generator {
		g.Text = s
		return g
	}
}

//Font sets the font for the text of the button to be generated
func Font(f *render.Font) Option {
	return func(g Generator) Generator {
		g.Font = f
		return g
	}
}

//TxtOff sets the text offset  of the button generator from the bottom left
func TxtOff(x, y float64) Option {
	return func(g Generator) Generator {
		g.TxtX = x
		g.TxtY = y
		return g
	}
}
<commit_msg>Add FitText btn option<commit_after>package btn

import (
	"github.com/oakmound/oak/v2/render"
)

//Text sets the text of the button to be generated
func Text(s string) Option {
	return func(g Generator) Generator {
		g.Text = s
		return g
	}
}

//Font sets the font for the text of the button to be generated
func Font(f *render.Font) Option {
	return func(g Generator) Generator {
		g.Font = f
		return g
	}
}

//TxtOff sets the text offset  of the button generator from the bottom left
func TxtOff(x, y float64) Option {
	return func(g Generator) Generator {
		g.TxtX = x
		g.TxtY = y
		return g
	}
}

// FitText adjusts a btn's width, given it has text and font defined, to
// be large enough for the given text plus the provided buffer
func FitText(buffer int) Option {
	return func(g Generator) Generator {
		if g.Font != nil && g.Text != "" {
			w := g.Font.MeasureString(g.Text)
			wf := float64(w.Ceil() + buffer)
			if g.W < wf {
				g.W = wf
			}
		}
		return g
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsApiGatewayResource() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsApiGatewayResourceRead,
		Schema: map[string]*schema.Schema{
			"rest_api_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"path": {
				Type:     schema.TypeString,
				Required: true,
			},
			"path_part": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"parent_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceAwsApiGatewayResourceRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).apigateway

	restApiId := d.Get("rest_api_id").(string)
	target := d.Get("path").(string)
	params := &apigateway.GetResourcesInput{RestApiId: aws.String(restApiId)}

	var matches []*apigateway.Resource
	log.Printf("[DEBUG] Reading API Gateway Resources: %s", params)
	err := conn.GetResourcesPages(params, func(page *apigateway.GetResourcesOutput, lastPage bool) bool {
		for _, resource := range page.Items {
			if aws.StringValue(resource.Path) == target {
				matches = append(matches, resource)
			}
		}
		return !lastPage
	})
	if err != nil {
		return fmt.Errorf("error describing API Gateway Resources: %s", err)
	}

	if len(matches) == 0 {
		return fmt.Errorf("no Resources with path %q found for rest api %q", target, restApiId)
	}
	if len(matches) > 1 {
		return fmt.Errorf("multiple Resources with path %q found for rest api %q", target, restApiId)
	}

	match := matches[0]
	d.SetId(*match.Id)

	return nil
}
<commit_msg>Setting path_part and parent_id<commit_after>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/apigateway"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsApiGatewayResource() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsApiGatewayResourceRead,
		Schema: map[string]*schema.Schema{
			"rest_api_id": {
				Type:     schema.TypeString,
				Required: true,
			},
			"path": {
				Type:     schema.TypeString,
				Required: true,
			},
			"path_part": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"parent_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceAwsApiGatewayResourceRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).apigateway

	restApiId := d.Get("rest_api_id").(string)
	target := d.Get("path").(string)
	params := &apigateway.GetResourcesInput{RestApiId: aws.String(restApiId)}

	var matches []*apigateway.Resource
	log.Printf("[DEBUG] Reading API Gateway Resources: %s", params)
	err := conn.GetResourcesPages(params, func(page *apigateway.GetResourcesOutput, lastPage bool) bool {
		for _, resource := range page.Items {
			if aws.StringValue(resource.Path) == target {
				matches = append(matches, resource)
			}
		}
		return !lastPage
	})
	if err != nil {
		return fmt.Errorf("error describing API Gateway Resources: %s", err)
	}

	if len(matches) == 0 {
		return fmt.Errorf("no Resources with path %q found for rest api %q", target, restApiId)
	}
	if len(matches) > 1 {
		return fmt.Errorf("multiple Resources with path %q found for rest api %q", target, restApiId)
	}

	match := matches[0]
	d.SetId(*match.Id)
	d.Set("path_part", match.PathPart)
	d.Set("parent_id", match.ParentId)

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/xray"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSXraySamplingRule_basic(t *testing.T) {
	var samplingRule xray.SamplingRule
	resourceName := "aws_xray_sampling_rule.test"
	rString := acctest.RandString(8)
	ruleName := fmt.Sprintf("tf_acc_sampling_rule_%s", rString)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSXraySamplingRuleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSXraySamplingRule_basic(ruleName, acctest.RandIntRange(0, 9999), acctest.RandIntRange(0, 2147483647)),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckXraySamplingRuleExists(resourceName, &samplingRule),
					testAccCheckResourceAttrRegionalARN(resourceName, "rule_arn", "xray", fmt.Sprintf("sampling-rule/%s", ruleName)),
				),
			},
		},
	})
}

func testAccAWSXraySamplingRule_basic(ruleName string, priority int, reservoirSize int) string {
	return fmt.Sprintf(`
resource "aws_xray_sampling_rule" "test" {
	rule_name = "%s"
	priority = %d
	version = 1
	reservoir_size = %d
	url_path = "*"
	host = "*"
	http_method = "GET"
	service_type = "*"
	service_name = "*"
	fixed_rate = 0.3
	resource_arn = "*"
}
`, ruleName, priority, reservoirSize)
}

func testAccCheckXraySamplingRuleExists(n string, samplingRule *xray.SamplingRule) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No XRay Sampling Rule ID is set")
		}

		rule, err := getSamplingRule(rs.Primary.ID)

		if err != nil {
			return err
		}

		*samplingRule = *rule

		return nil
	}
}

func testAccCheckAWSXraySamplingRuleDestroy(s *terraform.State) error {
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_xray_sampling_rule" {
			continue
		}

		_, err := getSamplingRule(rs.Primary.ID)

		if err == nil {
			return fmt.Errorf("Expected XRay Sampling Rule to be destroyed, %s found", rs.Primary.ID)
		}
	}

	return nil
}

func getSamplingRule(ruleName string) (*xray.SamplingRule, error) {
	conn := testAccProvider.Meta().(*AWSClient).xrayconn
	params := &xray.GetSamplingRulesInput{}
	for {
		out, err := conn.GetSamplingRules(params)
		if err != nil {
			return nil, err
		}
		for _, samplingRuleRecord := range out.SamplingRuleRecords {
			samplingRule := samplingRuleRecord.SamplingRule
			if aws.StringValue(samplingRule.RuleName) == ruleName {
				return samplingRule, nil
			}
		}
		if out.NextToken == nil {
			break
		}
		params.NextToken = out.NextToken
	}
	return nil, fmt.Errorf("XRay Sampling Rule: %s not found found", ruleName)
}
<commit_msg>Includes update and import tests for aws_xray_sampling_rule<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/xray"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSXraySamplingRule_basic(t *testing.T) {
	var samplingRule xray.SamplingRule
	resourceName := "aws_xray_sampling_rule.test"
	rString := acctest.RandString(8)
	ruleName := fmt.Sprintf("tf_acc_sampling_rule_%s", rString)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSXraySamplingRuleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSXraySamplingRuleConfig_basic(ruleName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckXraySamplingRuleExists(resourceName, &samplingRule),
					testAccCheckResourceAttrRegionalARN(resourceName, "rule_arn", "xray", fmt.Sprintf("sampling-rule/%s", ruleName)),
					resource.TestCheckResourceAttrSet(resourceName, "priority"),
					resource.TestCheckResourceAttrSet(resourceName, "version"),
					resource.TestCheckResourceAttrSet(resourceName, "reservoir_size"),
					resource.TestCheckResourceAttrSet(resourceName, "url_path"),
					resource.TestCheckResourceAttrSet(resourceName, "host"),
					resource.TestCheckResourceAttrSet(resourceName, "http_method"),
					resource.TestCheckResourceAttrSet(resourceName, "fixed_rate"),
					resource.TestCheckResourceAttrSet(resourceName, "resource_arn"),
					resource.TestCheckResourceAttrSet(resourceName, "service_name"),
					resource.TestCheckResourceAttrSet(resourceName, "service_type"),
					resource.TestCheckResourceAttr(resourceName, "attributes.%", "1"),
				),
			},
		},
	})
}

func TestAccAWSXraySamplingRule_update(t *testing.T) {
	var samplingRule xray.SamplingRule
	resourceName := "aws_xray_sampling_rule.test"
	rString := acctest.RandString(8)
	ruleName := fmt.Sprintf("tf_acc_sampling_rule_%s", rString)
	updatedPriority := acctest.RandIntRange(0, 9999)
	updatedReservoirSize := acctest.RandIntRange(0, 2147483647)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSXraySamplingRuleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSXraySamplingRuleConfig_update(ruleName, acctest.RandIntRange(0, 9999), acctest.RandIntRange(0, 2147483647)),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckXraySamplingRuleExists(resourceName, &samplingRule),
					testAccCheckResourceAttrRegionalARN(resourceName, "rule_arn", "xray", fmt.Sprintf("sampling-rule/%s", ruleName)),
					resource.TestCheckResourceAttr(resourceName, "attributes.%", "0"),
				),
			},
			{ // Update attributes
				Config: testAccAWSXraySamplingRuleConfig_update(ruleName, updatedPriority, updatedReservoirSize),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckXraySamplingRuleExists(resourceName, &samplingRule),
					testAccCheckResourceAttrRegionalARN(resourceName, "rule_arn", "xray", fmt.Sprintf("sampling-rule/%s", ruleName)),
					resource.TestCheckResourceAttr(resourceName, "priority", fmt.Sprintf("%d", updatedPriority)),
					resource.TestCheckResourceAttr(resourceName, "reservoir_size", fmt.Sprintf("%d", updatedReservoirSize)),
					resource.TestCheckResourceAttr(resourceName, "attributes.%", "0"),
				),
			},
		},
	})
}

func TestAccAWSXraySamplingRule_import(t *testing.T) {
	resourceName := "aws_xray_sampling_rule.test"
	rString := acctest.RandString(8)
	ruleName := fmt.Sprintf("tf_acc_sampling_rule_%s", rString)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSIotThingTypeDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSXraySamplingRuleConfig_basic(ruleName),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckXraySamplingRuleExists(n string, samplingRule *xray.SamplingRule) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No XRay Sampling Rule ID is set")
		}

		rule, err := getSamplingRule(rs.Primary.ID)

		if err != nil {
			return err
		}

		*samplingRule = *rule

		return nil
	}
}

func testAccCheckAWSXraySamplingRuleDestroy(s *terraform.State) error {
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_xray_sampling_rule" {
			continue
		}

		_, err := getSamplingRule(rs.Primary.ID)

		if err == nil {
			return fmt.Errorf("Expected XRay Sampling Rule to be destroyed, %s found", rs.Primary.ID)
		}
	}

	return nil
}

func getSamplingRule(ruleName string) (*xray.SamplingRule, error) {
	conn := testAccProvider.Meta().(*AWSClient).xrayconn
	params := &xray.GetSamplingRulesInput{}
	for {
		out, err := conn.GetSamplingRules(params)
		if err != nil {
			return nil, err
		}
		for _, samplingRuleRecord := range out.SamplingRuleRecords {
			samplingRule := samplingRuleRecord.SamplingRule
			if aws.StringValue(samplingRule.RuleName) == ruleName {
				return samplingRule, nil
			}
		}
		if out.NextToken == nil {
			break
		}
		params.NextToken = out.NextToken
	}
	return nil, fmt.Errorf("XRay Sampling Rule: %s not found found", ruleName)
}

func testAccAWSXraySamplingRuleConfig_basic(ruleName string) string {
	return fmt.Sprintf(`
resource "aws_xray_sampling_rule" "test" {
	rule_name = "%s"
	priority = 5
	version = 1
	reservoir_size = 10
	url_path = "*"
	host = "*"
	http_method = "GET"
	service_type = "*"
	service_name = "*"
	fixed_rate = 0.3
	resource_arn = "*"
	attributes = {
		Hello = "World"
	}
}
`, ruleName)
}

func testAccAWSXraySamplingRuleConfig_update(ruleName string, priority int, reservoirSize int) string {
	return fmt.Sprintf(`
resource "aws_xray_sampling_rule" "test" {
	rule_name = "%s"
	priority = %d
	version = 1
	reservoir_size = %d
	url_path = "*"
	host = "*"
	http_method = "GET"
	service_type = "*"
	service_name = "*"
	fixed_rate = 0.3
	resource_arn = "*"
}
`, ruleName, priority, reservoirSize)
}
<|endoftext|>


<commit_before><commit_msg>stats added<commit_after><|endoftext|>


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

package util

import "sort"

// Int64Slice attaches the methods of Interface to []int64, sorting in increasing order.
type Int64Slice []int64

func (p Int64Slice) Len() int           { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// IsSliceInt64Eq returns if the two slice has the same elements but different sequences.
func IsSliceInt64Eq(a, b []int64) bool {
	if len(a) != len(b) {
		return false
	}
	sort.Sort(Int64Slice(a))
	sort.Sort(Int64Slice(b))
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// ExistsInSlice returns true if string exists in slice
func ExistsInSlice(target string, slice []string) bool {
	i := sort.Search(len(slice),
		func(i int) bool { return slice[i] == target })
	return i < len(slice)
}

// IsEqualSlice returns true if slices are equal
func IsEqualSlice(target []string, source []string) bool {
	if len(target) != len(source) {
		return false
	}

	if (target == nil) != (source == nil) {
		return false
	}

	sort.Strings(target)
	sort.Strings(source)

	for i, v := range target {
		if v != source[i] {
			return false
		}
	}

	return true
}
<commit_msg>Change comment, try to make lint happy<commit_after>// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package util

import "sort"

// Int64Slice attaches the methods of Interface to []int64, sorting in increasing order.
type Int64Slice []int64

func (p Int64Slice) Len() int           { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// IsSliceInt64Eq returns if the two slice has the same elements but different sequences.
func IsSliceInt64Eq(a, b []int64) bool {
	if len(a) != len(b) {
		return false
	}
	sort.Sort(Int64Slice(a))
	sort.Sort(Int64Slice(b))
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// ExistsInSlice returns true if string exists in slice.
func ExistsInSlice(target string, slice []string) bool {
	i := sort.Search(len(slice),
		func(i int) bool { return slice[i] == target })
	return i < len(slice)
}

// IsEqualSlice returns true if slices are equal.
func IsEqualSlice(target []string, source []string) bool {
	if len(target) != len(source) {
		return false
	}

	if (target == nil) != (source == nil) {
		return false
	}

	sort.Strings(target)
	sort.Strings(source)

	for i, v := range target {
		if v != source[i] {
			return false
		}
	}

	return true
}
<|endoftext|>


<commit_before>// package composite contains helpful functions for compositing information
// onto video in real time
package composite

import (
	"bufio"
	"code.google.com/p/freetype-go/freetype"
	"image"
	"image/draw"
	//"image/png"
	"io/ioutil"
	"os"
)

// function RenderTextToPNG uses freetype to render the text (first argument)
// to a PNG file, using the TTF format font located at fontPath
func RenderTextToPNG(text string, filename string, fontPath string) error {
	fontBytes, err := ioutil.ReadFile(fontPath)
	if err != nil {
		return err
	}

	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		return err
	}

	fg, bg := image.White, image.Transparent
	rgba := image.NewRGBA(image.Rect(0, 0, 640, 480))
	fsize := 32.0
	draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
	c := freetype.NewContext()
	c.SetDPI(140)
	c.SetFont(font)
	c.SetFontSize(fsize)
	c.SetClip(rgba.Bounds())
	c.SetDst(rgba)
	c.SetSrc(fg)
	c.SetHinting(freetype.NoHinting)

	pt := freetype.Pt(100, 100+int(c.PointToFix32(fsize)>>8))
	_, err = c.DrawString(text, pt)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	b := bufio.NewWriter(f)
	//err = png.Encode(b, rgba)
	if err != nil {
		return err
	}
	err = b.Flush()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>undo test comments<commit_after>// package composite contains helpful functions for compositing information
// onto video in real time
package composite

import (
	"bufio"
	"code.google.com/p/freetype-go/freetype"
	"image"
	"image/draw"
	"image/png"
	"io/ioutil"
	"os"
)

// function RenderTextToPNG uses freetype to render the text (first argument
// to a PNG file, using the TTF format font located at fontPath
func RenderTextToPNG(text string, filename string, fontPath string) error {
	fontBytes, err := ioutil.ReadFile(fontPath)
	if err != nil {
		return err
	}

	font, err := freetype.ParseFont(fontBytes)
	if err != nil {
		return err
	}

	fg, bg := image.White, image.Transparent
	rgba := image.NewRGBA(image.Rect(0, 0, 640, 480))
	fsize := 32.0
	draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
	c := freetype.NewContext()
	c.SetDPI(140)
	c.SetFont(font)
	c.SetFontSize(fsize)
	c.SetClip(rgba.Bounds())
	c.SetDst(rgba)
	c.SetSrc(fg)
	c.SetHinting(freetype.NoHinting)

	pt := freetype.Pt(100, 100+int(c.PointToFix32(fsize)>>8))
	_, err = c.DrawString(text, pt)
	if err != nil {
		return err
	}

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	b := bufio.NewWriter(f)
	err = png.Encode(b, rgba)
	if err != nil {
		return err
	}
	err = b.Flush()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"errors"
	"os"

	_ "github.com/mattn/go-sqlite3"

	log "code.google.com/p/log4go"
)

const (
	dbName = "db.sqlite"
)

// Errors
var RowScanError = errors.New("Row scan failure")

// The SQL database.
type DB struct {
	dbConn *sql.DB
}

// Query result types
type RowResult map[string]string
type RowResults []map[string]string

// New creates a new database. Deletes any existing database.
func New(dbPath string) *DB {
	os.Remove(dbPath)
	return Open(dbPath)
}

// Open an existing database, creating it if it does not exist.
func Open(dbPath string) *DB {
	log.Trace("SQLite database path is %s", dbPath)
	dbc, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Error(err)
		return nil
	}
	return &DB{
		dbConn: dbc,
	}
}

// Close closes the underlying database connection.
func (db *DB) Close() error {
	return db.dbConn.Close()
}

// Query runs the supplied query against the sqlite database. It returns a slice of
// RowResults.
func (db *DB) Query(query string) (RowResults, error) {
	rows, err := db.dbConn.Query(query)
	if err != nil {
		log.Error("failed to execute SQLite query", err.Error())
		return nil, err
	}
	defer rows.Close()

	results := make(RowResults, 0)

	columns, _ := rows.Columns()
	rawResult := make([][]byte, len(columns))
	dest := make([]interface{}, len(columns))
	for i, _ := range rawResult {
		dest[i] = &rawResult[i] // Pointers to each string in the interface slice
	}

	for rows.Next() {
		err = rows.Scan(dest...)
		if err != nil {
			log.Error("failed to scan SQLite row", err.Error())
			return nil, RowScanError
		}

		r := make(RowResult)
		for i, raw := range rawResult {
			if raw == nil {
				r[columns[i]] = "null"
			} else {
				r[columns[i]] = string(raw)
			}
		}
		results = append(results, r)
	}
	log.Debug(func() string { return "Executed query successfully: " + query })
	return results, nil
}

// Execute executes the given sqlite statement, of a type that doesn't return rows.
func (db *DB) Execute(stmt string) error {
	_, err := db.dbConn.Exec(stmt)
	log.Debug(func() string {
		if err != nil {
			return "Error executing " + stmt
		}
		return "Successfully executed " + stmt
	})
	return err
}

// StartTransaction starts an explicit transaction.
func (db *DB) StartTransaction() error {
	_, err := db.dbConn.Exec("BEGIN")
	log.Debug(func() string {
		if err != nil {
			return "Error starting transaction"
		}
		return "Successfully started transaction"
	})
	return err
}

// CommitTransaction commits all changes made since StartTraction was called.
func (db *DB) CommitTransaction() error {
	_, err := db.dbConn.Exec("END")
	log.Debug(func() string {
		if err != nil {
			return "Error ending transaction"
		}
		return "Successfully ended transaction"
	})
	return err
}

// RollbackTransaction aborts the transaction. No statement issued since
// StartTransaction was called will take effect.
func (db *DB) RollbackTransaction() error {
	_, err := db.dbConn.Exec("ROLLBACK")
	log.Debug(func() string {
		if err != nil {
			return "Error rolling back transaction"
		}
		return "Successfully rolled back transaction"
	})
	return err
}
<commit_msg>Remove RowScanQuery<commit_after>package db

import (
	"database/sql"
	"os"

	_ "github.com/mattn/go-sqlite3"

	log "code.google.com/p/log4go"
)

const (
	dbName = "db.sqlite"
)

// The SQL database.
type DB struct {
	dbConn *sql.DB
}

// Query result types
type RowResult map[string]string
type RowResults []map[string]string

// New creates a new database. Deletes any existing database.
func New(dbPath string) *DB {
	os.Remove(dbPath)
	return Open(dbPath)
}

// Open an existing database, creating it if it does not exist.
func Open(dbPath string) *DB {
	log.Trace("SQLite database path is %s", dbPath)
	dbc, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Error(err)
		return nil
	}
	return &DB{
		dbConn: dbc,
	}
}

// Close closes the underlying database connection.
func (db *DB) Close() error {
	return db.dbConn.Close()
}

// Query runs the supplied query against the sqlite database. It returns a slice of
// RowResults.
func (db *DB) Query(query string) (RowResults, error) {
	rows, err := db.dbConn.Query(query)
	if err != nil {
		log.Error("failed to execute SQLite query", err.Error())
		return nil, err
	}
	defer rows.Close()

	results := make(RowResults, 0)

	columns, _ := rows.Columns()
	rawResult := make([][]byte, len(columns))
	dest := make([]interface{}, len(columns))
	for i, _ := range rawResult {
		dest[i] = &rawResult[i] // Pointers to each string in the interface slice
	}

	for rows.Next() {
		err = rows.Scan(dest...)
		if err != nil {
			log.Error("failed to scan SQLite row", err.Error())
			return nil, err
		}

		r := make(RowResult)
		for i, raw := range rawResult {
			if raw == nil {
				r[columns[i]] = "null"
			} else {
				r[columns[i]] = string(raw)
			}
		}
		results = append(results, r)
	}
	log.Debug(func() string { return "Executed query successfully: " + query })
	return results, nil
}

// Execute executes the given sqlite statement, of a type that doesn't return rows.
func (db *DB) Execute(stmt string) error {
	_, err := db.dbConn.Exec(stmt)
	log.Debug(func() string {
		if err != nil {
			return "Error executing " + stmt
		}
		return "Successfully executed " + stmt
	})
	return err
}

// StartTransaction starts an explicit transaction.
func (db *DB) StartTransaction() error {
	_, err := db.dbConn.Exec("BEGIN")
	log.Debug(func() string {
		if err != nil {
			return "Error starting transaction"
		}
		return "Successfully started transaction"
	})
	return err
}

// CommitTransaction commits all changes made since StartTraction was called.
func (db *DB) CommitTransaction() error {
	_, err := db.dbConn.Exec("END")
	log.Debug(func() string {
		if err != nil {
			return "Error ending transaction"
		}
		return "Successfully ended transaction"
	})
	return err
}

// RollbackTransaction aborts the transaction. No statement issued since
// StartTransaction was called will take effect.
func (db *DB) RollbackTransaction() error {
	_, err := db.dbConn.Exec("ROLLBACK")
	log.Debug(func() string {
		if err != nil {
			return "Error rolling back transaction"
		}
		return "Successfully rolled back transaction"
	})
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"go/ast"
	"go/parser"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

type mImportPaths struct {
	Fn  string
	Src string
	Env map[string]string
}

type mImportPathsDecl struct {
	Name string `json:"name"`
	Path string `json:"path"`
}

func (m *mImportPaths) Call() (interface{}, string) {
	imports := []mImportPathsDecl{}
	_, af, err := parseAstFile(m.Fn, m.Src, parser.ImportsOnly)
	if err != nil {
		return M{}, err.Error()
	}

	if m.Fn != "" || m.Src != "" {
		for _, decl := range af.Decls {
			if gdecl, ok := decl.(*ast.GenDecl); ok && len(gdecl.Specs) > 0 {
				for _, spec := range gdecl.Specs {
					if ispec, ok := spec.(*ast.ImportSpec); ok {
						sd := mImportPathsDecl{
							Path: unquote(ispec.Path.Value),
						}
						if ispec.Name != nil {
							sd.Name = ispec.Name.String()
						}
						imports = append(imports, sd)
					}
				}
			}
		}
	}

	paths := map[string]string{}
	l, _ := importPaths(m.Env)
	for _, p := range l {
		paths[p] = ""
	}

	res := M{
		"imports": imports,
		"paths":   paths,
	}
	return res, ""
}

func init() {
	registry.Register("import_paths", func(_ *Broker) Caller {
		return &mImportPaths{
			Env: map[string]string{},
		}
	})
}

func importPaths(environ map[string]string) ([]string, error) {
	imports := []string{
		"unsafe",
	}
	paths := map[string]bool{}

	env := []string{
		environ["GOPATH"],
		environ["GOROOT"],
		os.Getenv("GOPATH"),
		os.Getenv("GOROOT"),
		runtime.GOROOT(),
	}
	for _, ent := range env {
		for _, path := range filepath.SplitList(ent) {
			if path != "" {
				paths[path] = true
			}
		}
	}

	seen := map[string]bool{}
	pfx := strings.HasPrefix
	sfx := strings.HasSuffix
	osArch := runtime.GOOS + "_" + runtime.GOARCH
	for root, _ := range paths {
		root = filepath.Join(root, "pkg", osArch)
		walkF := func(p string, info os.FileInfo, err error) error {
			if err == nil && !info.IsDir() {
				p, e := filepath.Rel(root, p)
				if e == nil && sfx(p, ".a") {
					p := p[:len(p)-2]
					if !pfx(p, ".") && !pfx(p, "_") && !sfx(p, "_test") {
						p = path.Clean(filepath.ToSlash(p))
						if !seen[p] {
							seen[p] = true
							imports = append(imports, p)
						}
					}
				}
			}
			return nil
		}
		filepath.Walk(root, walkF)
	}
	return imports, nil
}
<commit_msg>* implement switching between the legacy `.a` imports and src imports<commit_after>package main

import (
	"go/ast"
	"go/parser"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

type mImportPaths struct {
	Fn               string
	Src              string
	Env              map[string]string
	UseLegacyImports bool
	WantPkgNames     bool
}

type mImportPathsDecl struct {
	Name string `json:"name"`
	Path string `json:"path"`
}

func (m *mImportPaths) Call() (interface{}, string) {
	imports := []mImportPathsDecl{}
	_, af, err := parseAstFile(m.Fn, m.Src, parser.ImportsOnly)
	if err != nil {
		return M{}, err.Error()
	}

	if m.Fn != "" || m.Src != "" {
		for _, decl := range af.Decls {
			if gdecl, ok := decl.(*ast.GenDecl); ok && len(gdecl.Specs) > 0 {
				for _, spec := range gdecl.Specs {
					if ispec, ok := spec.(*ast.ImportSpec); ok {
						sd := mImportPathsDecl{
							Path: unquote(ispec.Path.Value),
						}
						if ispec.Name != nil {
							sd.Name = ispec.Name.String()
						}
						imports = append(imports, sd)
					}
				}
			}
		}
	}

	paths := map[string]string{}

	if m.UseLegacyImports {
		l, _ := importPaths(m.Env)
		for _, p := range l {
			paths[p] = ""
		}
	} else {
		for _, m := range mPkgPathsRes(m.Env, []string{"main"}, m.WantPkgNames) {
			for p, nm := range m {
				paths[p] = nm
			}
		}
	}

	res := M{
		"imports": imports,
		"paths":   paths,
	}
	return res, ""
}

func init() {
	registry.Register("import_paths", func(_ *Broker) Caller {
		return &mImportPaths{
			Env: map[string]string{},
		}
	})
}

func importPaths(environ map[string]string) ([]string, error) {
	imports := []string{
		"unsafe",
	}
	paths := map[string]bool{}

	env := []string{
		environ["GOPATH"],
		environ["GOROOT"],
		os.Getenv("GOPATH"),
		os.Getenv("GOROOT"),
		runtime.GOROOT(),
	}
	for _, ent := range env {
		for _, path := range filepath.SplitList(ent) {
			if path != "" {
				paths[path] = true
			}
		}
	}

	seen := map[string]bool{}
	pfx := strings.HasPrefix
	sfx := strings.HasSuffix
	osArch := runtime.GOOS + "_" + runtime.GOARCH
	for root, _ := range paths {
		root = filepath.Join(root, "pkg", osArch)
		walkF := func(p string, info os.FileInfo, err error) error {
			if err == nil && !info.IsDir() {
				p, e := filepath.Rel(root, p)
				if e == nil && sfx(p, ".a") {
					p := p[:len(p)-2]
					if !pfx(p, ".") && !pfx(p, "_") && !sfx(p, "_test") {
						p = path.Clean(filepath.ToSlash(p))
						if !seen[p] {
							seen[p] = true
							imports = append(imports, p)
						}
					}
				}
			}
			return nil
		}
		filepath.Walk(root, walkF)
	}
	return imports, nil
}
<|endoftext|>