<commit_before>/*

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 kubectl

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"

	api "sigs.k8s.io/multi-tenancy/incubator/hnc/api/v1alpha2"
)

var setResourceCmd = &cobra.Command{
	Use: fmt.Sprintf("set-resource RESOURCE [--group GROUP] [--force] --mode <%s|%s|%s>",
		api.Propagate, api.Remove, api.Ignore),
	Short: "Sets the HNC configuration of a specific resource",
	Example: fmt.Sprintf("  # Set configuration of a core type\n" +
		"  kubectl hns config set-resource secrets --mode Ignore\n\n" +
		"  # Set configuration of a custom type\n" +
		"  kubectl hns config set-resource crontabs --group stable.example.com --mode Propagate"),
	Args: cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		resource := args[0]
		flags := cmd.Flags()
		group, _ := flags.GetString("group")
		modeStr, _ := flags.GetString("mode")
		mode := api.SynchronizationMode(modeStr)
		force, _ := flags.GetBool("force")
		config := client.getHNCConfig()

		exist := false
		for i := 0; i < len(config.Spec.Resources); i++ {
			r := &config.Spec.Resources[i]
			if r.Group == group && r.Resource == resource {
				if r.Mode == api.Ignore && mode == api.Propagate && !force {
					fmt.Printf("Switching directly from 'Ignore' to 'Propagate' mode could cause existing %q objects in "+
						"child namespaces to be overwritten by objects from ancestor namespaces.\n", resource)
					fmt.Println("If you are sure you want to proceed with this operation, use the '--force' flag.")
					fmt.Println("If you are not sure and would like to see what source objects would be overwritten," +
						"please switch to 'Remove' first. To see how to enable propagation safely, refer to " +
						"https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/docs/user-guide/how-to.md#admin-types")
					os.Exit(1)
				}
				r.Mode = mode
				exist = true
				break
			}
		}

		if !exist {
			config.Spec.Resources = append(config.Spec.Resources,
				api.ResourceSpec{
					Group:    group,
					Resource: resource,
					Mode:     mode,
				})
		}

		client.updateHNCConfig(config)
	},
}

func newSetResourceCmd() *cobra.Command {
	setResourceCmd.Flags().String("group", "", "The group of the resource; may be omitted for core resources (or explicitly set to the empty string)")
	setResourceCmd.Flags().String("mode", "", "The synchronization mode: one of Propagate, Remove or Ignore")
	setResourceCmd.Flags().BoolP("force", "f", false, "Allow the synchronization mode to be changed directly from Ignore to Propagate despite the dangers of doing so")
	return setResourceCmd
}
<commit_msg>This normalize synchronize mode string format to match with current supported mode: Propagate, Ignore, Remove, allows synchronize mode input to be case-insensitive.<commit_after>/*

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 kubectl

import (
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"

	api "sigs.k8s.io/multi-tenancy/incubator/hnc/api/v1alpha2"
)

var setResourceCmd = &cobra.Command{
	Use: fmt.Sprintf("set-resource RESOURCE [--group GROUP] [--force] --mode <%s|%s|%s>",
		api.Propagate, api.Remove, api.Ignore),
	Short: "Sets the HNC configuration of a specific resource",
	Example: fmt.Sprintf("  # Set configuration of a core type\n" +
		"  kubectl hns config set-resource secrets --mode Ignore\n\n" +
		"  # Set configuration of a custom type\n" +
		"  kubectl hns config set-resource crontabs --group stable.example.com --mode Propagate"),
	Args: cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		resource := args[0]
		flags := cmd.Flags()
		group, _ := flags.GetString("group")
		modeStr, _ := flags.GetString("mode")
		mode := api.SynchronizationMode(normalizeModeString(modeStr))
		force, _ := flags.GetBool("force")
		config := client.getHNCConfig()

		exist := false
		for i := 0; i < len(config.Spec.Resources); i++ {
			r := &config.Spec.Resources[i]
			if r.Group == group && r.Resource == resource {
				if r.Mode == api.Ignore && mode == api.Propagate && !force {
					fmt.Printf("Switching directly from 'Ignore' to 'Propagate' mode could cause existing %q objects in "+
						"child namespaces to be overwritten by objects from ancestor namespaces.\n", resource)
					fmt.Println("If you are sure you want to proceed with this operation, use the '--force' flag.")
					fmt.Println("If you are not sure and would like to see what source objects would be overwritten," +
						"please switch to 'Remove' first. To see how to enable propagation safely, refer to " +
						"https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/docs/user-guide/how-to.md#admin-types")
					os.Exit(1)
				}
				r.Mode = mode
				exist = true
				break
			}
		}

		if !exist {
			config.Spec.Resources = append(config.Spec.Resources,
				api.ResourceSpec{
					Group:    group,
					Resource: resource,
					Mode:     mode,
				})
		}

		client.updateHNCConfig(config)
	},
}

// normalizeModeString corrects format of input Synchronization Mode string
func normalizeModeString(modeStr string) string {
	low := strings.ToLower(modeStr)
	return strings.Title(low)
}

func newSetResourceCmd() *cobra.Command {
	setResourceCmd.Flags().String("group", "", "The group of the resource; may be omitted for core resources (or explicitly set to the empty string)")
	setResourceCmd.Flags().String("mode", "", "The synchronization mode: one of Propagate, Remove or Ignore")
	setResourceCmd.Flags().BoolP("force", "f", false, "Allow the synchronization mode to be changed directly from Ignore to Propagate despite the dangers of doing so")
	return setResourceCmd
}
<|endoftext|>


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

package flushfs_test

import (
	"io"
	"os"
	"path"
	"sync"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/flushfs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFlushFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FlushFSTest struct {
	samples.SampleTest

	mu sync.Mutex

	// GUARDED_BY(mu)
	flushes []string

	// GUARDED_BY(mu)
	fsyncs []string
}

func init() { RegisterTestSuite(&FlushFSTest{}) }

func (t *FlushFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a file system.
	reportTo := func(slice *[]string) func(string) {
		return func(s string) {
			t.mu.Lock()
			defer t.mu.Unlock()
			*slice = append(*slice, s)
		}
	}

	t.FileSystem, err = flushfs.NewFileSystem(
		reportTo(&t.flushes),
		reportTo(&t.fsyncs))

	if err != nil {
		panic(err)
	}

	// Mount it.
	t.SampleTest.SetUp(ti)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

// Match byte slices equal to the supplied string.
func byteSliceEq(expected string) Matcher

// Return a copy of the current contents of t.flushes.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFlushes() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.flushes))
	copy(p, t.flushes)
	return
}

// Return a copy of the current contents of t.fsyncs.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFsyncs() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.fsyncs))
	copy(p, t.fsyncs)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FlushFSTest) CloseReports_ReadWrite() {
	var n int
	var off int64
	var err error
	buf := make([]byte, 1024)

	// Open the file.
	f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
	AssertEq(nil, err)

	defer func() {
		if f != nil {
			ExpectEq(nil, f.Close())
		}
	}()

	// Write some contents to the file.
	n, err = f.Write([]byte("taco"))
	AssertEq(nil, err)
	AssertEq(4, n)

	// Seek and read them back.
	off, err = f.Seek(0, 0)
	AssertEq(nil, err)
	AssertEq(0, off)

	n, err = f.Read(buf)
	AssertThat(err, AnyOf(nil, io.EOF))
	AssertEq("taco", string(buf[:n]))

	// At this point, no flushes or fsyncs should have happened.
	AssertThat(t.getFlushes(), ElementsAre())
	AssertThat(t.getFsyncs(), ElementsAre())

	// Close the file.
	err = f.Close()
	f = nil
	AssertEq(nil, err)

	// Now we should have received the flush operation (but still no fsync).
	ExpectThat(t.getFlushes(), ElementsAre(byteSliceEq("taco")))
	ExpectThat(t.getFsyncs(), ElementsAre())
}

func (t *FlushFSTest) CloseReports_ReadOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_WriteOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_NonOverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_OverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseError() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncReports() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncError() {
	AssertTrue(false, "TODO")
}
<commit_msg>byteSliceEq<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package flushfs_test

import (
	"errors"
	"fmt"
	"io"
	"os"
	"path"
	"sync"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/flushfs"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFlushFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FlushFSTest struct {
	samples.SampleTest

	mu sync.Mutex

	// GUARDED_BY(mu)
	flushes []string

	// GUARDED_BY(mu)
	fsyncs []string
}

func init() { RegisterTestSuite(&FlushFSTest{}) }

func (t *FlushFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a file system.
	reportTo := func(slice *[]string) func(string) {
		return func(s string) {
			t.mu.Lock()
			defer t.mu.Unlock()
			*slice = append(*slice, s)
		}
	}

	t.FileSystem, err = flushfs.NewFileSystem(
		reportTo(&t.flushes),
		reportTo(&t.fsyncs))

	if err != nil {
		panic(err)
	}

	// Mount it.
	t.SampleTest.SetUp(ti)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

// Match byte slices equal to the supplied string.
func byteSliceEq(expected string) Matcher {
	pred := func(c interface{}) error {
		slice, ok := c.([]byte)
		if !ok {
			return errors.New("which is not []byte")
		}

		if string(slice) != expected {
			return fmt.Errorf("which is string \"%s\"", string(slice))
		}

		return nil
	}

	return NewMatcher(
		pred,
		fmt.Sprintf("byte slice equal to string \"%s\"", expected))
}

// Return a copy of the current contents of t.flushes.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFlushes() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.flushes))
	copy(p, t.flushes)
	return
}

// Return a copy of the current contents of t.fsyncs.
//
// LOCKS_EXCLUDED(t.mu)
func (t *FlushFSTest) getFsyncs() (p []string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	p = make([]string, len(t.fsyncs))
	copy(p, t.fsyncs)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FlushFSTest) CloseReports_ReadWrite() {
	var n int
	var off int64
	var err error
	buf := make([]byte, 1024)

	// Open the file.
	f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
	AssertEq(nil, err)

	defer func() {
		if f != nil {
			ExpectEq(nil, f.Close())
		}
	}()

	// Write some contents to the file.
	n, err = f.Write([]byte("taco"))
	AssertEq(nil, err)
	AssertEq(4, n)

	// Seek and read them back.
	off, err = f.Seek(0, 0)
	AssertEq(nil, err)
	AssertEq(0, off)

	n, err = f.Read(buf)
	AssertThat(err, AnyOf(nil, io.EOF))
	AssertEq("taco", string(buf[:n]))

	// At this point, no flushes or fsyncs should have happened.
	AssertThat(t.getFlushes(), ElementsAre())
	AssertThat(t.getFsyncs(), ElementsAre())

	// Close the file.
	err = f.Close()
	f = nil
	AssertEq(nil, err)

	// Now we should have received the flush operation (but still no fsync).
	ExpectThat(t.getFlushes(), ElementsAre(byteSliceEq("taco")))
	ExpectThat(t.getFsyncs(), ElementsAre())
}

func (t *FlushFSTest) CloseReports_ReadOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_WriteOnly() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_NonOverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseReports_MultipleTimes_OverlappingFileHandles() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) CloseError() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncReports() {
	AssertTrue(false, "TODO")
}

func (t *FlushFSTest) FsyncError() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package kcl

import (
	"sync"
	"sync/atomic"
	"time"

	"github.com/aws/aws-sdk-go/service/kinesis"
)

var (
	streamConsumerUpdateMin = time.Second * 5
	streamConsumerUpdateMax = time.Second * 30
	restartConsumerInterval = time.Duration(60) * time.Second
)

type SharedReader struct {
	client *Client

	streamName string
	clientName string

	err error

	recordsChan chan *kinesis.Record
	closed      bool
	closedMu    sync.Mutex

	consumers  []*LockedReader
	consumerWg *sync.WaitGroup

	runningConsumers int64
}

func (c *Client) NewSharedReader(streamName string, clientName string) (*SharedReader, error) {
	if c.distlock == nil {
		return nil, ErrMissingLocker
	}
	if c.checkpoint == nil {
		return nil, ErrMissingCheckpointer
	}

	r := &SharedReader{
		client:     c,
		streamName: streamName,
		clientName: clientName,

		recordsChan: make(chan *kinesis.Record),

		consumers:  []*LockedReader{},
		consumerWg: &sync.WaitGroup{},
	}

	return r, nil
}

func (sr *SharedReader) Records() chan *kinesis.Record {
	go sr.consumeRecords()
	return sr.recordsChan
}

func (sr *SharedReader) consumeShard(lockedReader *LockedReader) {
	sr.consumerWg.Add(1)
	atomic.AddInt64(&sr.runningConsumers, 1)
	defer sr.consumerWg.Done()
	defer atomic.AddInt64(&sr.runningConsumers, -1)

	Logger.Printf("Consuming shard: %s", lockedReader.shardId)

	go func() {
		<-time.After(restartConsumerInterval)

		if err := lockedReader.Close(); err != nil {
			sr.err = err
			sr.Close()
		}
	}()

	for record := range lockedReader.Records() {
		Logger.Printf("Shard %s | Message: %s", lockedReader.shardId, string(record.Data))

		sr.recordsChan <- record
	}
	if err := lockedReader.Close(); err != nil {
		sr.err = err
		sr.Close()
	}
}

func (sr *SharedReader) consumeRecords() {
	for {
		if sr.closed {
			return
		}

		streamDescription, err := sr.client.StreamDescription(sr.streamName)
		if err != nil {
			sr.err = err
			return
		}

		for _, shard := range streamDescription.Shards {
			lockedReader, err := sr.client.NewLockedShardReader(sr.streamName, *shard.ShardId, sr.clientName)
			if err == ErrShardLocked {
				continue
			} else if err != nil {
				sr.err = err
				return
			}

			sr.consumers = append(sr.consumers, lockedReader)
			go sr.consumeShard(lockedReader)

			break // one shard per interval
		}

		updateInterval := streamConsumerUpdateMin * time.Duration(sr.runningConsumers+1)
		if updateInterval > streamConsumerUpdateMax {
			updateInterval = streamConsumerUpdateMax
		}
		time.Sleep(updateInterval)
	}
}

func (sr *SharedReader) Close() error {
	sr.closedMu.Lock()
	defer sr.closedMu.Unlock()

	if !sr.closed {
		sr.closed = true
		go func() {
			sr.consumerWg.Wait()
			close(sr.recordsChan)
		}()
	}

	return sr.err
}

func (sr *SharedReader) UpdateCheckpoint() error {
	for _, c := range sr.consumers {
		err := c.UpdateCheckpoint()
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Remove old shard readers<commit_after>package kcl

import (
	"sync"
	"sync/atomic"
	"time"

	"github.com/aws/aws-sdk-go/service/kinesis"
)

var (
	streamConsumerUpdateMin = time.Second * 5
	streamConsumerUpdateMax = time.Second * 30
	restartConsumerInterval = time.Duration(60) * time.Second
)

type SharedReader struct {
	client *Client

	streamName string
	clientName string

	err error

	recordsChan chan *kinesis.Record
	closed      bool
	closedMu    sync.Mutex

	consumers   []*LockedReader
	consumersMu sync.Mutex
	consumerWg  *sync.WaitGroup

	runningConsumers int64
}

func (c *Client) NewSharedReader(streamName string, clientName string) (*SharedReader, error) {
	if c.distlock == nil {
		return nil, ErrMissingLocker
	}
	if c.checkpoint == nil {
		return nil, ErrMissingCheckpointer
	}

	r := &SharedReader{
		client:     c,
		streamName: streamName,
		clientName: clientName,

		recordsChan: make(chan *kinesis.Record),

		consumers:  []*LockedReader{},
		consumerWg: &sync.WaitGroup{},
	}

	return r, nil
}

func (sr *SharedReader) Records() chan *kinesis.Record {
	go sr.consumeRecords()
	return sr.recordsChan
}

func (sr *SharedReader) consumeShard(lockedReader *LockedReader) {
	sr.consumerWg.Add(1)
	atomic.AddInt64(&sr.runningConsumers, 1)
	defer sr.consumerWg.Done()
	defer atomic.AddInt64(&sr.runningConsumers, -1)

	Logger.Printf("Consuming shard: %s", lockedReader.shardId)

	go func() {
		<-time.After(restartConsumerInterval)

		if err := lockedReader.Close(); err != nil {
			sr.err = err
			sr.Close()
		}
	}()

	for record := range lockedReader.Records() {
		Logger.Printf("Shard %s | Message: %s", lockedReader.shardId, string(record.Data))

		sr.recordsChan <- record
	}
	if err := lockedReader.Close(); err != nil {
		sr.err = err
		sr.Close()
	}
}

func (sr *SharedReader) consumeRecords() {
	for {
		if sr.closed {
			return
		}

		streamDescription, err := sr.client.StreamDescription(sr.streamName)
		if err != nil {
			sr.err = err
			return
		}

		for _, shard := range streamDescription.Shards {
			lockedReader, err := sr.client.NewLockedShardReader(sr.streamName, *shard.ShardId, sr.clientName)
			if err == ErrShardLocked {
				continue
			} else if err != nil {
				sr.err = err
				return
			}

			sr.consumersMu.Lock()
			sr.consumers = append(sr.consumers, lockedReader)
			sr.consumersMu.Unlock()

			go sr.consumeShard(lockedReader)

			break // one shard per interval
		}

		updateInterval := streamConsumerUpdateMin * time.Duration(sr.runningConsumers+1)
		if updateInterval > streamConsumerUpdateMax {
			updateInterval = streamConsumerUpdateMax
		}
		time.Sleep(updateInterval)
	}
}

func (sr *SharedReader) Close() error {
	sr.closedMu.Lock()
	defer sr.closedMu.Unlock()

	if !sr.closed {
		sr.closed = true
		go func() {
			sr.consumerWg.Wait()
			close(sr.recordsChan)
		}()
	}

	return sr.err
}

func (sr *SharedReader) UpdateCheckpoint() error {
	sr.consumersMu.Lock()
	defer sr.consumersMu.Unlock()

	newConsumers := sr.consumers[0:0]

	for _, c := range sr.consumers {
		closed := c.IsClosed()
		err := c.UpdateCheckpoint()
		if err != nil {
			return err
		}
		if !closed {
			newConsumers = append(newConsumers, c)
		}
	}

	sr.consumers = newConsumers

	return nil
}
<|endoftext|>


<commit_before>package flagnet

// Value is like flag.Getter (which is a superset of flag.Value)
type Value interface {
	String() string
	Set(string) error
	Get() interface{}
}
<commit_msg>flagnet: add doc links<commit_after>package flagnet

// Value is like [flag.Getter] (which is a superset of [flag.Value]).
type Value interface {
	String() string
	Set(string) error
	Get() interface{}
}
<|endoftext|>


<commit_before>package fsOp

import (
	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/rio/fs"
)

/*
	Makes dirs recursively so the requested path exists, applying the assigned metadata
	to each one that needed to be produced.

	Existing dirs are not mutated.

	Symlinks will be traversed without comment (i.e. this will never emit ErrBreakout).
	(Note that this means this function is *not* used in either transmats nor stitch.)
*/
func MkdirAll(afs fs.FS, path fs.RelPath, perms fs.Perms) error {
	// Check if the path already exists.
	stat, err := afs.Stat(path)
	// Switch on status of the (derefenced) file.
	//  Recurse and mkdir if necessary.
	switch Category(err) {
	case nil:
		if stat.Type == fs.Type_Dir {
			return nil
		}
		return Errorf(fs.ErrNotDir, "%s already exists and is a %s not %s", afs.BasePath().Join(path), stat.Type, fs.Type_Dir)
	case fs.ErrNotExists:
		if path == (fs.RelPath{}) {
			return Errorf(fs.ErrNotExists, "base path %s does not exist!", afs.BasePath())
		}
		if err := MkdirAll(afs, path.Dir(), perms); err != nil {
			return err
		}
		if err := afs.Mkdir(path, perms); err != nil {
			switch Category(err) {
			case fs.ErrAlreadyExists:
				// this seemingly-contradictory message means the path does exist... it's just that stat said it didn't, beacuse it's a dangling symlink.
				return Errorf(fs.ErrNotDir, "%s already exists and is a %s not %s", afs.BasePath().Join(path), fs.Type_Symlink, fs.Type_Dir)
			default:
				return err
			}
		}
		return nil
	case fs.ErrNotDir:
		// Reformat the error a tad to not say "lstat", which is distracting.
		return Errorf(fs.ErrNotDir, "%s has parents which are not a directory", afs.BasePath().Join(path))
	default:
		return err
	}
}

/*
	Records the mtime property currently set on a path and returns a function which
	will force it to that value again.

	The typical use for this is `defer RepairMtime(fs, "./somedir")()` right
	before invoking some funcs which will mutate the contents of that dir.
	When the rest of the changes are done and the function returns, the mtime
	of the dir will be forced back to its previous value, seemingly unchanged.
*/
func RepairMtime(afs fs.FS, path fs.RelPath) func() {
	fmeta, _ := afs.LStat(path)
	return func() {
		afs.SetTimesLNano(path, fmeta.Mtime, fs.DefaultAtime)
	}
}
<commit_msg>fsOp: fix MkdirAll in presense of filesystem race.<commit_after>package fsOp

import (
	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/rio/fs"
)

/*
	Makes dirs recursively so the requested path exists, applying the assigned metadata
	to each one that needed to be produced.

	Existing dirs are not mutated.

	Symlinks will be traversed without comment (i.e. this will never emit ErrBreakout).
	(Note that this means this function is *not* used in either transmats nor stitch.)
*/
func MkdirAll(afs fs.FS, path fs.RelPath, perms fs.Perms) error {
	// Check if the path already exists.
	stat, err := afs.Stat(path)
	// Switch on status of the (derefenced) file.
	//  Recurse and mkdir if necessary.
	switch Category(err) {
	case nil:
		if stat.Type == fs.Type_Dir {
			return nil
		}
		return Errorf(fs.ErrNotDir, "%s already exists and is a %s not %s", afs.BasePath().Join(path), stat.Type, fs.Type_Dir)
	case fs.ErrNotExists:
		if path == (fs.RelPath{}) {
			return Errorf(fs.ErrNotExists, "base path %s does not exist!", afs.BasePath())
		}
		if err := MkdirAll(afs, path.Dir(), perms); err != nil {
			return err
		}
		if err := afs.Mkdir(path, perms); err != nil {
			// Re-check if it exists and is a dir; we may have been raced, and we're okay with that.
			stat, err1 := afs.LStat(path)
			if err1 == nil && stat.Type == fs.Type_Dir {
				return nil
			}
			switch Category(err) {
			case fs.ErrAlreadyExists:
				// this seemingly-contradictory message means the path does exist... it's just that stat said it didn't, beacuse it's a dangling symlink.
				return Errorf(fs.ErrNotDir, "%s already exists and is a %s not %s", afs.BasePath().Join(path), fs.Type_Symlink, fs.Type_Dir)
			default:
				return err
			}
		}
		return nil
	case fs.ErrNotDir:
		// Reformat the error a tad to not say "lstat", which is distracting.
		return Errorf(fs.ErrNotDir, "%s has parents which are not a directory", afs.BasePath().Join(path))
	default:
		return err
	}
}

/*
	Records the mtime property currently set on a path and returns a function which
	will force it to that value again.

	The typical use for this is `defer RepairMtime(fs, "./somedir")()` right
	before invoking some funcs which will mutate the contents of that dir.
	When the rest of the changes are done and the function returns, the mtime
	of the dir will be forced back to its previous value, seemingly unchanged.
*/
func RepairMtime(afs fs.FS, path fs.RelPath) func() {
	fmeta, _ := afs.LStat(path)
	return func() {
		afs.SetTimesLNano(path, fmeta.Mtime, fs.DefaultAtime)
	}
}
<|endoftext|>


<commit_before>package rev

import (
	"net/http"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

type Request struct {
	*http.Request
	ContentType    string
	Format         string // "html", "xml", "json", or "text"
	AcceptLanguage AcceptLanguages
}

type Response struct {
	Status      int
	ContentType string

	Out http.ResponseWriter
}

func NewRequest(r *http.Request) *Request {
	return &Request{
		Request:        r,
		ContentType:    ResolveContentType(r),
		Format:         ResolveFormat(r),
		AcceptLanguage: ResolveAcceptLanguage(r),
	}
}

func NewResponse(w http.ResponseWriter) *Response {
	return &Response{Out: w}
}

var (
	controllerType    = reflect.TypeOf(Controller{})
	controllerPtrType = reflect.TypeOf(&Controller{})
)

func NewAppController(req *Request, resp *Response, controllerName, methodName string) (*Controller, reflect.Value) {
	var appControllerType *ControllerType = LookupControllerType(controllerName)
	if appControllerType == nil {
		INFO.Printf("Controller %s not found: %s", controllerName, req.URL)
		return nil, reflect.ValueOf(nil)
	}

	controller := NewController(req, resp, appControllerType)
	appControllerPtr := initNewAppController(appControllerType.Type, controller)

	// Set the method being called.
	controller.MethodType = appControllerType.Method(methodName)
	if controller.MethodType == nil {
		INFO.Println("Failed to find method", methodName, "on Controller",
			controllerName)
		return nil, reflect.ValueOf(nil)
	}

	return controller, appControllerPtr
}

// This is a helper that initializes (zeros) a new app controller value.
// Generally, everything is set to its zero value, except:
// 1. Embedded controller pointers are newed up.
// 2. The rev.Controller embedded type is set to the value provided.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType reflect.Type, c *Controller) reflect.Value {
	// It might be a multi-level embedding, so we have to create new controllers
	// at every level of the hierarchy.
	// ASSUME: the first field in each type is the way up to rev.Controller.
	appControllerPtr := reflect.New(appControllerType)
	ptr := appControllerPtr
	for {
		var (
			embeddedField     reflect.Value = ptr.Elem().Field(0)
			embeddedFieldType reflect.Type  = embeddedField.Type()
		)

		// Check if it's the controller.
		if embeddedFieldType == controllerType {
			embeddedField.Set(reflect.ValueOf(c).Elem())
			break
		} else if embeddedFieldType == controllerPtrType {
			embeddedField.Set(reflect.ValueOf(c))
			break
		}

		// If the embedded field is a pointer, then instantiate an object and set it.
		// (If it's not a pointer, then it's already initialized)
		if embeddedFieldType.Kind() == reflect.Ptr {
			embeddedField.Set(reflect.New(embeddedFieldType.Elem()))
			ptr = embeddedField
		} else {
			ptr = embeddedField.Addr()
		}
	}
	return appControllerPtr
}

func RenderError(req *Request, resp *Response, err error) {
	stubController(req, resp).RenderError(err).Apply(req, resp)
}

// This function is useful if there is no relevant Controller available.
// It writes the 404 response immediately.
func NotFound(req *Request, resp *Response, msg string) {
	stubController(req, resp).NotFound(msg).Apply(req, resp)
}

func stubController(req *Request, resp *Response) *Controller {
	return &Controller{
		Response: resp,
		RenderArgs: map[string]interface{}{
			"RunMode": RunMode,
		},
	}
}

// Get the content type.
// e.g. From "multipart/form-data; boundary=--" to "multipart/form-data"
// If none is specified, returns "text/html" by default.
func ResolveContentType(req *http.Request) string {
	contentType := req.Header.Get("Content-Type")
	if contentType == "" {
		return "text/html"
	}
	return strings.ToLower(strings.TrimSpace(strings.Split(contentType, ";")[0]))
}

func ResolveFormat(req *http.Request) string {
	accept := req.Header.Get("accept")

	switch {
	case accept == "",
		strings.HasPrefix(accept, "*/*"),
		strings.Contains(accept, "application/xhtml"),
		strings.Contains(accept, "text/html"):
		return "html"
	case strings.Contains(accept, "application/xml"),
		strings.Contains(accept, "text/xml"):
		return "xml"
	case strings.Contains(accept, "text/plain"):
		return "txt"
	case strings.Contains(accept, "application/json"),
		strings.Contains(accept, "text/javascript"):
		return "json"
	}

	return "html"
}

// A single language from the Accept-Language HTTP header.
type AcceptLanguage struct {
	Language string
	Quality  float32
}

// A collection of AcceptLanguage instances.
type AcceptLanguages []AcceptLanguage

func (al AcceptLanguages) Len() int           { return len(al) }
func (al AcceptLanguages) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AcceptLanguages) Less(i, j int) bool { return al[i].Quality > al[j].Quality }

// Resolve the Accept-Language header value.
//
// The results are sorted using the quality defined in the header for each language range with the most qualified
// language range as the first element in the slice.
//
// See the HTTP header fields specification (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) for more details.
func ResolveAcceptLanguage(req *http.Request) AcceptLanguages {
	header := req.Header.Get("Accept-Language")
	if header == "" {
		return nil
	}

	acceptLanguageHeaderValues := strings.Split(header, ",")
	acceptLanguages := make(AcceptLanguages, len(acceptLanguageHeaderValues))

	for i, languageRange := range acceptLanguageHeaderValues {
		if qualifiedRange := strings.Split(languageRange, ";q="); len(qualifiedRange) == 2 {
			quality, error := strconv.ParseFloat(qualifiedRange[1], 32)
			if error != nil {
				WARN.Printf("Detected malformed Accept-Language header quality in '%s', assuming quality is 1", languageRange)
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], 1}
			} else {
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], float32(quality)}
			}
		} else {
			acceptLanguages[i] = AcceptLanguage{languageRange, 1}
		}
	}

	sort.Sort(acceptLanguages)
	return acceptLanguages
}

// Write the header (for now, just the status code).
// The status may be set directly by the application (c.Response.Status = 501).
// if it isn't, then fall back to the provided status code.
func (resp *Response) WriteHeader(defaultStatusCode int, defaultContentType string) {
	if resp.Status == 0 {
		resp.Status = defaultStatusCode
	}
	if resp.ContentType == "" {
		resp.ContentType = defaultContentType
	}
	resp.Out.Header().Set("Content-Type", resp.ContentType)
	resp.Out.WriteHeader(resp.Status)
}

// Internal bookeeping

type ControllerType struct {
	Type    reflect.Type
	Methods []*MethodType
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	lowerName      string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

// Searches for a given exported method (case insensitive)
func (ct *ControllerType) Method(name string) *MethodType {
	lowerName := strings.ToLower(name)
	for _, method := range ct.Methods {
		if method.lowerName == lowerName {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

// Register a Controller and its Methods with Revel.
func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		m.lowerName = strings.ToLower(m.Name)
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[strings.ToLower(elem.Name())] = &ControllerType{Type: elem, Methods: methods}
	TRACE.Printf("Registered controller: %s", elem.Name())
}

func LookupControllerType(name string) *ControllerType {
	return controllers[strings.ToLower(name)]
}
<commit_msg>Fixed AcceptLanguages field name<commit_after>package rev

import (
	"net/http"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

type Request struct {
	*http.Request
	ContentType     string
	Format          string // "html", "xml", "json", or "text"
	AcceptLanguages AcceptLanguages
}

type Response struct {
	Status      int
	ContentType string

	Out http.ResponseWriter
}

func NewRequest(r *http.Request) *Request {
	return &Request{
		Request:         r,
		ContentType:     ResolveContentType(r),
		Format:          ResolveFormat(r),
		AcceptLanguages: ResolveAcceptLanguage(r),
	}
}

func NewResponse(w http.ResponseWriter) *Response {
	return &Response{Out: w}
}

var (
	controllerType    = reflect.TypeOf(Controller{})
	controllerPtrType = reflect.TypeOf(&Controller{})
)

func NewAppController(req *Request, resp *Response, controllerName, methodName string) (*Controller, reflect.Value) {
	var appControllerType *ControllerType = LookupControllerType(controllerName)
	if appControllerType == nil {
		INFO.Printf("Controller %s not found: %s", controllerName, req.URL)
		return nil, reflect.ValueOf(nil)
	}

	controller := NewController(req, resp, appControllerType)
	appControllerPtr := initNewAppController(appControllerType.Type, controller)

	// Set the method being called.
	controller.MethodType = appControllerType.Method(methodName)
	if controller.MethodType == nil {
		INFO.Println("Failed to find method", methodName, "on Controller",
			controllerName)
		return nil, reflect.ValueOf(nil)
	}

	return controller, appControllerPtr
}

// This is a helper that initializes (zeros) a new app controller value.
// Generally, everything is set to its zero value, except:
// 1. Embedded controller pointers are newed up.
// 2. The rev.Controller embedded type is set to the value provided.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType reflect.Type, c *Controller) reflect.Value {
	// It might be a multi-level embedding, so we have to create new controllers
	// at every level of the hierarchy.
	// ASSUME: the first field in each type is the way up to rev.Controller.
	appControllerPtr := reflect.New(appControllerType)
	ptr := appControllerPtr
	for {
		var (
			embeddedField     reflect.Value = ptr.Elem().Field(0)
			embeddedFieldType reflect.Type  = embeddedField.Type()
		)

		// Check if it's the controller.
		if embeddedFieldType == controllerType {
			embeddedField.Set(reflect.ValueOf(c).Elem())
			break
		} else if embeddedFieldType == controllerPtrType {
			embeddedField.Set(reflect.ValueOf(c))
			break
		}

		// If the embedded field is a pointer, then instantiate an object and set it.
		// (If it's not a pointer, then it's already initialized)
		if embeddedFieldType.Kind() == reflect.Ptr {
			embeddedField.Set(reflect.New(embeddedFieldType.Elem()))
			ptr = embeddedField
		} else {
			ptr = embeddedField.Addr()
		}
	}
	return appControllerPtr
}

func RenderError(req *Request, resp *Response, err error) {
	stubController(req, resp).RenderError(err).Apply(req, resp)
}

// This function is useful if there is no relevant Controller available.
// It writes the 404 response immediately.
func NotFound(req *Request, resp *Response, msg string) {
	stubController(req, resp).NotFound(msg).Apply(req, resp)
}

func stubController(req *Request, resp *Response) *Controller {
	return &Controller{
		Response: resp,
		RenderArgs: map[string]interface{}{
			"RunMode": RunMode,
		},
	}
}

// Get the content type.
// e.g. From "multipart/form-data; boundary=--" to "multipart/form-data"
// If none is specified, returns "text/html" by default.
func ResolveContentType(req *http.Request) string {
	contentType := req.Header.Get("Content-Type")
	if contentType == "" {
		return "text/html"
	}
	return strings.ToLower(strings.TrimSpace(strings.Split(contentType, ";")[0]))
}

func ResolveFormat(req *http.Request) string {
	accept := req.Header.Get("accept")

	switch {
	case accept == "",
		strings.HasPrefix(accept, "*/*"),
		strings.Contains(accept, "application/xhtml"),
		strings.Contains(accept, "text/html"):
		return "html"
	case strings.Contains(accept, "application/xml"),
		strings.Contains(accept, "text/xml"):
		return "xml"
	case strings.Contains(accept, "text/plain"):
		return "txt"
	case strings.Contains(accept, "application/json"),
		strings.Contains(accept, "text/javascript"):
		return "json"
	}

	return "html"
}

// A single language from the Accept-Language HTTP header.
type AcceptLanguage struct {
	Language string
	Quality  float32
}

// A collection of AcceptLanguage instances.
type AcceptLanguages []AcceptLanguage

func (al AcceptLanguages) Len() int           { return len(al) }
func (al AcceptLanguages) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AcceptLanguages) Less(i, j int) bool { return al[i].Quality > al[j].Quality }

// Resolve the Accept-Language header value.
//
// The results are sorted using the quality defined in the header for each language range with the most qualified
// language range as the first element in the slice.
//
// See the HTTP header fields specification (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) for more details.
func ResolveAcceptLanguage(req *http.Request) AcceptLanguages {
	header := req.Header.Get("Accept-Language")
	if header == "" {
		return nil
	}

	acceptLanguageHeaderValues := strings.Split(header, ",")
	acceptLanguages := make(AcceptLanguages, len(acceptLanguageHeaderValues))

	for i, languageRange := range acceptLanguageHeaderValues {
		if qualifiedRange := strings.Split(languageRange, ";q="); len(qualifiedRange) == 2 {
			quality, error := strconv.ParseFloat(qualifiedRange[1], 32)
			if error != nil {
				WARN.Printf("Detected malformed Accept-Language header quality in '%s', assuming quality is 1", languageRange)
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], 1}
			} else {
				acceptLanguages[i] = AcceptLanguage{qualifiedRange[0], float32(quality)}
			}
		} else {
			acceptLanguages[i] = AcceptLanguage{languageRange, 1}
		}
	}

	sort.Sort(acceptLanguages)
	return acceptLanguages
}

// Write the header (for now, just the status code).
// The status may be set directly by the application (c.Response.Status = 501).
// if it isn't, then fall back to the provided status code.
func (resp *Response) WriteHeader(defaultStatusCode int, defaultContentType string) {
	if resp.Status == 0 {
		resp.Status = defaultStatusCode
	}
	if resp.ContentType == "" {
		resp.ContentType = defaultContentType
	}
	resp.Out.Header().Set("Content-Type", resp.ContentType)
	resp.Out.WriteHeader(resp.Status)
}

// Internal bookeeping

type ControllerType struct {
	Type    reflect.Type
	Methods []*MethodType
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	lowerName      string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

// Searches for a given exported method (case insensitive)
func (ct *ControllerType) Method(name string) *MethodType {
	lowerName := strings.ToLower(name)
	for _, method := range ct.Methods {
		if method.lowerName == lowerName {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

// Register a Controller and its Methods with Revel.
func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		m.lowerName = strings.ToLower(m.Name)
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[strings.ToLower(elem.Name())] = &ControllerType{Type: elem, Methods: methods}
	TRACE.Printf("Registered controller: %s", elem.Name())
}

func LookupControllerType(name string) *ControllerType {
	return controllers[strings.ToLower(name)]
}
<|endoftext|>


<commit_before>package virtualbox

import (
	"bytes"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type StatusType string

const (
	NotFound  StatusType = "notfound"
	Invalid              = "invalid"
	Stopped              = "stopped"
	Suspended            = "suspended"
	Running              = "running"
	Saved                = "saved"
	// TODO: more statuses
)

func VboxManageOutput(exe string, args ...string) (string, error) {
	var stdout, stderr bytes.Buffer
	log.Debugf("Executing VBoxManageOutput: %#v", args)
	cmd := exec.Command(exe, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManageOutput error: %s", stderrString)
	}

	return stdout.String(), err
}

func VBoxManage(args ...string) (string, error) {
	return VboxManageOutput("vboxmanage", args...)
}

func Version() (string, error) {
	version, err := VBoxManage("--version")
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(version), nil
}

func FindSSHPort(vmName string) (string, error) {
	info, err := VBoxManage("showvminfo", vmName)
	portRe := regexp.MustCompile(`guestssh.*host port = (\d+)`)
	sshPort := portRe.FindStringSubmatch(info)
	return sshPort[1], err
}

func Exist(vmName string) bool {
	_, err := VBoxManage("showvminfo", vmName)
	if err != nil {
		return false
	}
	return true
}

func CreateOsVM(vmName string, templateName string) error {
	_, err := VBoxManage("clonevm", vmName, "--mode", "machine", "--name", templateName, "--register")
	return err
}

func FindNextPort(highport string, usedPorts [][]string) string {
	for _, port := range usedPorts {
		if highport == port[1] {
			var temp int
			temp, _ = strconv.Atoi(highport)
			temp = temp + 1
			highport = strconv.Itoa(temp)
			highport = FindNextPort(highport, usedPorts)
		}
	}
	return highport
}

func ConfigureSSH(vmName string, vmSSHPort string) error {
	var localport string
	output, err := VBoxManage("list", "vms", "-l")
	allPortsRe := regexp.MustCompile(`host port = (\d+)`)
	usedPorts := allPortsRe.FindAllStringSubmatch(output, -1)
	log.Debugln(usedPorts)
	if usedPorts == nil {
		localport = "2222"
	} else {
		highport := "2222"
		localport = FindNextPort(highport, usedPorts)
	}

	rule := fmt.Sprintf("guestssh,tcp,127.0.0.1,%s,,%s", localport, vmSSHPort)
	_, err = VBoxManage("modifyvm", vmName, "--natpf1", rule)
	return err
}

func CreateSnapshot(vmName string, snapshotName string) error {
	_, err := VBoxManage("snapshot", vmName, "take", snapshotName)
	return err
}

func RevertToSnapshot(vmName string) error {
	_, err := VBoxManage("snapshot", vmName, "restorecurrent")
	return err
}

func Start(vmName string) error {
	_, err := VBoxManage("startvm", vmName, "--type", "headless")
	return err
}

func Stop(vmName string) error {
	_, err := VBoxManage("controlvm", vmName, "poweroff")
	return err
}

func Kill(vmName string) error {
	_, err := VBoxManage("controlvm", vmName, "acpipowerbutton")
	return err
}

func Delete(vmName string) error {
	_, err := VBoxManage("unregistervm", vmName, "--delete")
	return err
}

func Status(vmName string) (StatusType, error) {
	output, err := VBoxManage("showvminfo", vmName, "--machinereadable")
	statusRe := regexp.MustCompile(`VMState="(\w+)"`)
	status := statusRe.FindStringSubmatch(output)
	if err != nil {
		return NotFound, err
	}
	return StatusType(status[1]), nil
}

func WaitForStatus(vmName string, vmStatus StatusType, seconds int) error {
	var status StatusType
	var err error
	for i := 0; i < seconds; i++ {
		status, err = Status(vmName)
		if err != nil {
			return err
		}
		if status == vmStatus {
			return nil
		}
		time.Sleep(time.Second)
	}
	return errors.New("VM " + vmName + " is in " + string(status) + " where it should be in " + string(vmStatus))
}

func Unregister(vmName string) error {
	_, err := VBoxManage("unregistervm", vmName)
	return err
}
<commit_msg>Rework fix for #1074 based on feedback<commit_after>package virtualbox

import (
	"bytes"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"net"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type StatusType string

const (
	NotFound  StatusType = "notfound"
	Invalid              = "invalid"
	Stopped              = "stopped"
	Suspended            = "suspended"
	Running              = "running"
	Saved                = "saved"
	// TODO: more statuses
)

func VboxManageOutput(exe string, args ...string) (string, error) {
	var stdout, stderr bytes.Buffer
	log.Debugf("Executing VBoxManageOutput: %#v", args)
	cmd := exec.Command(exe, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManageOutput error: %s", stderrString)
	}

	return stdout.String(), err
}

func VBoxManage(args ...string) (string, error) {
	return VboxManageOutput("vboxmanage", args...)
}

func Version() (string, error) {
	version, err := VBoxManage("--version")
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(version), nil
}

func FindSSHPort(vmName string) (string, error) {
	info, err := VBoxManage("showvminfo", vmName)
	portRe := regexp.MustCompile(`guestssh.*host port = (\d+)`)
	sshPort := portRe.FindStringSubmatch(info)
	return sshPort[1], err
}

func Exist(vmName string) bool {
	_, err := VBoxManage("showvminfo", vmName)
	if err != nil {
		return false
	}
	return true
}

func CreateOsVM(vmName string, templateName string) error {
	_, err := VBoxManage("clonevm", vmName, "--mode", "machine", "--name", templateName, "--register")
	return err
}

func FindNextPort(highport string, usedPorts [][]string) string {
	for _, port := range usedPorts {
		if highport == port[1] {
			var temp int
			temp, _ = strconv.Atoi(highport)
			temp = temp + 1
			highport = strconv.Itoa(temp)
			highport = FindNextPort(highport, usedPorts)
		}
	}
	return highport
}

func isPortUnassigned(highport string, usedPorts [][]string) bool {
	for _, port := range usedPorts {
		if highport == port[1] {
			return false
		}
	}
	return true
}

func getUsedVirtualboxPorts() ([][]string, error) {
	output, err := VBoxManage("list", "vms", "-l")
	if err != nil {
		return nil, err
	}
	allPortsRe := regexp.MustCompile(`host port = (\d+)`)
	usedPorts := allPortsRe.FindAllStringSubmatch(output, -1)
	log.Debugln(usedPorts)
	return usedPorts, nil
}

func ConfigureSSH(vmName string, vmSSHPort string) error {
	var localport string

	for {
		ln, err := net.Listen("tcp", ":0")
		if err != nil {
			log.Debugln(err)
			return err
		}
		defer ln.Close()

		addressElements := strings.Split(ln.Addr().String(), ":")
		localport = addressElements[len(addressElements)-1]

		usedPorts, err := getUsedVirtualboxPorts()
		if err != nil {
			log.Debugln(err)
			return err
		}

		if isPortUnassigned(localport, usedPorts) {
			break
		}
		// We're going around the loop again, getting a new ln
		ln.Close()
	}

	rule := fmt.Sprintf("guestssh,tcp,127.0.0.1,%s,,%s", localport, vmSSHPort)
	_, err := VBoxManage("modifyvm", vmName, "--natpf1", rule)
	return err
}

func CreateSnapshot(vmName string, snapshotName string) error {
	_, err := VBoxManage("snapshot", vmName, "take", snapshotName)
	return err
}

func RevertToSnapshot(vmName string) error {
	_, err := VBoxManage("snapshot", vmName, "restorecurrent")
	return err
}

func Start(vmName string) error {
	_, err := VBoxManage("startvm", vmName, "--type", "headless")
	return err
}

func Stop(vmName string) error {
	_, err := VBoxManage("controlvm", vmName, "poweroff")
	return err
}

func Kill(vmName string) error {
	_, err := VBoxManage("controlvm", vmName, "acpipowerbutton")
	return err
}

func Delete(vmName string) error {
	_, err := VBoxManage("unregistervm", vmName, "--delete")
	return err
}

func Status(vmName string) (StatusType, error) {
	output, err := VBoxManage("showvminfo", vmName, "--machinereadable")
	statusRe := regexp.MustCompile(`VMState="(\w+)"`)
	status := statusRe.FindStringSubmatch(output)
	if err != nil {
		return NotFound, err
	}
	return StatusType(status[1]), nil
}

func WaitForStatus(vmName string, vmStatus StatusType, seconds int) error {
	var status StatusType
	var err error
	for i := 0; i < seconds; i++ {
		status, err = Status(vmName)
		if err != nil {
			return err
		}
		if status == vmStatus {
			return nil
		}
		time.Sleep(time.Second)
	}
	return errors.New("VM " + vmName + " is in " + string(status) + " where it should be in " + string(vmStatus))
}

func Unregister(vmName string) error {
	_, err := VBoxManage("unregistervm", vmName)
	return err
}
<|endoftext|>


<commit_before>package smoke

import (
	"encoding/json"
	"os"
	"path/filepath"
)

type Config struct {
	SuiteName string `json:"suite_name"`

	ApiEndpoint string `json:"api"`
	AppsDomain  string `json:"apps_domain"`

	SkipSSLValidation bool `json:"skip_ssl_validation"`

	User     string `json:"user"`
	Password string `json:"password"`

	Org   string `json:"org"`
	Space string `json:"space"`

	UseExistingOrg   bool `json:"use_existing_org"`
	UseExistingSpace bool `json:"use_existing_space"`

	// existing app names - if empty the space will be managed and a random app name will be used
	LoggingApp string `json:"logging_app"`
	RuntimeApp string `json:"runtime_app"`

	ArtifactsDirectory string `json:"artifacts_directory"`
}

// singleton cache
var cachedConfig *Config

func GetConfig() *Config {
	if cachedConfig == nil {
		cachedConfig = loadConfig()
	}
	return cachedConfig
}

func loadConfig() *Config {
	config := newDefaultConfig()
	loadConfigFromJson(config)
	validateRequiredFields(config)
	return config
}

func newDefaultConfig() *Config {
	return &Config{
		ArtifactsDirectory: filepath.Join("..", "results"),
		UseExistingOrg: false,
		UseExistingSpace: false,
	}
}

func validateRequiredFields(config *Config) {
	if config.SuiteName == "" {
		panic("missing configuration 'suite_name'")
	}

	if config.ApiEndpoint == "" {
		panic("missing configuration 'api'")
	}

	if config.User == "" {
		panic("missing configuration 'user'")
	}

	if config.Password == "" {
		panic("missing configuration 'password'")
	}

	if config.Org == "" {
		panic("missing configuration 'org'")
	}

	if config.Space == "" {
		panic("missing configuration 'space'")
	}
}

// Loads the config from json into the supplied config object
func loadConfigFromJson(config *Config) {
	path := configPath()

	configFile, err := os.Open(path)
	if err != nil {
		panic(err)
	}

	decoder := json.NewDecoder(configFile)
	err = decoder.Decode(config)
	if err != nil {
		panic(err)
	}
}

func configPath() string {
	path := os.Getenv("CONFIG")
	if path == "" {
		panic("Must set $CONFIG to point to an integration config .json file.")
	}

	return path
}
<commit_msg>Enforce apps_domain in config<commit_after>package smoke

import (
	"encoding/json"
	"os"
	"path/filepath"
)

type Config struct {
	SuiteName string `json:"suite_name"`

	ApiEndpoint string `json:"api"`
	AppsDomain  string `json:"apps_domain"`

	SkipSSLValidation bool `json:"skip_ssl_validation"`

	User     string `json:"user"`
	Password string `json:"password"`

	Org   string `json:"org"`
	Space string `json:"space"`

	UseExistingOrg   bool `json:"use_existing_org"`
	UseExistingSpace bool `json:"use_existing_space"`

	// existing app names - if empty the space will be managed and a random app name will be used
	LoggingApp string `json:"logging_app"`
	RuntimeApp string `json:"runtime_app"`

	ArtifactsDirectory string `json:"artifacts_directory"`
}

// singleton cache
var cachedConfig *Config

func GetConfig() *Config {
	if cachedConfig == nil {
		cachedConfig = loadConfig()
	}
	return cachedConfig
}

func loadConfig() *Config {
	config := newDefaultConfig()
	loadConfigFromJson(config)
	validateRequiredFields(config)
	return config
}

func newDefaultConfig() *Config {
	return &Config{
		ArtifactsDirectory: filepath.Join("..", "results"),
		UseExistingOrg: false,
		UseExistingSpace: false,
	}
}

func validateRequiredFields(config *Config) {
	if config.SuiteName == "" {
		panic("missing configuration 'suite_name'")
	}

	if config.ApiEndpoint == "" {
		panic("missing configuration 'api'")
	}

	if config.AppsDomain == "" {
		panic("missing configuration 'apps_domain'")
	}

	if config.User == "" {
		panic("missing configuration 'user'")
	}

	if config.Password == "" {
		panic("missing configuration 'password'")
	}

	if config.Org == "" {
		panic("missing configuration 'org'")
	}

	if config.Space == "" {
		panic("missing configuration 'space'")
	}
}

// Loads the config from json into the supplied config object
func loadConfigFromJson(config *Config) {
	path := configPath()

	configFile, err := os.Open(path)
	if err != nil {
		panic(err)
	}

	decoder := json.NewDecoder(configFile)
	err = decoder.Decode(config)
	if err != nil {
		panic(err)
	}
}

func configPath() string {
	path := os.Getenv("CONFIG")
	if path == "" {
		panic("Must set $CONFIG to point to an integration config .json file.")
	}

	return path
}
<|endoftext|>


<commit_before>package smtpapi

import (
	"encoding/json"
	"reflect"
	"testing"
)

var testEmail = "email@email.com"
var category = "category"

func TestNewSMTPIAPIHeader(t *testing.T) {
	headers := NewSMTPAPIHeader()
	if headers == nil {
		t.Error("NewSMTPAPIHeader() should never return nil")
	}
}

func TestAddTo(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddTo(testEmail)
	if len(headers.To) == 0 {
		t.Errorf("AddTo Failed - %v", headers.To)
	}
}

func TestAddTos(t *testing.T) {
	headers := NewSMTPAPIHeader()
	tos := []string{testEmail, testEmail}
	headers.AddTos(tos)
	if len(headers.To) == 0 {
		t.Errorf("AddTos Failed - %v", headers.To)
	}
}

func TestSetTos(t *testing.T) {
	headers := NewSMTPAPIHeader()
	tos := []string{testEmail, testEmail}
	headers.SetTos(tos)
	if len(headers.To) == 0 {
		t.Errorf("SetTos Failed - %v", headers.To)
	}
}

func TestAddSubstitution(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSubstitution("sub", "val")
	if len(headers.Sub) == 0 {
		t.Errorf("AddSubstitution Failed - %v", headers.Sub)
	}
}

func TestAddSubstitutions(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSubstitutions("sub", []string{"val", "val2"})
	if len(headers.Sub) == 0 && len(headers.Sub["sub"]) != 2 {
		t.Errorf("AddSubstitutions Failed - %v", headers.Sub)
	}
}

func TestSetSubstitutions(t *testing.T) {
	headers := NewSMTPAPIHeader()
	sub := make(map[string][]string)
	sub["sub"] = []string{"val", "val2"}
	headers.SetSubstitutions(sub)
	if len(headers.Sub) == 0 && len(headers.Sub["sub"]) != 2 {
		t.Errorf("SetSubstitutions Failed - %v", headers.Sub)
	}
}

func TestAddSection(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSection("section", "value")
	if len(headers.Section) == 0 {
		t.Errorf("AddSection Failed - %v", headers.Section)
	}
}

func TestSetSections(t *testing.T) {
	headers := NewSMTPAPIHeader()
	section := make(map[string]string)
	section["section"] = "val"
	headers.SetSections(section)
	if len(headers.Section) == 0 {
		t.Errorf("SetSections Failed - %v", headers.Section)
	}
}

func TestAddCategory(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddCategory(category)
	if len(headers.Category) == 0 {
		t.Errorf("AddCategory Failed - %v", headers.Category)
	}
}

func TestAddCategories(t *testing.T) {
	headers := NewSMTPAPIHeader()
	categories := []string{category, category}
	headers.AddCategories(categories)
	if len(headers.Category) == 0 {
		t.Errorf("AddCategories Failed - %v", headers.Category)
	}
}

func TestSetCategories(t *testing.T) {
	headers := NewSMTPAPIHeader()
	categories := []string{category, category}
	headers.SetCategories(categories)
	if len(headers.Category) == 0 {
		t.Errorf("SetCategories Failed - %v", headers.Category)
	}
}

func TestAddUniqueArgs(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddUniqueArg("arg", "value")
	if len(headers.Unique_args) == 0 {
		t.Errorf("AddUniqueArg Failed - %v", headers.Unique_args)
	}
}

func TestSetUniqueArgs(t *testing.T) {
	headers := NewSMTPAPIHeader()
	args := make(map[string]string)
	args["arg"] = "val"
	headers.SetUniqueArgs(args)
	if len(headers.Unique_args) == 0 {
		t.Errorf("SetUniqueArgs Failed - %v", headers.Unique_args)
	}
}

func Test_Adds(t *testing.T) {
	validHeader, _ := json.Marshal([]byte(`{"to":["test@email.com"],"sub":{"subKey":["subValue"]},"section":{"testSection":"sectionValue"},"category":["testCategory"],"unique_args":{"testUnique":"uniqueValue"},"filters":{"testFilter":{"settings":{"filter":"filterValue"}}}}`))
	headers := NewSMTPAPIHeader()
	headers.AddTo("test@email.com")
	headers.AddSubstitution("subKey", "subValue")
	headers.AddSection("testSection", "sectionValue")
	headers.AddCategory("testCategory")
	headers.AddUniqueArg("testUnique", "uniqueValue")
	headers.AddFilter("testFilter", "filter", "filterValue")
	if h, e := headers.JsonString(); e != nil {
		t.Errorf("Error! %s", e)
	} else {
		testHeader, _ := json.Marshal([]byte(h))
		if reflect.DeepEqual(testHeader, validHeader) {
			t.Logf("Success")
		} else {
			t.Errorf("Invalid headers")
		}
	}
}

func Test_Sets(t *testing.T) {
	validHeader, _ := json.Marshal([]byte(`{"to":["test@email.com"],"sub":{"subKey":["subValue"]},"section":{"testSection":"sectionValue"},"category":["testCategory"],"unique_args":{"testUnique":"uniqueValue"},"filters":{"testFilter":{"settings":{"filter":"filterValue"}}}}`))
	headers := NewSMTPAPIHeader()
	headers.SetTos([]string{"test@email.com"})
	sub := make(map[string][]string)
	sub["subKey"] = []string{"subValue"}
	headers.SetSubstitutions(sub)
	sections := make(map[string]string)
	sections["testSection"] = "sectionValue"
	headers.SetSections(sections)
	headers.SetCategories([]string{"testCategory"})
	unique := make(map[string]string)
	unique["testUnique"] = "uniqueValue"
	headers.SetUniqueArgs(unique)
	headers.AddFilter("testFilter", "filter", "filterValue")
	if h, e := headers.JsonString(); e != nil {
		t.Errorf("Error! %s", e)
	} else {
		testHeader, _ := json.Marshal([]byte(h))
		if reflect.DeepEqual(testHeader, validHeader) {
			t.Logf("Success")
		} else {
			t.Errorf("Invalid headers")
		}
	}
}
<commit_msg>Added Tests for Filters<commit_after>package smtpapi

import (
	"encoding/json"
	"reflect"
	"testing"
)

var testEmail = "email@email.com"
var category = "category"

func TestNewSMTPIAPIHeader(t *testing.T) {
	headers := NewSMTPAPIHeader()
	if headers == nil {
		t.Error("NewSMTPAPIHeader() should never return nil")
	}
}

func TestAddTo(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddTo(testEmail)
	if len(headers.To) == 0 {
		t.Errorf("AddTo Failed - %v", headers.To)
	}
}

func TestAddTos(t *testing.T) {
	headers := NewSMTPAPIHeader()
	tos := []string{testEmail, testEmail}
	headers.AddTos(tos)
	if len(headers.To) == 0 {
		t.Errorf("AddTos Failed - %v", headers.To)
	}
}

func TestSetTos(t *testing.T) {
	headers := NewSMTPAPIHeader()
	tos := []string{testEmail, testEmail}
	headers.SetTos(tos)
	if len(headers.To) == 0 {
		t.Errorf("SetTos Failed - %v", headers.To)
	}
}

func TestAddSubstitution(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSubstitution("sub", "val")
	if len(headers.Sub) == 0 {
		t.Errorf("AddSubstitution Failed - %v", headers.Sub)
	}
}

func TestAddSubstitutions(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSubstitutions("sub", []string{"val", "val2"})
	if len(headers.Sub) == 0 && len(headers.Sub["sub"]) != 2 {
		t.Errorf("AddSubstitutions Failed - %v", headers.Sub)
	}
}

func TestSetSubstitutions(t *testing.T) {
	headers := NewSMTPAPIHeader()
	sub := make(map[string][]string)
	sub["sub"] = []string{"val", "val2"}
	headers.SetSubstitutions(sub)
	if len(headers.Sub) == 0 && len(headers.Sub["sub"]) != 2 {
		t.Errorf("SetSubstitutions Failed - %v", headers.Sub)
	}
}

func TestAddSection(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddSection("section", "value")
	if len(headers.Section) == 0 {
		t.Errorf("AddSection Failed - %v", headers.Section)
	}
}

func TestSetSections(t *testing.T) {
	headers := NewSMTPAPIHeader()
	section := make(map[string]string)
	section["section"] = "val"
	headers.SetSections(section)
	if len(headers.Section) == 0 {
		t.Errorf("SetSections Failed - %v", headers.Section)
	}
}

func TestAddCategory(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddCategory(category)
	if len(headers.Category) == 0 {
		t.Errorf("AddCategory Failed - %v", headers.Category)
	}
}

func TestAddCategories(t *testing.T) {
	headers := NewSMTPAPIHeader()
	categories := []string{category, category}
	headers.AddCategories(categories)
	if len(headers.Category) == 0 {
		t.Errorf("AddCategories Failed - %v", headers.Category)
	}
}

func TestSetCategories(t *testing.T) {
	headers := NewSMTPAPIHeader()
	categories := []string{category, category}
	headers.SetCategories(categories)
	if len(headers.Category) == 0 {
		t.Errorf("SetCategories Failed - %v", headers.Category)
	}
}

func TestAddUniqueArgs(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddUniqueArg("arg", "value")
	if len(headers.UniqueArgs) == 0 {
		t.Errorf("AddUniqueArg Failed - %v", headers.UniqueArgs)
	}
}

func TestSetUniqueArgs(t *testing.T) {
	headers := NewSMTPAPIHeader()
	args := make(map[string]string)
	args["arg"] = "val"
	headers.SetUniqueArgs(args)
	if len(headers.UniqueArgs) == 0 {
		t.Errorf("SetUniqueArgs Failed - %v", headers.UniqueArgs)
	}
}

func TestAddFilter(t *testing.T) {
	headers := NewSMTPAPIHeader()
	headers.AddFilter("filter", "setting", "value")
	if len(headers.Filters) == 0 {
		t.Errorf("AddFilter Failed - %v", headers.Filters)
	}
}

func TestSetFilter(t *testing.T) {
	headers := NewSMTPAPIHeader()
	filter := &Filter{
		Settings: make(map[string]string),
	}
	filter.Settings["setting"] = "value"
	headers.SetFilter("filter", filter)
	if len(headers.Filters) == 0 {
		t.Errorf("SetFilter Failed - %v", headers.Filters)
	}
}

func TestJSONStringWithAdds(t *testing.T) {
	validHeader, _ := json.Marshal([]byte(`{"to":["test@email.com"],"sub":{"subKey":["subValue"]},"section":{"testSection":"sectionValue"},"category":["testCategory"],"unique_args":{"testUnique":"uniqueValue"},"filters":{"testFilter":{"settings":{"filter":"filterValue"}}}}`))
	headers := NewSMTPAPIHeader()
	headers.AddTo("test@email.com")
	headers.AddSubstitution("subKey", "subValue")
	headers.AddSection("testSection", "sectionValue")
	headers.AddCategory("testCategory")
	headers.AddUniqueArg("testUnique", "uniqueValue")
	headers.AddFilter("testFilter", "filter", "filterValue")
	if h, e := headers.JSONString(); e != nil {
		t.Errorf("Error! %s", e)
	} else {
		testHeader, _ := json.Marshal([]byte(h))
		if reflect.DeepEqual(testHeader, validHeader) {
			t.Logf("Success")
		} else {
			t.Errorf("Invalid headers")
		}
	}
}

func TestJSONStringWithSets(t *testing.T) {
	validHeader, _ := json.Marshal([]byte(`{"to":["test@email.com"],"sub":{"subKey":["subValue"]},"section":{"testSection":"sectionValue"},"category":["testCategory"],"unique_args":{"testUnique":"uniqueValue"},"filters":{"testFilter":{"settings":{"filter":"filterValue"}}}}`))
	headers := NewSMTPAPIHeader()
	headers.SetTos([]string{"test@email.com"})
	sub := make(map[string][]string)
	sub["subKey"] = []string{"subValue"}
	headers.SetSubstitutions(sub)
	sections := make(map[string]string)
	sections["testSection"] = "sectionValue"
	headers.SetSections(sections)
	headers.SetCategories([]string{"testCategory"})
	unique := make(map[string]string)
	unique["testUnique"] = "uniqueValue"
	headers.SetUniqueArgs(unique)
	headers.AddFilter("testFilter", "filter", "filterValue")
	if h, e := headers.JSONString(); e != nil {
		t.Errorf("Error! %s", e)
	} else {
		testHeader, _ := json.Marshal([]byte(h))
		if reflect.DeepEqual(testHeader, validHeader) {
			t.Logf("Success")
		} else {
			t.Errorf("Invalid headers")
		}
	}
}
<|endoftext|>


<commit_before>package edison

import (
	"errors"
	"fmt"
	"os"
	"strconv"
	"syscall"
)

const (
	// HIGH pin state
	HIGH = 1
	// LOW pin state
	LOW = 0
	// IN input pin mode
	IN = "in"
	// OUT output pin mode
	OUT = "out"
	// GPIOPATH is the path to the sysfs gpio
	GPIOPATH = "/sys/class/gpio"
)

func writeFile(path string, data []byte) (i int, err error) {
	file, err := os.OpenFile(path, os.O_WRONLY, 0644)
	defer file.Close()
	if err != nil {
		return
	}

	return file.Write(data)
}

func readFile(path string) ([]byte, error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0644)
	defer file.Close()
	if err != nil {
		return make([]byte, 0), err
	}

	buf := make([]byte, 200)
	var i = 0
	i, err = file.Read(buf)
	if i == 0 {
		return buf, err
	}
	return buf[:i], err
}

type mux struct {
	pin   int
	value int
}

type pin struct {
	pin   int
	rPin  int
	label string
}

type fsPin struct {
	pin          int
	resistor     int
	levelShifter int
	pwmPin       int
	label        string
	mux          []mux
}

var pwmPins = make(map[int]*pwmPin)
var digitalPins = make(map[int]DigitalPin)

// Pin represents a GPIO pin on the Edison.
type Pin interface {
	Direction(dir string) (err error)
	Export() (err error)
	Unexport() (err error)
}

// DigitalPin abstracts a digital (vs analog) pin.
type DigitalPin interface {
	Pin
	DigitalWrite(int) (err error)
	DigitalRead() (val int, err error)
	PwmWrite(val byte) (err error)
}

var pinMap = map[int]fsPin{
	0: fsPin{
		pin:          130,
		resistor:     216,
		levelShifter: 248,
		pwmPin:       -1,
		mux:          []mux{},
	},
	1: fsPin{
		pin:          131,
		resistor:     217,
		levelShifter: 249,
		pwmPin:       -1,
		mux:          []mux{},
	},
	2: fsPin{
		pin:          128,
		resistor:     218,
		levelShifter: 250,
		pwmPin:       -1,
		mux:          []mux{},
	},
	3: fsPin{
		pin:          12,
		resistor:     219,
		levelShifter: 251,
		pwmPin:       0,
		mux:          []mux{},
	},

	4: fsPin{
		pin:          129,
		resistor:     220,
		levelShifter: 252,
		pwmPin:       -1,
		mux:          []mux{},
	},
	5: fsPin{
		pin:          13,
		resistor:     221,
		levelShifter: 253,
		pwmPin:       1,
		mux:          []mux{},
	},
	6: fsPin{
		pin:          182,
		resistor:     222,
		levelShifter: 254,
		pwmPin:       2,
		mux:          []mux{},
	},
	7: fsPin{
		pin:          48,
		resistor:     223,
		levelShifter: 255,
		pwmPin:       -1,
		mux:          []mux{},
	},
	8: fsPin{
		pin:          49,
		resistor:     224,
		levelShifter: 256,
		pwmPin:       -1,
		mux:          []mux{},
	},
	9: fsPin{
		pin:          183,
		resistor:     225,
		levelShifter: 257,
		pwmPin:       3,
		mux:          []mux{},
	},
	10: fsPin{
		pin:          41,
		resistor:     226,
		levelShifter: 258,
		pwmPin:       4,
		mux: []mux{
			mux{263, HIGH},
			mux{240, LOW},
		},
	},
	11: fsPin{
		pin:          43,
		resistor:     227,
		levelShifter: 259,
		pwmPin:       5,
		mux: []mux{
			mux{262, HIGH},
			mux{241, LOW},
		},
	},
	12: fsPin{
		pin:          42,
		resistor:     228,
		levelShifter: 260,
		pwmPin:       -1,
		mux: []mux{
			mux{242, LOW},
		},
	},
	13: fsPin{
		pin:          40,
		resistor:     229,
		levelShifter: 261,
		pwmPin:       -1,
		mux: []mux{
			mux{243, LOW},
		},
	},
}

func newDigitalRootPin(p int, r int, v ...string) DigitalPin {
	d := &pin{pin: p, rPin: r}
	if len(v) > 0 {
		d.label = v[0]
	} else {
		d.label = "gpio" + strconv.Itoa(d.pin)
	}
	return d
}

func newDigitalPin(p int, v ...string) DigitalPin {
	d := &pin{pin: p}
	if len(v) > 0 {
		d.label = v[0]
	} else {
		d.label = "gpio" + strconv.Itoa(d.pin)
	}
	return d
}

// GetDigitalPin creates a pin object given pin number and output.
// TODO specify what pin number being used here
// TODO move to enum types for direction (rather than using a string)
func GetDigitalPin(p int, dir string) (pin DigitalPin, err error) {
	fpin := pinMap[p]
	if digitalPins[fpin.pin] == nil {
		digitalPins[fpin.pin] = newDigitalRootPin(fpin.pin, p)
		if err = digitalPins[fpin.pin].Export(); err != nil {
			return
		}
		digitalPins[fpin.resistor] = newDigitalPin(fpin.resistor)
		if err = digitalPins[fpin.resistor].Export(); err != nil {
			return
		}
		digitalPins[fpin.levelShifter] = newDigitalPin(fpin.levelShifter)
		if err = digitalPins[fpin.levelShifter].Export(); err != nil {
			return
		}

		if len(fpin.mux) > 0 {
			for _, mux := range fpin.mux {
				digitalPins[mux.pin] = newDigitalPin(mux.pin)
				if err = digitalPins[mux.pin].Export(); err != nil {
					return
				}
				if err = digitalPins[mux.pin].Direction(OUT); err != nil {
					return
				}
				if err = digitalPins[mux.pin].DigitalWrite(mux.value); err != nil {
					return
				}
			}
		}
	}

	if dir == IN {
		if err = digitalPins[fpin.pin].Direction(IN); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].DigitalWrite(LOW); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].DigitalWrite(LOW); err != nil {
			return
		}
	} else if dir == OUT {
		if err = digitalPins[fpin.pin].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].Direction(IN); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].DigitalWrite(HIGH); err != nil {
			return
		}
	}

	pin = digitalPins[fpin.pin]
	return pin, err
}

func (p *pin) DigitalWrite(b int) (err error) {
	str := fmt.Sprintf("%v/%s/value", GPIOPATH, p.label)
	fmt.Printf("Writing value (%d) to pin (%d)\n", b, p.pin)
	_, err = writeFile(str, []byte(strconv.Itoa(b)))
	return err
}

func (p *pin) Export() (err error) {
	fmt.Printf("Exporting pin: %d\n", p.pin)
	if _, err := writeFile(GPIOPATH+"/export", []byte(strconv.Itoa(p.pin))); err != nil {
		// If EBUSY then the pin has already been exported
		if err.(*os.PathError).Err != syscall.EBUSY {
			return err
		}
	}
	return nil
}

func (p *pin) Unexport() (err error) {
	if _, err := writeFile(GPIOPATH+"/unexport", []byte(strconv.Itoa(p.pin))); err != nil {
		// If EINVAL then the pin is reserved in the system and can't be unexported
		if err.(*os.PathError).Err != syscall.EINVAL {
			return err
		}
	}
	return nil
}

func (p *pin) Direction(dir string) (err error) {
	str := fmt.Sprintf("%v/%s/direction", GPIOPATH, p.label)
	fmt.Printf("Setting direction (%s) for pin (%d)\n", dir, p.pin)
	_, err = writeFile(str, []byte(dir))
	return err
}

func writeValue(pin int, val byte) (err error) {
	p, err := GetDigitalPin(pin, "out")
	if err != nil {
		return
	}
	return p.DigitalWrite(int(val))
}

// changePinMode writes pin mode to current_pinmux file
func changePinMode(pin int, mode string) (err error) {
	_, err = writeFile(
		"/sys/kernel/debug/gpio_debug/gpio"+strconv.Itoa(pin)+"/current_pinmux",
		[]byte("mode"+mode),
	)
	return
}

func (p *pin) PwmWrite(val byte) (err error) {
	fpin := pinMap[p.rPin]
	if fpin.pwmPin != -1 {
		if pwmPins[fpin.pwmPin] == nil {
			if err = writeValue(p.rPin, 1); err != nil {
				return
			}
			if err = changePinMode(fpin.pin, "1"); err != nil {
				return
			}
			pwmPins[fpin.pwmPin] = newPwmPin(fpin.pwmPin)
			if err = pwmPins[fpin.pwmPin].export(); err != nil {
				return
			}
			if err = pwmPins[fpin.pwmPin].enable("1"); err != nil {
				return
			}
		}

		periodStr, err := pwmPins[fpin.pwmPin].period()
		if err != nil {
			return err
		}
		period, err := strconv.Atoi(periodStr)
		if err != nil {
			return err
		}
		duty := FromScale(float64(val), 0, 255.0)
		return pwmPins[fpin.pwmPin].writeDuty(strconv.Itoa(int(float64(period) * duty)))
	}
	return errors.New("Not a PWM pin")
}

func (p *pin) DigitalRead() (val int, err error) {
	buf, err := readFile(fmt.Sprintf("%v/%d/value", GPIOPATH, p.pin))
	if err != nil {
		return 0, err
	}
	return strconv.Atoi(string(buf[0]))
}
<commit_msg>Add debugging of all file writes<commit_after>package edison

import (
	"errors"
	"fmt"
	"os"
	"strconv"
	"syscall"
)

const (
	// HIGH pin state
	HIGH = 1
	// LOW pin state
	LOW = 0
	// IN input pin mode
	IN = "in"
	// OUT output pin mode
	OUT = "out"
	// GPIOPATH is the path to the sysfs gpio
	GPIOPATH = "/sys/class/gpio"
)

func writeFile(path string, data []byte) (i int, err error) {
	fmt.Println(">>", path, string(data))
	file, err := os.OpenFile(path, os.O_WRONLY, 0644)
	defer file.Close()
	if err != nil {
		return
	}

	return file.Write(data)
}

func readFile(path string) ([]byte, error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0644)
	defer file.Close()
	if err != nil {
		return make([]byte, 0), err
	}

	buf := make([]byte, 200)
	var i = 0
	i, err = file.Read(buf)
	if i == 0 {
		return buf, err
	}
	return buf[:i], err
}

type mux struct {
	pin   int
	value int
}

type pin struct {
	pin   int
	rPin  int
	label string
}

type fsPin struct {
	pin          int
	resistor     int
	levelShifter int
	pwmPin       int
	label        string
	mux          []mux
}

var pwmPins = make(map[int]*pwmPin)
var digitalPins = make(map[int]DigitalPin)

// Pin represents a GPIO pin on the Edison.
type Pin interface {
	Direction(dir string) (err error)
	Export() (err error)
	Unexport() (err error)
}

// DigitalPin abstracts a digital (vs analog) pin.
type DigitalPin interface {
	Pin
	DigitalWrite(int) (err error)
	DigitalRead() (val int, err error)
	PwmWrite(val byte) (err error)
}

var pinMap = map[int]fsPin{
	0: fsPin{
		pin:          130,
		resistor:     216,
		levelShifter: 248,
		pwmPin:       -1,
		mux:          []mux{},
	},
	1: fsPin{
		pin:          131,
		resistor:     217,
		levelShifter: 249,
		pwmPin:       -1,
		mux:          []mux{},
	},
	2: fsPin{
		pin:          128,
		resistor:     218,
		levelShifter: 250,
		pwmPin:       -1,
		mux:          []mux{},
	},
	3: fsPin{
		pin:          12,
		resistor:     219,
		levelShifter: 251,
		pwmPin:       0,
		mux:          []mux{},
	},

	4: fsPin{
		pin:          129,
		resistor:     220,
		levelShifter: 252,
		pwmPin:       -1,
		mux:          []mux{},
	},
	5: fsPin{
		pin:          13,
		resistor:     221,
		levelShifter: 253,
		pwmPin:       1,
		mux:          []mux{},
	},
	6: fsPin{
		pin:          182,
		resistor:     222,
		levelShifter: 254,
		pwmPin:       2,
		mux:          []mux{},
	},
	7: fsPin{
		pin:          48,
		resistor:     223,
		levelShifter: 255,
		pwmPin:       -1,
		mux:          []mux{},
	},
	8: fsPin{
		pin:          49,
		resistor:     224,
		levelShifter: 256,
		pwmPin:       -1,
		mux:          []mux{},
	},
	9: fsPin{
		pin:          183,
		resistor:     225,
		levelShifter: 257,
		pwmPin:       3,
		mux:          []mux{},
	},
	10: fsPin{
		pin:          41,
		resistor:     226,
		levelShifter: 258,
		pwmPin:       4,
		mux: []mux{
			mux{263, HIGH},
			mux{240, LOW},
		},
	},
	11: fsPin{
		pin:          43,
		resistor:     227,
		levelShifter: 259,
		pwmPin:       5,
		mux: []mux{
			mux{262, HIGH},
			mux{241, LOW},
		},
	},
	12: fsPin{
		pin:          42,
		resistor:     228,
		levelShifter: 260,
		pwmPin:       -1,
		mux: []mux{
			mux{242, LOW},
		},
	},
	13: fsPin{
		pin:          40,
		resistor:     229,
		levelShifter: 261,
		pwmPin:       -1,
		mux: []mux{
			mux{243, LOW},
		},
	},
}

func newDigitalRootPin(p int, r int, v ...string) DigitalPin {
	d := &pin{pin: p, rPin: r}
	if len(v) > 0 {
		d.label = v[0]
	} else {
		d.label = "gpio" + strconv.Itoa(d.pin)
	}
	return d
}

func newDigitalPin(p int, v ...string) DigitalPin {
	d := &pin{pin: p}
	if len(v) > 0 {
		d.label = v[0]
	} else {
		d.label = "gpio" + strconv.Itoa(d.pin)
	}
	return d
}

// GetDigitalPin creates a pin object given pin number and output.
// TODO specify what pin number being used here
// TODO move to enum types for direction (rather than using a string)
func GetDigitalPin(p int, dir string) (pin DigitalPin, err error) {
	fpin := pinMap[p]
	if digitalPins[fpin.pin] == nil {
		digitalPins[fpin.pin] = newDigitalRootPin(fpin.pin, p)
		if err = digitalPins[fpin.pin].Export(); err != nil {
			return
		}
		digitalPins[fpin.resistor] = newDigitalPin(fpin.resistor)
		if err = digitalPins[fpin.resistor].Export(); err != nil {
			return
		}
		digitalPins[fpin.levelShifter] = newDigitalPin(fpin.levelShifter)
		if err = digitalPins[fpin.levelShifter].Export(); err != nil {
			return
		}

		if len(fpin.mux) > 0 {
			for _, mux := range fpin.mux {
				digitalPins[mux.pin] = newDigitalPin(mux.pin)
				if err = digitalPins[mux.pin].Export(); err != nil {
					return
				}
				if err = digitalPins[mux.pin].Direction(OUT); err != nil {
					return
				}
				if err = digitalPins[mux.pin].DigitalWrite(mux.value); err != nil {
					return
				}
			}
		}
	}

	if dir == IN {
		if err = digitalPins[fpin.pin].Direction(IN); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].DigitalWrite(LOW); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].DigitalWrite(LOW); err != nil {
			return
		}
	} else if dir == OUT {
		if err = digitalPins[fpin.pin].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.resistor].Direction(IN); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].Direction(OUT); err != nil {
			return
		}
		if err = digitalPins[fpin.levelShifter].DigitalWrite(HIGH); err != nil {
			return
		}
	}

	pin = digitalPins[fpin.pin]
	return pin, err
}

func (p *pin) DigitalWrite(b int) (err error) {
	str := fmt.Sprintf("%v/%s/value", GPIOPATH, p.label)
	fmt.Printf("Writing value (%d) to pin (%d)\n", b, p.pin)
	_, err = writeFile(str, []byte(strconv.Itoa(b)))
	return err
}

func (p *pin) Export() (err error) {
	fmt.Printf("Exporting pin: %d\n", p.pin)
	if _, err := writeFile(GPIOPATH+"/export", []byte(strconv.Itoa(p.pin))); err != nil {
		// If EBUSY then the pin has already been exported
		if err.(*os.PathError).Err != syscall.EBUSY {
			return err
		}
	}
	return nil
}

func (p *pin) Unexport() (err error) {
	if _, err := writeFile(GPIOPATH+"/unexport", []byte(strconv.Itoa(p.pin))); err != nil {
		// If EINVAL then the pin is reserved in the system and can't be unexported
		if err.(*os.PathError).Err != syscall.EINVAL {
			return err
		}
	}
	return nil
}

func (p *pin) Direction(dir string) (err error) {
	str := fmt.Sprintf("%v/%s/direction", GPIOPATH, p.label)
	fmt.Printf("Setting direction (%s) for pin (%d)\n", dir, p.pin)
	_, err = writeFile(str, []byte(dir))
	return err
}

func writeValue(pin int, val byte) (err error) {
	p, err := GetDigitalPin(pin, "out")
	if err != nil {
		return
	}
	return p.DigitalWrite(int(val))
}

// changePinMode writes pin mode to current_pinmux file
func changePinMode(pin int, mode string) (err error) {
	_, err = writeFile(
		"/sys/kernel/debug/gpio_debug/gpio"+strconv.Itoa(pin)+"/current_pinmux",
		[]byte("mode"+mode),
	)
	return
}

func (p *pin) PwmWrite(val byte) (err error) {
	fpin := pinMap[p.rPin]
	if fpin.pwmPin != -1 {
		if pwmPins[fpin.pwmPin] == nil {
			if err = writeValue(p.rPin, 1); err != nil {
				return
			}
			if err = changePinMode(fpin.pin, "1"); err != nil {
				return
			}
			pwmPins[fpin.pwmPin] = newPwmPin(fpin.pwmPin)
			if err = pwmPins[fpin.pwmPin].export(); err != nil {
				return
			}
			if err = pwmPins[fpin.pwmPin].enable("1"); err != nil {
				return
			}
		}

		periodStr, err := pwmPins[fpin.pwmPin].period()
		if err != nil {
			return err
		}
		period, err := strconv.Atoi(periodStr)
		if err != nil {
			return err
		}
		duty := FromScale(float64(val), 0, 255.0)
		return pwmPins[fpin.pwmPin].writeDuty(strconv.Itoa(int(float64(period) * duty)))
	}
	return errors.New("Not a PWM pin")
}

func (p *pin) DigitalRead() (val int, err error) {
	buf, err := readFile(fmt.Sprintf("%v/%d/value", GPIOPATH, p.pin))
	if err != nil {
		return 0, err
	}
	return strconv.Atoi(string(buf[0]))
}
<|endoftext|>


<commit_before>package pmc

import (
	"errors"
	"math"
	"strconv"

	"code.google.com/p/gofarmhash"

	"github.com/lukut/bitmaps"
)

/*
Sketch ...
*/
type Sketch struct {
	l      float64
	m      float64
	w      float64
	bitmap bitmaps.Bitmap
}

/*
New returns a PMC Sketch with the properties:
l = total number of bits for sketch
m = total number of rows for each flow
w = total number of columns for each flow
*/
func New(l uint, m uint, w uint) (*Sketch, error) {
	if l == 0 {
		return nil, errors.New("Expected l > 0, got 0")
	}
	if m == 0 {
		return nil, errors.New("Expected m > 0, got 0")
	}
	if w == 0 {
		return nil, errors.New("Expected w > 0, got 0")
	}
	return &Sketch{float64(l), float64(m), float64(w), make(bitmaps.Bitmap, l/8)}, nil
}

/*
NewForMaxFlows returns a PMC Sketch adapted to the size of the max number of
flows expected.
*/
func NewForMaxFlows(maxFlows uint) (*Sketch, error) {
	l := maxFlows * 32
	return New(l, 256, 32)
}

/*
It is straightforward to use any uniformly distributed hash function with
sufficiently random output in the role of H: the input parameters can
simply be concatenated to a single bit string.
*/
func (sketch *Sketch) getPos(f []byte, i, j uint) uint {
	s := strconv.Itoa(int(i)) + string(f) + strconv.Itoa(int(j))
	hash := farmhash.Hash64([]byte(s))
	return uint(hash) % uint(sketch.l)
}

/*
Increment the count of the flow by 1
*/
func (sketch *Sketch) Increment(flow []byte) {
	i := rand(uint(sketch.m))
	j := georand(uint(sketch.w))
	pos := sketch.getPos(flow, i, j)
	sketch.bitmap.Set(pos, true)
}

func (sketch *Sketch) getZSum(flow []byte) uint {
	z := 0.0
	for i := 0.0; i < sketch.m; i++ {
		j := 0.0
		for j < sketch.w {
			pos := sketch.getPos(flow, uint(i), uint(j))
			if sketch.bitmap.Get(pos) == false {
				break
			}
			j++
		}
		z += j
	}
	return uint(z)
}

func (sketch *Sketch) getEmptyRows(flow []byte) uint {
	k := uint(0)
	for i := 0.0; i < sketch.m; i++ {
		pos := sketch.getPos(flow, uint(i), 0)
		if sketch.bitmap.Get(pos) == false {
			k++
		}
	}
	return k
}

func (sketch *Sketch) getP() float64 {
	ones := float64(0)
	for i := uint(0); i < uint(sketch.bitmap.Size()); i++ {
		if sketch.bitmap.Get(i) == true {
			ones++
		}
	}
	return ones / float64(sketch.l)
}

/*
GetEstimate returns the estimated count of a given flow
*/
func (sketch *Sketch) GetEstimate(flow []byte) uint {
	m := sketch.m
	p := sketch.getP()
	k := float64(sketch.getEmptyRows(flow))
	// Use const due to quick conversion against 0.78 (n = 1000000.0)
	//n := -2 * m * math.Log((k)/(m*(1-p)))
	n := 100000.0

	// Dealing with small multiplicities
	if k/(1-p) > 0.3*m {
		return uint(-2 * m * math.Log(k/(m*(1-p))))
	}

	qk := func(k, n, p float64) float64 {
		result := 1.0
		for i := 1.0; i <= k; i++ {
			result *= (1.0 - math.Pow(1.0-math.Pow(2, -i), n)*(1.0-p))
		}
		return result
	}

	E := func(n, p float64) float64 {
		result := float64(0)
		for k := 1.0; k <= sketch.w; k++ {
			result += (k * (qk(k, n, p) - qk(k+1, n, p)))
		}
		return result
	}
	rho := func(p float64) float64 {
		return math.Pow(2, E(n, p)) / n
	}

	z := float64(sketch.getZSum(flow))
	return uint(m * math.Pow(2, z/m) / rho(p))
}
<commit_msg>Update comments<commit_after>package pmc

import (
	"errors"
	"math"
	"strconv"

	"code.google.com/p/gofarmhash"

	"github.com/lukut/bitmaps"
)

/*
Sketch is a Probabilistic Multiplicity Counting Sketch, a novel data structure
that is capable of accounting traffic per flow probabilistically, that can be
used as an alternative to Count-min sketch.
*/
type Sketch struct {
	l      float64
	m      float64
	w      float64
	bitmap bitmaps.Bitmap // FIXME: Get Rid of bitmap and use uint32 array
}

/*
New returns a PMC Sketch with the properties:
l = total number of bits for sketch
m = total number of rows for each flow
w = total number of columns for each flow
*/
func New(l uint, m uint, w uint) (*Sketch, error) {
	if l == 0 {
		return nil, errors.New("Expected l > 0, got 0")
	}
	if m == 0 {
		return nil, errors.New("Expected m > 0, got 0")
	}
	if w == 0 {
		return nil, errors.New("Expected w > 0, got 0")
	}
	return &Sketch{float64(l), float64(m), float64(w), make(bitmaps.Bitmap, l/8)}, nil
}

/*
NewForMaxFlows returns a PMC Sketch adapted to the size of the max number of
flows expected.
*/
func NewForMaxFlows(maxFlows uint) (*Sketch, error) {
	l := maxFlows * 32
	return New(l, 256, 32)
}

/*
It is straightforward to use any uniformly distributed hash function with
sufficiently random output in the role of H: the input parameters can
simply be concatenated to a single bit string.
*/
func (sketch *Sketch) getPos(f []byte, i, j uint) uint {
	s := strconv.Itoa(int(i)) + string(f) + strconv.Itoa(int(j))
	hash := farmhash.Hash64([]byte(s))
	return uint(hash) % uint(sketch.l)
}

/*
Increment the count of the flow by 1
*/
func (sketch *Sketch) Increment(flow []byte) {
	i := rand(uint(sketch.m))
	j := georand(uint(sketch.w))
	pos := sketch.getPos(flow, i, j)
	sketch.bitmap.Set(pos, true)
}

func (sketch *Sketch) getZSum(flow []byte) uint {
	z := 0.0
	for i := 0.0; i < sketch.m; i++ {
		j := 0.0
		for j < sketch.w {
			pos := sketch.getPos(flow, uint(i), uint(j))
			if sketch.bitmap.Get(pos) == false {
				break
			}
			j++
		}
		z += j
	}
	return uint(z)
}

func (sketch *Sketch) getEmptyRows(flow []byte) uint {
	k := uint(0)
	for i := 0.0; i < sketch.m; i++ {
		pos := sketch.getPos(flow, uint(i), 0)
		if sketch.bitmap.Get(pos) == false {
			k++
		}
	}
	return k
}

func (sketch *Sketch) getP() float64 {
	ones := float64(0)
	for i := uint(0); i < uint(sketch.bitmap.Size()); i++ {
		if sketch.bitmap.Get(i) == true {
			ones++
		}
	}
	return ones / float64(sketch.l)
}

/*
GetEstimate returns the estimated count of a given flow
*/
func (sketch *Sketch) GetEstimate(flow []byte) uint {
	m := sketch.m
	p := sketch.getP()
	k := float64(sketch.getEmptyRows(flow))
	// Use const due to quick conversion against 0.78 (n = 1000000.0)
	// n := -2 * m * math.Log((k)/(m*(1-p)))
	n := 100000.0

	// Dealing with small multiplicities
	if k/(1-p) > 0.3*m {
		return uint(-2 * m * math.Log(k/(m*(1-p))))
	}

	// FIXME: Move out of function
	qk := func(k, n, p float64) float64 {
		result := 1.0
		for i := 1.0; i <= k; i++ {
			result *= (1.0 - math.Pow(1.0-math.Pow(2, -i), n)*(1.0-p))
		}
		return result
	}

	// FIXME: Move out of function
	E := func(n, p float64) float64 {
		result := float64(0)
		for k := 1.0; k <= sketch.w; k++ {
			result += (k * (qk(k, n, p) - qk(k+1, n, p)))
		}
		return result
	}

	// FIXME: Move out of function
	rho := func(p float64) float64 {
		return math.Pow(2, E(n, p)) / n
	}

	z := float64(sketch.getZSum(flow))
	return uint(m * math.Pow(2, z/m) / rho(p))
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2014 PPCD developers.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"time"

	"github.com/conformal/btclog"
	"github.com/mably/btcwire"
)

// TxOffsetUnknown is the value returned for a transaction offset that is unknown.
// This is typically because the transaction has not been inserted into a block
// yet.
const TxOffsetUnknown = uint32(0)

// Offset returns the saved offset of the transaction within a block.  This value
// will be TxOffsetUnknown if it hasn't already explicitly been set.
func (t *Tx) Offset() uint32 {
	return t.txOffset
}

// SetOffset sets the offset of the transaction in within a block.
func (t *Tx) SetOffset(offset uint32) {
	t.txOffset = offset
}

func (b *Block) Meta() *btcwire.Meta {
	if b.meta != nil {
		return b.meta
	}
	b.meta = new(btcwire.Meta)
	return b.meta
}

func NewBlockFromBytesWithMeta(serializedBlock []byte) (*Block, error) {
	br := bytes.NewReader(serializedBlock)
	var meta btcwire.Meta
	err := meta.Deserialize(br)
	if err != nil {
		return nil, err
	}
	var msgBlock btcwire.MsgBlock
	err = msgBlock.Deserialize(br)
	if err != nil {
		return nil, err
	}

	b := Block{
		msgBlock:    &msgBlock,
		blockHeight: BlockHeightUnknown,
		meta:        &meta,
	}
	// TODO(kac-) no cache
	//b.serializedBlock = serializedBlock
	return &b, nil
}

func (b *Block) BytesWithMeta() ([]byte, error) {
	// Return the cached serialized bytes if it has already been generated.
	/*if false & len(b.serializedBlock) != 0 {
		return b.serializedBlock, nil
	}*/
	var w bytes.Buffer

	// Serialize Meta.
	err := b.Meta().Serialize(&w)
	if err != nil {
		return nil, err
	}

	// Serialize the MsgBlock.
	err = b.msgBlock.Serialize(&w)
	if err != nil {
		return nil, err
	}

	serializedBlockWithMeta := w.Bytes()

	// TODO(kac-) no cache
	// Cache the serialized bytes and return them.
	//b.serializedBlock = serializedBlock

	return serializedBlockWithMeta, nil
}

// NewBlock returns a new instance of a bitcoin block given an underlying
// btcwire.MsgBlock.  See Block.
func NewBlockWithMetas(msgBlock *btcwire.MsgBlock, meta *btcwire.Meta) *Block {
	return &Block{
		msgBlock:    msgBlock,
		blockHeight: BlockHeightUnknown,
		meta:        meta,
	}
}

// https://github.com/ppcoin/ppcoin/blob/v0.4.0ppc/src/main.h#L962
// ppc: two types of block: proof-of-work or proof-of-stake
func (block *Block) IsProofOfStake() bool {
	return block.msgBlock.IsProofOfStake()
}

func Now() time.Time {
	return time.Now()
}

func TimeTrack(log btclog.Logger, start time.Time, name string) {
	elapsed := time.Since(start)
	log.Tracef("%s took %s", name, elapsed)
}

func Slice(args ...interface{}) []interface{} {
	return args
}
<commit_msg>ppc: KernelStakeModifierUnknown constant defined, block not used for minting yet<commit_after>// Copyright (c) 2014-2014 PPCD developers.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcutil

import (
	"bytes"
	"time"

	"github.com/conformal/btclog"
	"github.com/mably/btcwire"
)

// TxOffsetUnknown is the value returned for a transaction offset that is unknown.
// This is typically because the transaction has not been inserted into a block
// yet.
const TxOffsetUnknown = uint32(0)

// KernelStakeModifierUnknown is the value returned for a block kernel stake
// modifier that is unknown.
// This is typically because the block has not been used for minting yet.
const KernelStakeModifierUnknown = uint64(0)

// Offset returns the saved offset of the transaction within a block.  This value
// will be TxOffsetUnknown if it hasn't already explicitly been set.
func (t *Tx) Offset() uint32 {
	return t.txOffset
}

// SetOffset sets the offset of the transaction in within a block.
func (t *Tx) SetOffset(offset uint32) {
	t.txOffset = offset
}

func (b *Block) Meta() *btcwire.Meta {
	if b.meta != nil {
		return b.meta
	}
	b.meta = new(btcwire.Meta)
	return b.meta
}

func NewBlockFromBytesWithMeta(serializedBlock []byte) (*Block, error) {
	br := bytes.NewReader(serializedBlock)
	var meta btcwire.Meta
	err := meta.Deserialize(br)
	if err != nil {
		return nil, err
	}
	var msgBlock btcwire.MsgBlock
	err = msgBlock.Deserialize(br)
	if err != nil {
		return nil, err
	}

	b := Block{
		msgBlock:    &msgBlock,
		blockHeight: BlockHeightUnknown,
		meta:        &meta,
	}
	// TODO(kac-) no cache
	//b.serializedBlock = serializedBlock
	return &b, nil
}

func (b *Block) BytesWithMeta() ([]byte, error) {
	// Return the cached serialized bytes if it has already been generated.
	/*if false & len(b.serializedBlock) != 0 {
		return b.serializedBlock, nil
	}*/
	var w bytes.Buffer

	// Serialize Meta.
	err := b.Meta().Serialize(&w)
	if err != nil {
		return nil, err
	}

	// Serialize the MsgBlock.
	err = b.msgBlock.Serialize(&w)
	if err != nil {
		return nil, err
	}

	serializedBlockWithMeta := w.Bytes()

	// TODO(kac-) no cache
	// Cache the serialized bytes and return them.
	//b.serializedBlock = serializedBlock

	return serializedBlockWithMeta, nil
}

// NewBlock returns a new instance of a bitcoin block given an underlying
// btcwire.MsgBlock.  See Block.
func NewBlockWithMetas(msgBlock *btcwire.MsgBlock, meta *btcwire.Meta) *Block {
	return &Block{
		msgBlock:    msgBlock,
		blockHeight: BlockHeightUnknown,
		meta:        meta,
	}
}

// https://github.com/ppcoin/ppcoin/blob/v0.4.0ppc/src/main.h#L962
// ppc: two types of block: proof-of-work or proof-of-stake
func (block *Block) IsProofOfStake() bool {
	return block.msgBlock.IsProofOfStake()
}

func Now() time.Time {
	return time.Now()
}

func TimeTrack(log btclog.Logger, start time.Time, name string) {
	elapsed := time.Since(start)
	log.Tracef("%s took %s", name, elapsed)
}

func Slice(args ...interface{}) []interface{} {
	return args
}
<|endoftext|>