<commit_before>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 go_kafka_client

import (
	"errors"
	"time"
)

type ProducerConfig struct {
	Clientid              string
	BrokerList            []string
	SendBufferSize        int
	CompressionCodec      string
	FlushByteCount        int
	FlushTimeout          time.Duration
	BatchSize             int
	MaxMessageBytes       int
	MaxMessagesPerRequest int
	Acks                  int
	RetryBackoff          time.Duration
	Timeout               time.Duration

	//Retries            int //TODO ??
}

func DefaultProducerConfig() *ProducerConfig {
	return &ProducerConfig{
		Clientid:        "mirrormaker",
		MaxMessageBytes: 1000000,
		Acks:            -1,
		RetryBackoff:    250 * time.Millisecond,
	}
}

func ProducerConfigFromFile(filename string) (*ProducerConfig, error) {
	p, err := LoadConfiguration(filename)
	if err != nil {
		return nil, err
	}

	config := DefaultProducerConfig()
	setStringConfig(&config.Clientid, p["client.id"])
	setStringSliceConfig(&config.BrokerList, p["metadata.broker.list"], ",")
	if err := setIntConfig(&config.SendBufferSize, p["send.buffer.size"]); err != nil {
		return nil, err
	}
	setStringConfig(&config.CompressionCodec, p["compression.codec"])
	if err := setIntConfig(&config.FlushByteCount, p["flush.byte.count"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.FlushTimeout, p["flush.timeout"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.BatchSize, p["batch.size"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.MaxMessageBytes, p["max.message.bytes"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.MaxMessagesPerRequest, p["max.messages.per.request"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.Acks, p["acks"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.RetryBackoff, p["retry.backoff"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.Timeout, p["timeout"]); err != nil {
		return nil, err
	}

	return config, nil
}

func (this *ProducerConfig) Validate() error {
	if len(this.BrokerList) == 0 {
		return errors.New("Broker list cannot be empty")
	}

	return nil
}
<commit_msg>one more last fix<commit_after>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 go_kafka_client

import (
	"errors"
	"time"
)

type ProducerConfig struct {
	Clientid              string
	BrokerList            []string
	SendBufferSize        int
	CompressionCodec      string
	FlushByteCount        int
	FlushTimeout          time.Duration
	BatchSize             int
	MaxMessageBytes       int
	MaxMessagesPerRequest int
	Acks                  int
	RetryBackoff          time.Duration
	Timeout               time.Duration

	//Retries            int //TODO ??
}

func DefaultProducerConfig() *ProducerConfig {
	return &ProducerConfig{
		Clientid:        "mirrormaker",
		MaxMessageBytes: 1000000,
		Acks:            1,
		RetryBackoff:    250 * time.Millisecond,
	}
}

func ProducerConfigFromFile(filename string) (*ProducerConfig, error) {
	p, err := LoadConfiguration(filename)
	if err != nil {
		return nil, err
	}

	config := DefaultProducerConfig()
	setStringConfig(&config.Clientid, p["client.id"])
	setStringSliceConfig(&config.BrokerList, p["metadata.broker.list"], ",")
	if err := setIntConfig(&config.SendBufferSize, p["send.buffer.size"]); err != nil {
		return nil, err
	}
	setStringConfig(&config.CompressionCodec, p["compression.codec"])
	if err := setIntConfig(&config.FlushByteCount, p["flush.byte.count"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.FlushTimeout, p["flush.timeout"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.BatchSize, p["batch.size"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.MaxMessageBytes, p["max.message.bytes"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.MaxMessagesPerRequest, p["max.messages.per.request"]); err != nil {
		return nil, err
	}
	if err := setIntConfig(&config.Acks, p["acks"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.RetryBackoff, p["retry.backoff"]); err != nil {
		return nil, err
	}
	if err := setDurationConfig(&config.Timeout, p["timeout"]); err != nil {
		return nil, err
	}

	return config, nil
}

func (this *ProducerConfig) Validate() error {
	if len(this.BrokerList) == 0 {
		return errors.New("Broker list cannot be empty")
	}

	return nil
}
<|endoftext|>


<commit_before>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.22.5 Aluminium 2018-04-26"
<commit_msg>Bump version: v0.23.0 Berkelium 2018-04-27<commit_after>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.23.0 Berkelium 2018-04-27"
<|endoftext|>


<commit_before>// +build pro ent

package command

import (
	"strings"
	"testing"

	"github.com/mitchellh/cli"
	"github.com/stretchr/testify/assert"
)

func TestNamespaceApplyCommand_Implements(t *testing.T) {
	t.Parallel()
	var _ cli.Command = &NamespaceApplyCommand{}
}

func TestNamespaceApplyCommand_Fails(t *testing.T) {
	t.Parallel()
	ui := new(cli.MockUi)
	cmd := &NamespaceApplyCommand{Meta: Meta{Ui: ui}}

	// Fails on misuse
	if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
		t.Fatalf("expected exit code 1, got: %d", code)
	}
	if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) {
		t.Fatalf("expected help output, got: %s", out)
	}
	ui.ErrorWriter.Reset()

	if code := cmd.Run([]string{"-address=nope"}); code != 1 {
		t.Fatalf("expected exit code 1, got: %d", code)
	}
	if out := ui.ErrorWriter.String(); !strings.Contains(out, "name required") {
		t.Fatalf("name required error, got: %s", out)
	}
	ui.ErrorWriter.Reset()
}

func TestNamespaceApplyCommand_Good(t *testing.T) {
	t.Parallel()

	// Create a server
	srv, client, url := testServer(t, true, nil)
	defer srv.Shutdown()

	ui := new(cli.MockUi)
	cmd := &NamespaceApplyCommand{Meta: Meta{Ui: ui}}

	// Create a namespace
	name, desc := "foo", "bar"
	if code := cmd.Run([]string{"-address=" + url, "-description=" + desc, name}); code != 0 {
		t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String())
	}

	namespaces, _, err := client.Namespaces().List(nil)
	assert.Nil(t, err)
	assert.Len(t, namespaces, 2)
}
<commit_msg>fix test<commit_after>// +build pro ent

package command

import (
	"strings"
	"testing"

	"github.com/mitchellh/cli"
	"github.com/stretchr/testify/assert"
)

func TestNamespaceApplyCommand_Implements(t *testing.T) {
	t.Parallel()
	var _ cli.Command = &NamespaceApplyCommand{}
}

func TestNamespaceApplyCommand_Fails(t *testing.T) {
	t.Parallel()
	ui := new(cli.MockUi)
	cmd := &NamespaceApplyCommand{Meta: Meta{Ui: ui}}

	// Fails on misuse
	if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
		t.Fatalf("expected exit code 1, got: %d", code)
	}
	if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) {
		t.Fatalf("expected help output, got: %s", out)
	}
	ui.ErrorWriter.Reset()

	if code := cmd.Run([]string{"-address=nope"}); code != 1 {
		t.Fatalf("expected exit code 1, got: %d", code)
	}
	if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) {
		t.Fatalf("name required error, got: %s", out)
	}
	ui.ErrorWriter.Reset()
}

func TestNamespaceApplyCommand_Good(t *testing.T) {
	t.Parallel()

	// Create a server
	srv, client, url := testServer(t, true, nil)
	defer srv.Shutdown()

	ui := new(cli.MockUi)
	cmd := &NamespaceApplyCommand{Meta: Meta{Ui: ui}}

	// Create a namespace
	name, desc := "foo", "bar"
	if code := cmd.Run([]string{"-address=" + url, "-description=" + desc, name}); code != 0 {
		t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String())
	}

	namespaces, _, err := client.Namespaces().List(nil)
	assert.Nil(t, err)
	assert.Len(t, namespaces, 2)
}
<|endoftext|>


<commit_before>package meli

import (
	"context"
	"io/ioutil"
	"strings"
	"testing"
)

func TestPullDockerImage(t *testing.T) {
	tt := []struct {
		dc          *DockerContainer
		expectedErr error
	}{
		{&DockerContainer{ComposeService: ComposeService{Image: "busybox"}, LogMedium: ioutil.Discard}, nil},
	}
	var ctx = context.Background()
	cli := &mockDockerClient{}
	for _, v := range tt {
		err := PullDockerImage(ctx, cli, v.dc)
		if err != nil {
			t.Errorf("\nCalled PullDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, err, v.expectedErr)
		}
	}
}

func TestBuildDockerImage(t *testing.T) {
	tt := []struct {
		dc          *DockerContainer
		expected    string
		expectedErr error
	}{
		{
			&DockerContainer{
				ServiceName:       "myservicename",
				DockerComposeFile: "docker-compose.yml",
				ComposeService: ComposeService{
					Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
				LogMedium: ioutil.Discard},
			"meli_myservicename",
			nil},
		{
			&DockerContainer{
				ServiceName:       "myservicename",
				DockerComposeFile: "docker-compose.yml",
				ComposeService: ComposeService{
					Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
				LogMedium: ioutil.Discard,
				Rebuild:   true,
			},
			"meli_myservicename",
			nil},
	}

	var ctx = context.Background()
	cli := &mockDockerClient{}
	LoadAuth()
	for _, v := range tt {
		actual, err := BuildDockerImage(ctx, cli, v.dc)
		if err != nil {
			t.Errorf("\nCalled BuildDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, err, v.expectedErr)
		}
		if actual != v.expected {
			t.Errorf("\nCalled BuildDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, actual, v.expected)
		}
	}
}

func BenchmarkPullDockerImage(b *testing.B) {
	var ctx = context.Background()
	cli := &mockDockerClient{}
	dc := &DockerContainer{ComposeService: ComposeService{Image: "busybox"}, LogMedium: ioutil.Discard}
	LoadAuth()
	for n := 0; n < b.N; n++ {
		_ = PullDockerImage(ctx, cli, dc)
	}
}

func BenchmarkBuildDockerImage(b *testing.B) {
	var ctx = context.Background()
	cli := &mockDockerClient{}
	dc := &DockerContainer{
		ServiceName:       "myservicename",
		DockerComposeFile: "docker-compose.yml",
		ComposeService: ComposeService{
			Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
		LogMedium: ioutil.Discard,
		Rebuild:   true,
	}
	LoadAuth()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, _ = BuildDockerImage(ctx, cli, dc)
	}
}

func BenchmarkPoolReadFrom(b *testing.B) {
	r := strings.NewReader("hello")
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, _ = poolReadFrom(r)
	}
}
<commit_msg>add test for image with custom user context<commit_after>package meli

import (
	"context"
	"io/ioutil"
	"strings"
	"testing"
)

func TestPullDockerImage(t *testing.T) {
	tt := []struct {
		dc          *DockerContainer
		expectedErr error
	}{
		{&DockerContainer{ComposeService: ComposeService{Image: "busybox"}, LogMedium: ioutil.Discard}, nil},
	}
	var ctx = context.Background()
	cli := &mockDockerClient{}
	for _, v := range tt {
		err := PullDockerImage(ctx, cli, v.dc)
		if err != nil {
			t.Errorf("\nCalled PullDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, err, v.expectedErr)
		}
	}
}

func TestBuildDockerImage(t *testing.T) {
	tt := []struct {
		dc          *DockerContainer
		expected    string
		expectedErr error
	}{
		{
			&DockerContainer{
				ServiceName:       "myservicename",
				DockerComposeFile: "docker-compose.yml",
				ComposeService: ComposeService{
					Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
				LogMedium: ioutil.Discard},
			"meli_myservicename",
			nil},
		{
			&DockerContainer{
				ServiceName:       "myservicename",
				DockerComposeFile: "docker-compose.yml",
				ComposeService: ComposeService{
					Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
				LogMedium: ioutil.Discard,
				Rebuild:   true,
			},
			"meli_myservicename",
			nil},
		{

			&DockerContainer{
				ServiceName:       "myservicename",
				DockerComposeFile: "testdata/docker-compose.yml",
				ComposeService: ComposeService{
					Build: Buildstruct{
						Dockerfile: "nestedDockerfile",
						Context:    "nestedDir/level1/level2/"}},
				LogMedium: ioutil.Discard,
				Rebuild:   true,
			},
			"meli_myservicename",
			nil},
	}

	var ctx = context.Background()
	cli := &mockDockerClient{}
	LoadAuth()
	for _, v := range tt {
		actual, err := BuildDockerImage(ctx, cli, v.dc)
		if err != nil {
			t.Errorf("\nCalled BuildDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, err, v.expectedErr)
		}
		if actual != v.expected {
			t.Errorf("\nCalled BuildDockerImage(%#+v) \ngot %s \nwanted %#+v", v.dc, actual, v.expected)
		}
	}
}

func BenchmarkPullDockerImage(b *testing.B) {
	var ctx = context.Background()
	cli := &mockDockerClient{}
	dc := &DockerContainer{ComposeService: ComposeService{Image: "busybox"}, LogMedium: ioutil.Discard}
	LoadAuth()
	for n := 0; n < b.N; n++ {
		_ = PullDockerImage(ctx, cli, dc)
	}
}

func BenchmarkBuildDockerImage(b *testing.B) {
	var ctx = context.Background()
	cli := &mockDockerClient{}
	dc := &DockerContainer{
		ServiceName:       "myservicename",
		DockerComposeFile: "docker-compose.yml",
		ComposeService: ComposeService{
			Build: Buildstruct{Dockerfile: "testdata/Dockerfile"}},
		LogMedium: ioutil.Discard,
		Rebuild:   true,
	}
	LoadAuth()
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, _ = BuildDockerImage(ctx, cli, dc)
	}
}

func BenchmarkPoolReadFrom(b *testing.B) {
	r := strings.NewReader("hello")
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		_, _ = poolReadFrom(r)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/ChristopherRabotin/smd"
)

const (
	debug = false
)

var (
	cpus   int
	planet string
)

func init() {
	// Read flags
	flag.IntVar(&cpus, "cpus", -1, "number of CPUs to use for this simulation (set to 0 for max CPUs)")
	if cpus <= 0 {
		cpus = runtime.NumCPU()
	}
	runtime.GOMAXPROCS(cpus)
	fmt.Printf("Running on %d CPUs\n", cpus)
	flag.StringVar(&planet, "planet", "undef", "departure planet to perform the spiral from")
	planet = strings.ToLower(planet)
}

/*
 * This example shows how to find the greatest heliocentric velocity at the end of a spiral by iterating on the initial
 * true anomaly.
 */

func sc() *smd.Spacecraft {
	eps := smd.NewUnlimitedEPS()
	thrusters := []smd.EPThruster{smd.NewGenericEP(5, 5000)} // VASIMR (approx.)
	dryMass := 10000.0
	fuelMass := 5000.0
	return smd.NewSpacecraft("Spiral", dryMass, fuelMass, eps, thrusters, false, []*smd.Cargo{},
		[]smd.Waypoint{smd.NewToHyperbolic(nil)})
}

func initEarthOrbit(i, Ω, ω, ν float64) *smd.Orbit {
	a, e := smd.Radii2ae(39300+smd.Earth.Radius, 290+smd.Earth.Radius)
	return smd.NewOrbitFromOE(a, e, i, Ω, ω, ν, smd.Earth)
}

// initMarsOrbit returns the initial orbit.
func initMarsOrbit(i, Ω, ω, ν float64) *smd.Orbit {
	// Exomars TGO.
	a, e := smd.Radii2ae(44500+smd.Mars.Radius, 426+smd.Mars.Radius)
	return smd.NewOrbitFromOE(a, e, i, Ω, ω, ν, smd.Mars)
}

func main() {
	flag.Parse()
	var orbitPtr func(i, Ω, ω, ν float64) *smd.Orbit

	switch planet {
	case "mars":
		orbitPtr = initMarsOrbit
	case "earth":
		orbitPtr = initEarthOrbit
	default:
		panic(fmt.Errorf("unsupported planet %s", planet))
	}

	fmt.Printf("Finding spirals leaving from %s\n", planet)

	//name := "spiral-mars"
	depart := time.Date(2018, 11, 8, 0, 0, 0, 0, time.UTC)
	chgframePath := "../../cmd/refframes/chgframe.py"
	maxV := -1e3
	minV := +1e3
	var maxOrbit smd.Orbit
	var minOrbit smd.Orbit
	a, e, _, _, _, _, _, _, _ := initMarsOrbit(10, 10, 10, 10).Elements()
	tsv := fmt.Sprintf("#a=%f km\te=%f\n#V(km/s), i (degrees), raan (degrees), arg peri (degrees),nu (degrees)\n", a, e)
	stepSize := 5.
	for i := 1.0; i < 90; i += stepSize {
		for Ω := 0.0; Ω < 360; Ω += stepSize {
			for ω := 0.0; ω < 360; ω += stepSize {
				for ν := 0.0; ν < 360; ν += stepSize {
					initOrbit := orbitPtr(i, Ω, ω, ν)
					astro := smd.NewMission(sc(), initOrbit, depart, depart.Add(-1), smd.Cartesian, smd.Perturbations{}, smd.ExportConfig{})
					astro.Propagate()

					// Run chgframe
					// We're now done so let's convert the position and velocity to heliocentric and check the output.
					R, V := initOrbit.RV()
					state := fmt.Sprintf("[%f,%f,%f,%f,%f,%f]", R[0], R[1], R[2], V[0], V[1], V[2])
					if debug {
						fmt.Printf("\n=== RUNNING CMD ===\npython %s -t J2000 -f IAU_Earth -e \"%s\" -s \"%s\"\n", chgframePath, astro.CurrentDT.Format(time.ANSIC), state)
					}
					cmd := exec.Command("python", chgframePath, "-t", "J2000", "-f", "IAU_Mars", "-e", astro.CurrentDT.Format(time.ANSIC), "-s", state)
					cmdOut, err := cmd.Output()
					if err != nil {
						fmt.Fprintln(os.Stderr, "Error converting orbit to helio ", err)
						os.Exit(1)
					}
					out := string(cmdOut)

					// Process output
					newState := strings.TrimSpace(string(out))
					// Cf. https://play.golang.org/p/g-a4idjhIb
					newState = newState[1 : len(newState)-1]
					components := strings.Split(newState, ",")
					var nR = make([]float64, 3)
					var nV = make([]float64, 3)
					for i := 0; i < 6; i++ {
						fl, err := strconv.ParseFloat(strings.TrimSpace(components[i]), 64)
						if err != nil {
							panic(err)
						}
						if i < 3 {
							nR[i] = fl
						} else {
							nV[i-3] = fl
						}
					}
					vNorm := math.Sqrt(math.Pow(nV[0], 2) + math.Pow(nV[1], 2) + math.Pow(nV[2], 2))
					// Add to TSV file
					tsv += fmt.Sprintf("%f,%f,%f,%f,%f\n", vNorm, i, Ω, ω, ν)
					if vNorm > maxV {
						maxV = vNorm
						maxOrbit = *initMarsOrbit(i, Ω, ω, ν)
					} else if vNorm < minV {
						minV = vNorm
						minOrbit = *initMarsOrbit(i, Ω, ω, ν)
					}
					if debug {
						fmt.Printf("\nν=%f\t=>V=%+v\t|V|=%f\n", ν, nV, vNorm)
					}
				}
			}
		}
	}
	fmt.Printf("\n\n=== RESULT ===\n\nmaxV=%.3f km/s\t%s\nminV=%.3f km/s\t%s\n\n", maxV, maxOrbit, minV, minOrbit)
	// Write CSV file.
	f, err := os.Create(fmt.Sprintf("./results-.csv"))
	if err != nil {
		panic(err)
	}
	defer f.Close()
	if _, err := f.WriteString(tsv); err != nil {
		panic(err)
	}
}
<commit_msg>Better management of flags<commit_after>package main

import (
	"flag"
	"fmt"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/ChristopherRabotin/smd"
)

const (
	debug = false
)

var (
	cpus     int
	planet   string
	stepSize float64
)

func init() {
	// Read flags
	flag.IntVar(&cpus, "cpus", -1, "number of CPUs to use for this simulation (set to 0 for max CPUs)")
	flag.StringVar(&planet, "planet", "undef", "departure planet to perform the spiral from")
	flag.Float64Var(&stepSize, "step", 15, "step size (10 to 30 recommended)")
}

/*
 * This example shows how to find the greatest heliocentric velocity at the end of a spiral by iterating on the initial
 * true anomaly.
 */

func sc() *smd.Spacecraft {
	eps := smd.NewUnlimitedEPS()
	thrusters := []smd.EPThruster{smd.NewGenericEP(5, 5000)} // VASIMR (approx.)
	dryMass := 10000.0
	fuelMass := 5000.0
	return smd.NewSpacecraft("Spiral", dryMass, fuelMass, eps, thrusters, false, []*smd.Cargo{},
		[]smd.Waypoint{smd.NewToHyperbolic(nil)})
}

func initEarthOrbit(i, Ω, ω, ν float64) *smd.Orbit {
	a, e := smd.Radii2ae(39300+smd.Earth.Radius, 290+smd.Earth.Radius)
	return smd.NewOrbitFromOE(a, e, i, Ω, ω, ν, smd.Earth)
}

// initMarsOrbit returns the initial orbit.
func initMarsOrbit(i, Ω, ω, ν float64) *smd.Orbit {
	// Exomars TGO.
	a, e := smd.Radii2ae(44500+smd.Mars.Radius, 426+smd.Mars.Radius)
	return smd.NewOrbitFromOE(a, e, i, Ω, ω, ν, smd.Mars)
}

func main() {
	flag.Parse()
	availableCPUs := runtime.NumCPU()
	if cpus <= 0 || cpus > availableCPUs {
		cpus = availableCPUs
	}
	runtime.GOMAXPROCS(cpus)
	fmt.Printf("running on %d CPUs\n", cpus)

	if stepSize <= 0 {
		fmt.Println("step size must be positive")
		flag.Usage()
		return
	} else if stepSize <= 5 {
		fmt.Println("[WARNING] A small step size will take several days to iterate over all possibilities")
	}

	var orbitPtr func(i, Ω, ω, ν float64) *smd.Orbit
	planet = strings.ToLower(planet)
	switch planet {
	case "mars":
		orbitPtr = initMarsOrbit
	case "earth":
		orbitPtr = initEarthOrbit
	default:
		fmt.Printf("unsupported planet `%s`\n", planet)
		flag.Usage()
		return
	}

	fmt.Printf("Finding spirals leaving from %s\n", planet)

	//name := "spiral-mars"
	depart := time.Date(2018, 11, 8, 0, 0, 0, 0, time.UTC)
	chgframePath := "../../cmd/refframes/chgframe.py"
	maxV := -1e3
	minV := +1e3
	var maxOrbit smd.Orbit
	var minOrbit smd.Orbit
	a, e, _, _, _, _, _, _, _ := initMarsOrbit(10, 10, 10, 10).Elements()
	tsv := fmt.Sprintf("#a=%f km\te=%f\n#V(km/s), i (degrees), raan (degrees), arg peri (degrees),nu (degrees)\n", a, e)
	for i := 1.0; i < 90; i += stepSize {
		for Ω := 0.0; Ω < 360; Ω += stepSize {
			for ω := 0.0; ω < 360; ω += stepSize {
				for ν := 0.0; ν < 360; ν += stepSize {
					initOrbit := orbitPtr(i, Ω, ω, ν)
					astro := smd.NewMission(sc(), initOrbit, depart, depart.Add(-1), smd.Cartesian, smd.Perturbations{}, smd.ExportConfig{})
					astro.Propagate()

					// Run chgframe
					// We're now done so let's convert the position and velocity to heliocentric and check the output.
					R, V := initOrbit.RV()
					state := fmt.Sprintf("[%f,%f,%f,%f,%f,%f]", R[0], R[1], R[2], V[0], V[1], V[2])
					if debug {
						fmt.Printf("\n=== RUNNING CMD ===\npython %s -t J2000 -f IAU_Earth -e \"%s\" -s \"%s\"\n", chgframePath, astro.CurrentDT.Format(time.ANSIC), state)
					}
					cmd := exec.Command("python", chgframePath, "-t", "J2000", "-f", "IAU_Mars", "-e", astro.CurrentDT.Format(time.ANSIC), "-s", state)
					cmdOut, err := cmd.Output()
					if err != nil {
						fmt.Fprintln(os.Stderr, "Error converting orbit to helio ", err)
						os.Exit(1)
					}
					out := string(cmdOut)

					// Process output
					newState := strings.TrimSpace(string(out))
					// Cf. https://play.golang.org/p/g-a4idjhIb
					newState = newState[1 : len(newState)-1]
					components := strings.Split(newState, ",")
					var nR = make([]float64, 3)
					var nV = make([]float64, 3)
					for i := 0; i < 6; i++ {
						fl, err := strconv.ParseFloat(strings.TrimSpace(components[i]), 64)
						if err != nil {
							panic(err)
						}
						if i < 3 {
							nR[i] = fl
						} else {
							nV[i-3] = fl
						}
					}
					vNorm := math.Sqrt(math.Pow(nV[0], 2) + math.Pow(nV[1], 2) + math.Pow(nV[2], 2))
					// Add to TSV file
					tsv += fmt.Sprintf("%f,%f,%f,%f,%f\n", vNorm, i, Ω, ω, ν)
					if vNorm > maxV {
						maxV = vNorm
						maxOrbit = *initMarsOrbit(i, Ω, ω, ν)
					} else if vNorm < minV {
						minV = vNorm
						minOrbit = *initMarsOrbit(i, Ω, ω, ν)
					}
					if debug {
						fmt.Printf("\nν=%f\t=>V=%+v\t|V|=%f\n", ν, nV, vNorm)
					}
				}
			}
		}
	}
	fmt.Printf("\n\n=== RESULT ===\n\nmaxV=%.3f km/s\t%s\nminV=%.3f km/s\t%s\n\n", maxV, maxOrbit, minV, minOrbit)
	// Write CSV file.
	f, err := os.Create(fmt.Sprintf("./results-.csv"))
	if err != nil {
		panic(err)
	}
	defer f.Close()
	if _, err := f.WriteString(tsv); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package bitswap

import (
	"os"
	"strconv"
	"time"

	inflect "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/chuckpreslar/inflect"
	process "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
	u "github.com/ipfs/go-ipfs/util"
)

var TaskWorkerCount = 16

func init() {
	twc := os.Getenv("IPFS_TASK_WORKERS")
	if twc != "" {
		n, err := strconv.Atoi(twc)
		if err != nil {
			log.Error(err)
			return
		}
		if n > 0 {
			TaskWorkerCount = n
		} else {
			log.Errorf("Invalid value of '%d' for IPFS_TASK_WORKERS", n)
		}
	}
}

func (bs *Bitswap) startWorkers(px process.Process, ctx context.Context) {
	// Start up a worker to handle block requests this node is making
	px.Go(func(px process.Process) {
		bs.clientWorker(ctx)
	})

	// Start up workers to handle requests from other nodes for the data on this node
	for i := 0; i < TaskWorkerCount; i++ {
		px.Go(func(px process.Process) {
			bs.taskWorker(ctx)
		})
	}

	// Start up a worker to manage periodically resending our wantlist out to peers
	px.Go(func(px process.Process) {
		bs.rebroadcastWorker(ctx)
	})

	px.Go(func(px process.Process) {
		bs.provideCollector(ctx)
	})

	// Spawn up multiple workers to handle incoming blocks
	// consider increasing number if providing blocks bottlenecks
	// file transfers
	for i := 0; i < provideWorkers; i++ {
		px.Go(func(px process.Process) {
			bs.provideWorker(ctx)
		})
	}
}

func (bs *Bitswap) taskWorker(ctx context.Context) {
	defer log.Info("bitswap task worker shutting down...")
	for {
		select {
		case nextEnvelope := <-bs.engine.Outbox():
			select {
			case envelope, ok := <-nextEnvelope:
				if !ok {
					continue
				}
				log.Event(ctx, "deliverBlocks", envelope.Message, envelope.Peer)
				bs.send(ctx, envelope.Peer, envelope.Message)
				envelope.Sent()
			case <-ctx.Done():
				return
			}
		case <-ctx.Done():
			return
		}
	}
}

func (bs *Bitswap) provideWorker(ctx context.Context) {
	for {
		select {
		case k, ok := <-bs.provideKeys:
			if !ok {
				log.Debug("provideKeys channel closed")
				return
			}
			ctx, cancel := context.WithTimeout(ctx, provideTimeout)
			err := bs.network.Provide(ctx, k)
			if err != nil {
				log.Error(err)
			}
			cancel()
		case <-ctx.Done():
			return
		}
	}
}

func (bs *Bitswap) provideCollector(ctx context.Context) {
	defer close(bs.provideKeys)
	var toProvide []u.Key
	var nextKey u.Key
	var keysOut chan u.Key

	for {
		select {
		case blk, ok := <-bs.newBlocks:
			if !ok {
				log.Debug("newBlocks channel closed")
				return
			}
			if keysOut == nil {
				nextKey = blk.Key()
				keysOut = bs.provideKeys
			} else {
				toProvide = append(toProvide, blk.Key())
			}
		case keysOut <- nextKey:
			if len(toProvide) > 0 {
				nextKey = toProvide[0]
				toProvide = toProvide[1:]
			} else {
				keysOut = nil
			}
		case <-ctx.Done():
			return
		}
	}
}

// TODO ensure only one active request per key
func (bs *Bitswap) clientWorker(parent context.Context) {
	defer log.Info("bitswap client worker shutting down...")

	for {
		select {
		case req := <-bs.batchRequests:
			keys := req.keys
			if len(keys) == 0 {
				log.Warning("Received batch request for zero blocks")
				continue
			}
			for i, k := range keys {
				bs.wantlist.Add(k, kMaxPriority-i)
			}

			done := make(chan struct{})
			go func() {
				bs.wantNewBlocks(req.ctx, keys)
				close(done)
			}()

			// NB: Optimization. Assumes that providers of key[0] are likely to
			// be able to provide for all keys. This currently holds true in most
			// every situation. Later, this assumption may not hold as true.
			child, cancel := context.WithTimeout(req.ctx, providerRequestTimeout)
			providers := bs.network.FindProvidersAsync(child, keys[0], maxProvidersPerRequest)
			err := bs.sendWantlistToPeers(req.ctx, providers)
			if err != nil {
				log.Debugf("error sending wantlist: %s", err)
			}
			cancel()

			// Wait for wantNewBlocks to finish
			<-done

		case <-parent.Done():
			return
		}
	}
}

func (bs *Bitswap) rebroadcastWorker(parent context.Context) {
	ctx, cancel := context.WithCancel(parent)
	defer cancel()

	broadcastSignal := time.After(rebroadcastDelay.Get())

	for {
		select {
		case <-time.Tick(10 * time.Second):
			n := bs.wantlist.Len()
			if n > 0 {
				log.Debug(n, inflect.FromNumber("keys", n), "in bitswap wantlist")
			}
		case <-broadcastSignal: // resend unfulfilled wantlist keys
			entries := bs.wantlist.Entries()
			if len(entries) > 0 {
				bs.sendWantlistToProviders(ctx, entries)
			}
			broadcastSignal = time.After(rebroadcastDelay.Get())
		case <-parent.Done():
			return
		}
	}
}
<commit_msg>change env var for bitswap<commit_after>package bitswap

import (
	"os"
	"strconv"
	"time"

	inflect "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/chuckpreslar/inflect"
	process "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
	u "github.com/ipfs/go-ipfs/util"
)

var TaskWorkerCount = 16

func init() {
	twc := os.Getenv("IPFS_BITSWAP_TASK_WORKERS")
	if twc != "" {
		n, err := strconv.Atoi(twc)
		if err != nil {
			log.Error(err)
			return
		}
		if n > 0 {
			TaskWorkerCount = n
		} else {
			log.Errorf("Invalid value of '%d' for IPFS_BITSWAP_TASK_WORKERS", n)
		}
	}
}

func (bs *Bitswap) startWorkers(px process.Process, ctx context.Context) {
	// Start up a worker to handle block requests this node is making
	px.Go(func(px process.Process) {
		bs.clientWorker(ctx)
	})

	// Start up workers to handle requests from other nodes for the data on this node
	for i := 0; i < TaskWorkerCount; i++ {
		px.Go(func(px process.Process) {
			bs.taskWorker(ctx)
		})
	}

	// Start up a worker to manage periodically resending our wantlist out to peers
	px.Go(func(px process.Process) {
		bs.rebroadcastWorker(ctx)
	})

	px.Go(func(px process.Process) {
		bs.provideCollector(ctx)
	})

	// Spawn up multiple workers to handle incoming blocks
	// consider increasing number if providing blocks bottlenecks
	// file transfers
	for i := 0; i < provideWorkers; i++ {
		px.Go(func(px process.Process) {
			bs.provideWorker(ctx)
		})
	}
}

func (bs *Bitswap) taskWorker(ctx context.Context) {
	defer log.Info("bitswap task worker shutting down...")
	for {
		select {
		case nextEnvelope := <-bs.engine.Outbox():
			select {
			case envelope, ok := <-nextEnvelope:
				if !ok {
					continue
				}
				log.Event(ctx, "deliverBlocks", envelope.Message, envelope.Peer)
				bs.send(ctx, envelope.Peer, envelope.Message)
				envelope.Sent()
			case <-ctx.Done():
				return
			}
		case <-ctx.Done():
			return
		}
	}
}

func (bs *Bitswap) provideWorker(ctx context.Context) {
	for {
		select {
		case k, ok := <-bs.provideKeys:
			if !ok {
				log.Debug("provideKeys channel closed")
				return
			}
			ctx, cancel := context.WithTimeout(ctx, provideTimeout)
			err := bs.network.Provide(ctx, k)
			if err != nil {
				log.Error(err)
			}
			cancel()
		case <-ctx.Done():
			return
		}
	}
}

func (bs *Bitswap) provideCollector(ctx context.Context) {
	defer close(bs.provideKeys)
	var toProvide []u.Key
	var nextKey u.Key
	var keysOut chan u.Key

	for {
		select {
		case blk, ok := <-bs.newBlocks:
			if !ok {
				log.Debug("newBlocks channel closed")
				return
			}
			if keysOut == nil {
				nextKey = blk.Key()
				keysOut = bs.provideKeys
			} else {
				toProvide = append(toProvide, blk.Key())
			}
		case keysOut <- nextKey:
			if len(toProvide) > 0 {
				nextKey = toProvide[0]
				toProvide = toProvide[1:]
			} else {
				keysOut = nil
			}
		case <-ctx.Done():
			return
		}
	}
}

// TODO ensure only one active request per key
func (bs *Bitswap) clientWorker(parent context.Context) {
	defer log.Info("bitswap client worker shutting down...")

	for {
		select {
		case req := <-bs.batchRequests:
			keys := req.keys
			if len(keys) == 0 {
				log.Warning("Received batch request for zero blocks")
				continue
			}
			for i, k := range keys {
				bs.wantlist.Add(k, kMaxPriority-i)
			}

			done := make(chan struct{})
			go func() {
				bs.wantNewBlocks(req.ctx, keys)
				close(done)
			}()

			// NB: Optimization. Assumes that providers of key[0] are likely to
			// be able to provide for all keys. This currently holds true in most
			// every situation. Later, this assumption may not hold as true.
			child, cancel := context.WithTimeout(req.ctx, providerRequestTimeout)
			providers := bs.network.FindProvidersAsync(child, keys[0], maxProvidersPerRequest)
			err := bs.sendWantlistToPeers(req.ctx, providers)
			if err != nil {
				log.Debugf("error sending wantlist: %s", err)
			}
			cancel()

			// Wait for wantNewBlocks to finish
			<-done

		case <-parent.Done():
			return
		}
	}
}

func (bs *Bitswap) rebroadcastWorker(parent context.Context) {
	ctx, cancel := context.WithCancel(parent)
	defer cancel()

	broadcastSignal := time.After(rebroadcastDelay.Get())

	for {
		select {
		case <-time.Tick(10 * time.Second):
			n := bs.wantlist.Len()
			if n > 0 {
				log.Debug(n, inflect.FromNumber("keys", n), "in bitswap wantlist")
			}
		case <-broadcastSignal: // resend unfulfilled wantlist keys
			entries := bs.wantlist.Entries()
			if len(entries) > 0 {
				bs.sendWantlistToProviders(ctx, entries)
			}
			broadcastSignal = time.After(rebroadcastDelay.Get())
		case <-parent.Done():
			return
		}
	}
}
<|endoftext|>


<commit_before>package bitswap

import (
	"errors"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"

	blocks "github.com/jbenet/go-ipfs/blocks"
	exchange "github.com/jbenet/go-ipfs/exchange"
	u "github.com/jbenet/go-ipfs/util"
)

func NewOfflineExchange() exchange.Interface {
	return &offlineExchange{}
}

// offlineExchange implements the Exchange interface but doesn't return blocks.
// For use in offline mode.
type offlineExchange struct {
}

// Block returns nil to signal that a block could not be retrieved for the
// given key.
// NB: This function may return before the timeout expires.
func (_ *offlineExchange) Block(context.Context, u.Key) (*blocks.Block, error) {
	return nil, errors.New("Block unavailable. Operating in offline mode")
}

// HasBlock always returns nil.
func (_ *offlineExchange) HasBlock(context.Context, blocks.Block) error {
	return nil
}
<commit_msg>fix(exch) name the error<commit_after>package bitswap

import (
	"errors"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"

	blocks "github.com/jbenet/go-ipfs/blocks"
	exchange "github.com/jbenet/go-ipfs/exchange"
	u "github.com/jbenet/go-ipfs/util"
)

var OfflineMode = errors.New("Block unavailable. Operating in offline mode")

func NewOfflineExchange() exchange.Interface {
	return &offlineExchange{}
}

// offlineExchange implements the Exchange interface but doesn't return blocks.
// For use in offline mode.
type offlineExchange struct {
}

// Block returns nil to signal that a block could not be retrieved for the
// given key.
// NB: This function may return before the timeout expires.
func (_ *offlineExchange) Block(context.Context, u.Key) (*blocks.Block, error) {
	return nil, OfflineMode
}

// HasBlock always returns nil.
func (_ *offlineExchange) HasBlock(context.Context, blocks.Block) error {
	return nil
}
<|endoftext|>


<commit_before>package gmx

import (
	"sync/atomic"
)

type counter struct {
	value uint64
}

func (c *counter) Inc() {
	atomic.AddUint64(&c.value, 1)
}

func NewCounter(name string) *counter {
	c := new(counter)
	Publish(name, func() interface{} {
		return c.value
	})
	return c
}

type gauge struct {
	value int64
}

func (g *gauge) Inc() {
	atomic.AddInt64(&g.value, 1)
}

func (g *gauge) Dec() {
	atomic.AddInt64(&g.value, -1)
}

func NewGauge(name string) *gauge {
	g := new(gauge)
	Publish(name, func() interface{} {
		return g.value
	})
	return g
}
<commit_msg>Export Counter and Gauge types<commit_after>package gmx

import (
	"sync/atomic"
)

type Counter struct {
	value uint64
}

func (c *Counter) Inc() {
	atomic.AddUint64(&c.value, 1)
}

func NewCounter(name string) *Counter {
	c := new(Counter)
	Publish(name, func() interface{} {
		return c.value
	})
	return c
}

type Gauge struct {
	value int64
}

func (g *Gauge) Inc() {
	atomic.AddInt64(&g.value, 1)
}

func (g *Gauge) Dec() {
	atomic.AddInt64(&g.value, -1)
}

func NewGauge(name string) *Gauge {
	g := new(Gauge)
	Publish(name, func() interface{} {
		return g.value
	})
	return g
}
<|endoftext|>


<commit_before>package memdb

import (
	"reflect"
	"testing"
	"time"
)

// Test that multiple concurrent transactions are isolated from each other
func TestTxn_Isolation(t *testing.T) {
	db := testDB(t)
	txn1 := db.Txn(true)

	obj := &TestObject{
		ID:  "my-object",
		Foo: "abc",
		Qux: []string{"abc1", "abc2"},
	}
	obj2 := &TestObject{
		ID:  "my-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}
	obj3 := &TestObject{
		ID:  "my-other-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}

	err := txn1.Insert("main", obj)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj2)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj3)
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Results should show up in this transaction
	raw, err := txn1.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw == nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Create a new transaction, current one is NOT committed
	txn2 := db.Txn(false)

	// Nothing should show up in this transaction
	raw, err = txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Commit txn1, txn2 should still be isolated
	txn1.Commit()

	// Nothing should show up in this transaction
	raw, err = txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Create a new txn
	txn3 := db.Txn(false)

	// Results should show up in this transaction
	raw, err = txn3.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw == nil {
		t.Fatalf("bad: %#v", raw)
	}
}

// Test that an abort clears progress
func TestTxn_Abort(t *testing.T) {
	db := testDB(t)
	txn1 := db.Txn(true)

	obj := &TestObject{
		ID:  "my-object",
		Foo: "abc",
		Qux: []string{"abc1", "abc2"},
	}
	obj2 := &TestObject{
		ID:  "my-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}
	obj3 := &TestObject{
		ID:  "my-other-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}

	err := txn1.Insert("main", obj)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj2)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj3)
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Abort the txn
	txn1.Abort()
	txn1.Commit()

	// Create a new transaction
	txn2 := db.Txn(false)

	// Nothing should show up in this transaction
	raw, err := txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}
}

func TestComplexDB(t *testing.T) {
	db := testComplexDB(t)
	testPopulateData(t, db)
	txn := db.Txn(false) // read only

	// Get using a full name
	raw, err := txn.First("people", "name", "Armon", "Dadgar")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	// Get using a prefix
	raw, err = txn.First("people", "name_prefix", "Armon")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	raw, err = txn.First("people", "id_prefix", raw.(*TestPerson).ID[:4])
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	// Get based on field set.
	result, err := txn.Get("people", "sibling", true)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	exp := map[string]bool{"Alex": true, "Armon": true}
	act := make(map[string]bool, 2)
	for i := result.Next(); i != nil; i = result.Next() {
		p, ok := i.(*TestPerson)
		if !ok {
			t.Fatalf("should get person")
		}
		act[p.First] = true
	}

	if !reflect.DeepEqual(act, exp) {
		t.Fatalf("Got %#v; want %#v", act, exp)
	}

	raw, err = txn.First("people", "sibling", false)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	if raw.(*TestPerson).First != "Mitchell" {
		t.Fatalf("wrong person!")
	}

	// Where in the world is mitchell hashimoto?
	raw, err = txn.First("people", "name_prefix", "Mitchell")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	person := raw.(*TestPerson)
	if person.First != "Mitchell" {
		t.Fatalf("wrong person!")
	}

	raw, err = txn.First("visits", "id_prefix", person.ID)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get visit")
	}

	visit := raw.(*TestVisit)

	raw, err = txn.First("places", "id", visit.Place)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get place")
	}

	place := raw.(*TestPlace)
	if place.Name != "Maui" {
		t.Fatalf("bad place (but isn't anywhere else really?): %v", place)
	}
}

func TestWatchUpdate(t *testing.T) {
	db := testComplexDB(t)
	testPopulateData(t, db)
	txn := db.Txn(false) // read only

	watchSetSpecific := NewWatchSet()
	watchSetPrefix := NewWatchSet()

	// Get using a full name
	watch, raw, err := txn.FirstWatch("people", "name", "Armon", "Dadgar")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	watchSetSpecific.Add(watch)

	// Get using a prefix
	watch, raw, err = txn.FirstWatch("people", "name_prefix", "Armon")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	watchSetPrefix.Add(watch)

	txn2 := db.Txn(true) // write
	noErr(t, txn2.Delete("people", raw))
	txn2.Commit()

	// Both watches should trigger!
	timeout := time.After(time.Second)
	if timeout := watchSetSpecific.Watch(timeout); timeout {
		t.Fatalf("should not timeout")
	}
	if timeout := watchSetPrefix.Watch(timeout); timeout {
		t.Fatalf("should not timeout")
	}
}

func testPopulateData(t *testing.T, db *MemDB) {
	// Start write txn
	txn := db.Txn(true)

	// Create some data
	person1 := testPerson()

	person2 := testPerson()
	person2.First = "Mitchell"
	person2.Last = "Hashimoto"

	person3 := testPerson()
	person3.First = "Alex"
	person3.Last = "Dadgar"

	person1.Sibling = person3
	person3.Sibling = person1

	place1 := testPlace()
	place2 := testPlace()
	place2.Name = "Maui"

	visit1 := &TestVisit{person1.ID, place1.ID}
	visit2 := &TestVisit{person2.ID, place2.ID}

	// Insert it all
	noErr(t, txn.Insert("people", person1))
	noErr(t, txn.Insert("people", person2))
	noErr(t, txn.Insert("people", person3))
	noErr(t, txn.Insert("places", place1))
	noErr(t, txn.Insert("places", place2))
	noErr(t, txn.Insert("visits", visit1))
	noErr(t, txn.Insert("visits", visit2))

	// Commit
	txn.Commit()
}

func noErr(t *testing.T, err error) {
	if err != nil {
		t.Fatalf("err: %v", err)
	}
}

type TestPerson struct {
	ID      string
	First   string
	Last    string
	Sibling *TestPerson
}

type TestPlace struct {
	ID   string
	Name string
}

type TestVisit struct {
	Person string
	Place  string
}

func testComplexSchema() *DBSchema {
	return &DBSchema{
		Tables: map[string]*TableSchema{
			"people": &TableSchema{
				Name: "people",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:    "id",
						Unique:  true,
						Indexer: &UUIDFieldIndex{Field: "ID"},
					},
					"name": &IndexSchema{
						Name:   "name",
						Unique: true,
						Indexer: &CompoundIndex{
							Indexes: []Indexer{
								&StringFieldIndex{Field: "First"},
								&StringFieldIndex{Field: "Last"},
							},
						},
					},
					"sibling": &IndexSchema{
						Name:    "sibling",
						Unique:  false,
						Indexer: &FieldSetIndex{Field: "Sibling"},
					},
				},
			},
			"places": &TableSchema{
				Name: "places",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:    "id",
						Unique:  true,
						Indexer: &UUIDFieldIndex{Field: "ID"},
					},
					"name": &IndexSchema{
						Name:    "name",
						Unique:  true,
						Indexer: &StringFieldIndex{Field: "Name"},
					},
				},
			},
			"visits": &TableSchema{
				Name: "visits",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:   "id",
						Unique: true,
						Indexer: &CompoundIndex{
							Indexes: []Indexer{
								&UUIDFieldIndex{Field: "Person"},
								&UUIDFieldIndex{Field: "Place"},
							},
						},
					},
				},
			},
		},
	}
}

func testComplexDB(t *testing.T) *MemDB {
	db, err := NewMemDB(testComplexSchema())
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	return db
}

func testPerson() *TestPerson {
	_, uuid := generateUUID()
	obj := &TestPerson{
		ID:    uuid,
		First: "Armon",
		Last:  "Dadgar",
	}
	return obj
}

func testPlace() *TestPlace {
	_, uuid := generateUUID()
	obj := &TestPlace{
		ID:   uuid,
		Name: "HashiCorp",
	}
	return obj
}
<commit_msg>Adds some test coverage for iterator watch channels and non-triggering snapshots.<commit_after>package memdb

import (
	"reflect"
	"testing"
	"time"
)

// Test that multiple concurrent transactions are isolated from each other
func TestTxn_Isolation(t *testing.T) {
	db := testDB(t)
	txn1 := db.Txn(true)

	obj := &TestObject{
		ID:  "my-object",
		Foo: "abc",
		Qux: []string{"abc1", "abc2"},
	}
	obj2 := &TestObject{
		ID:  "my-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}
	obj3 := &TestObject{
		ID:  "my-other-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}

	err := txn1.Insert("main", obj)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj2)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj3)
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Results should show up in this transaction
	raw, err := txn1.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw == nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Create a new transaction, current one is NOT committed
	txn2 := db.Txn(false)

	// Nothing should show up in this transaction
	raw, err = txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Commit txn1, txn2 should still be isolated
	txn1.Commit()

	// Nothing should show up in this transaction
	raw, err = txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}

	// Create a new txn
	txn3 := db.Txn(false)

	// Results should show up in this transaction
	raw, err = txn3.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw == nil {
		t.Fatalf("bad: %#v", raw)
	}
}

// Test that an abort clears progress
func TestTxn_Abort(t *testing.T) {
	db := testDB(t)
	txn1 := db.Txn(true)

	obj := &TestObject{
		ID:  "my-object",
		Foo: "abc",
		Qux: []string{"abc1", "abc2"},
	}
	obj2 := &TestObject{
		ID:  "my-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}
	obj3 := &TestObject{
		ID:  "my-other-cool-thing",
		Foo: "xyz",
		Qux: []string{"xyz1", "xyz2"},
	}

	err := txn1.Insert("main", obj)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj2)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = txn1.Insert("main", obj3)
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Abort the txn
	txn1.Abort()
	txn1.Commit()

	// Create a new transaction
	txn2 := db.Txn(false)

	// Nothing should show up in this transaction
	raw, err := txn2.First("main", "id")
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if raw != nil {
		t.Fatalf("bad: %#v", raw)
	}
}

func TestComplexDB(t *testing.T) {
	db := testComplexDB(t)
	testPopulateData(t, db)
	txn := db.Txn(false) // read only

	// Get using a full name
	raw, err := txn.First("people", "name", "Armon", "Dadgar")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	// Get using a prefix
	raw, err = txn.First("people", "name_prefix", "Armon")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	raw, err = txn.First("people", "id_prefix", raw.(*TestPerson).ID[:4])
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	// Get based on field set.
	result, err := txn.Get("people", "sibling", true)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	exp := map[string]bool{"Alex": true, "Armon": true}
	act := make(map[string]bool, 2)
	for i := result.Next(); i != nil; i = result.Next() {
		p, ok := i.(*TestPerson)
		if !ok {
			t.Fatalf("should get person")
		}
		act[p.First] = true
	}

	if !reflect.DeepEqual(act, exp) {
		t.Fatalf("Got %#v; want %#v", act, exp)
	}

	raw, err = txn.First("people", "sibling", false)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	if raw.(*TestPerson).First != "Mitchell" {
		t.Fatalf("wrong person!")
	}

	// Where in the world is mitchell hashimoto?
	raw, err = txn.First("people", "name_prefix", "Mitchell")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}

	person := raw.(*TestPerson)
	if person.First != "Mitchell" {
		t.Fatalf("wrong person!")
	}

	raw, err = txn.First("visits", "id_prefix", person.ID)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get visit")
	}

	visit := raw.(*TestVisit)

	raw, err = txn.First("places", "id", visit.Place)
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get place")
	}

	place := raw.(*TestPlace)
	if place.Name != "Maui" {
		t.Fatalf("bad place (but isn't anywhere else really?): %v", place)
	}
}

func TestWatchUpdate(t *testing.T) {
	db := testComplexDB(t)
	testPopulateData(t, db)
	txn := db.Txn(false) // read only

	watchSetIter := NewWatchSet()
	watchSetSpecific := NewWatchSet()
	watchSetPrefix := NewWatchSet()

	// Get using an iterator.
	iter, err := txn.Get("people", "name", "Armon", "Dadgar")
	noErr(t, err)
	watchSetIter.Add(iter.WatchCh())
	if raw := iter.Next(); raw == nil {
		t.Fatalf("should get person")
	}

	// Get using a full name.
	watch, raw, err := txn.FirstWatch("people", "name", "Armon", "Dadgar")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	watchSetSpecific.Add(watch)

	// Get using a prefix.
	watch, raw, err = txn.FirstWatch("people", "name_prefix", "Armon")
	noErr(t, err)
	if raw == nil {
		t.Fatalf("should get person")
	}
	watchSetPrefix.Add(watch)

	// Write to a snapshot.
	snap := db.Snapshot()
	txn2 := snap.Txn(true) // write
	noErr(t, txn2.Delete("people", raw))
	txn2.Commit()

	// None of the watches should trigger since we didn't alter the
	// primary.
	wait := 100 * time.Millisecond
	if timeout := watchSetIter.Watch(time.After(wait)); !timeout {
		t.Fatalf("should timeout")
	}
	if timeout := watchSetSpecific.Watch(time.After(wait)); !timeout {
		t.Fatalf("should timeout")
	}
	if timeout := watchSetPrefix.Watch(time.After(wait)); !timeout {
		t.Fatalf("should timeout")
	}

	// Write to the primary.
	txn3 := db.Txn(true) // write
	noErr(t, txn3.Delete("people", raw))
	txn3.Commit()

	// All three watches should trigger!
	wait = time.Second
	if timeout := watchSetIter.Watch(time.After(wait)); timeout {
		t.Fatalf("should not timeout")
	}
	if timeout := watchSetSpecific.Watch(time.After(wait)); timeout {
		t.Fatalf("should not timeout")
	}
	if timeout := watchSetPrefix.Watch(time.After(wait)); timeout {
		t.Fatalf("should not timeout")
	}
}

func testPopulateData(t *testing.T, db *MemDB) {
	// Start write txn
	txn := db.Txn(true)

	// Create some data
	person1 := testPerson()

	person2 := testPerson()
	person2.First = "Mitchell"
	person2.Last = "Hashimoto"

	person3 := testPerson()
	person3.First = "Alex"
	person3.Last = "Dadgar"

	person1.Sibling = person3
	person3.Sibling = person1

	place1 := testPlace()
	place2 := testPlace()
	place2.Name = "Maui"

	visit1 := &TestVisit{person1.ID, place1.ID}
	visit2 := &TestVisit{person2.ID, place2.ID}

	// Insert it all
	noErr(t, txn.Insert("people", person1))
	noErr(t, txn.Insert("people", person2))
	noErr(t, txn.Insert("people", person3))
	noErr(t, txn.Insert("places", place1))
	noErr(t, txn.Insert("places", place2))
	noErr(t, txn.Insert("visits", visit1))
	noErr(t, txn.Insert("visits", visit2))

	// Commit
	txn.Commit()
}

func noErr(t *testing.T, err error) {
	if err != nil {
		t.Fatalf("err: %v", err)
	}
}

type TestPerson struct {
	ID      string
	First   string
	Last    string
	Sibling *TestPerson
}

type TestPlace struct {
	ID   string
	Name string
}

type TestVisit struct {
	Person string
	Place  string
}

func testComplexSchema() *DBSchema {
	return &DBSchema{
		Tables: map[string]*TableSchema{
			"people": &TableSchema{
				Name: "people",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:    "id",
						Unique:  true,
						Indexer: &UUIDFieldIndex{Field: "ID"},
					},
					"name": &IndexSchema{
						Name:   "name",
						Unique: true,
						Indexer: &CompoundIndex{
							Indexes: []Indexer{
								&StringFieldIndex{Field: "First"},
								&StringFieldIndex{Field: "Last"},
							},
						},
					},
					"sibling": &IndexSchema{
						Name:    "sibling",
						Unique:  false,
						Indexer: &FieldSetIndex{Field: "Sibling"},
					},
				},
			},
			"places": &TableSchema{
				Name: "places",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:    "id",
						Unique:  true,
						Indexer: &UUIDFieldIndex{Field: "ID"},
					},
					"name": &IndexSchema{
						Name:    "name",
						Unique:  true,
						Indexer: &StringFieldIndex{Field: "Name"},
					},
				},
			},
			"visits": &TableSchema{
				Name: "visits",
				Indexes: map[string]*IndexSchema{
					"id": &IndexSchema{
						Name:   "id",
						Unique: true,
						Indexer: &CompoundIndex{
							Indexes: []Indexer{
								&UUIDFieldIndex{Field: "Person"},
								&UUIDFieldIndex{Field: "Place"},
							},
						},
					},
				},
			},
		},
	}
}

func testComplexDB(t *testing.T) *MemDB {
	db, err := NewMemDB(testComplexSchema())
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	return db
}

func testPerson() *TestPerson {
	_, uuid := generateUUID()
	obj := &TestPerson{
		ID:    uuid,
		First: "Armon",
		Last:  "Dadgar",
	}
	return obj
}

func testPlace() *TestPlace {
	_, uuid := generateUUID()
	obj := &TestPlace{
		ID:   uuid,
		Name: "HashiCorp",
	}
	return obj
}
<|endoftext|>


<commit_before>package cmagic

// This stuff is in flux.

// This is just an alias - unfortunately aliases in Go do not really work well -
// ie. you have to type cast to and from the original type.
type M map[string]interface{}

type NameSpace interface {
	Collection(name string, entity interface{}) Collection
}

// A Query is a subset of a collection intended to be read
type Query() interface {
	Read()
	ReadOne()
	Asc(bool) Query
	Opt(QueryOptions) Query
	RowOpt()
}

// A Selection is a subset of a collection, 1 or more rows
type Selection interface {
	// Selection modifiers
	Between(from, to) Selection
	GreaterThan(value) Selection
	LesserThan(value) Selection
	Keys([]interface) Selection
	// Operations
	Create(v interface{}) error
	Update(m map[string]interface{}) error  // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	Replace(v interface{}) 					// Replace doesn't make sense on a selection which result in more than 1 document
	Delete(id string) error
}

type Index interface {
	Select(keys []interface{}) Selection
}

type Table interface {
	Index(name string) Selection
	SetIndex()
}

// Job ((driverId), jobId)
// Table

type EqualityIndex interface {
	Equals(key string, value interface{}, opts *QueryOptions) ([]interface{}, error)
}

type TimeSeriesIndex interface {
	//
}

// RowOptions
// See comment aboove 'ReadOpt' method
type RowOptions struct {
	ColumnNames []string
	ColumnStart *string
	ColumnEnd   *string
}

func NewRowOptions() *RowOptions {
	return &RowOptions{
		ColumnNames: []string{},
	}
}

// Set column names to return
func (r *RowOptions) ColNames(ns []string) *RowOptions {
	r.ColumnNames = ns
	return r
}

// Set start of the column names to return
func (r *RowOptions) ColStart(start string) *RowOptions {
	r.ColumnStart = &start
	return r
}

// Set end of the column names to return
func (r *RowOptions) ColEnd(end string) *RowOptions {
	r.ColumnEnd = &end
	return r
}

type QueryOptions struct {
	StartRowId *string
	EndRowId   *string
	RowLimit   *int
}

func NewQueryOptions() *QueryOptions {
	return &QueryOptions{}
}

func (q *QueryOptions) Start(rowId string) *QueryOptions {
	q.StartRowId = &rowId
	return q
}

func (q *QueryOptions) End(rowId string) *QueryOptions {
	q.EndRowId = &rowId
	return q
}
<commit_msg>Examples<commit_after>package cmagic

// This stuff is in flux.

// This is just an alias - unfortunately aliases in Go do not really work well -
// ie. you have to type cast to and from the original type.
type M map[string]interface{}

type KeySpace interface {
	Table(name string, row interface{}) Collection
}

// A Query is a subset of a collection intended to be read
type Query() interface {
	Read()
	ReadOne()
	Asc(bool) Query
	Opt(QueryOptions) Query
	RowOpt()
}

// A Selection is a subset of a collection, 1 or more rows
type Selection interface {
	// Selection modifiers
	Between(from, to) Selection
	GreaterThan(value) Selection
	LesserThan(value) Selection
	Keys([]interface) Selection
	// Operations
	Create(v interface{}) error
	Update(m map[string]interface{}) error  // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	Replace(v interface{}) 					// Replace doesn't make sense on a selection which result in more than 1 document
	Delete(id string) error
}

type Index interface {
	Select(keys []interface{}) Selection
	// ((driverId), jobId) Select(700).Delete()
}

type IndexDef struct {
	Name string
	Keys []string // []string{"Id"}
}

type Table interface {
	Index(name string) Selection
	SetIndex()
	// SetIndex(IndexDef{"crud"}, PartitionKey: []string{"Id"}, CompositeKey: []string{})          -> t.Index("crud").Select(600).Delete()
	// SetIndex(IndexDef{"byDriverId"}, PartitionKey: []{"DriverId"}, CompositeKey: []{"Id"})      -> t.Index("byDriverId").Select(500).Delete()
	// SetIndex(IndexDef{"byCustomerId"}, PartitionKey: []{"CustomerId"}, CompositeKey: []{"Id"})
	// SetIndex()
}

// Job ((driverId), jobId)
// Table

type EqualityIndex interface {
	Equals(key string, value interface{}, opts *QueryOptions) ([]interface{}, error)
}

type TimeSeriesIndex interface {
	//
}

// RowOptions
// See comment aboove 'ReadOpt' method
type RowOptions struct {
	ColumnNames []string
	ColumnStart *string
	ColumnEnd   *string
}

func NewRowOptions() *RowOptions {
	return &RowOptions{
		ColumnNames: []string{},
	}
}

// Set column names to return
func (r *RowOptions) ColNames(ns []string) *RowOptions {
	r.ColumnNames = ns
	return r
}

// Set start of the column names to return
func (r *RowOptions) ColStart(start string) *RowOptions {
	r.ColumnStart = &start
	return r
}

// Set end of the column names to return
func (r *RowOptions) ColEnd(end string) *RowOptions {
	r.ColumnEnd = &end
	return r
}

type QueryOptions struct {
	StartRowId *string
	EndRowId   *string
	RowLimit   *int
}

func NewQueryOptions() *QueryOptions {
	return &QueryOptions{}
}

func (q *QueryOptions) Start(rowId string) *QueryOptions {
	q.StartRowId = &rowId
	return q
}

func (q *QueryOptions) End(rowId string) *QueryOptions {
	q.EndRowId = &rowId
	return q
}
<|endoftext|>


<commit_before>// Ipnow prints the current IP address.
package main

import (
	"errors"
	"fmt"
	"log"
	"net"
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("ipnow: ")

	a, err := ipAddr()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(a)
}

func ipAddr() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("no ip")
}
<commit_msg>ipnow: delete.<commit_after><|endoftext|>


<commit_before>// Copyright 2020 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"fmt"
	"github.com/gogf/gf/container/garray"
	"github.com/gogf/gf/text/gregex"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gutil"
)

var (
	createdFiledNames = []string{"created_at", "create_at"} // Default filed names of table for automatic-filled created datetime.
	updatedFiledNames = []string{"updated_at", "update_at"} // Default filed names of table for automatic-filled updated datetime.
	deletedFiledNames = []string{"deleted_at", "delete_at"} // Default filed names of table for automatic-filled deleted datetime.
)

// Unscoped disables the auto-update time feature for insert, update and delete options.
func (m *Model) Unscoped() *Model {
	model := m.getModel()
	model.unscoped = true
	return model
}

// getSoftFieldNameCreate checks and returns the field name for record creating time.
// If there's no field name for storing creating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameCreated(table ...string) string {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.CreatedAt != "" {
		return m.getSoftFieldName(tableName, append([]string{config.CreatedAt}, createdFiledNames...))
	}
	return m.getSoftFieldName(tableName, createdFiledNames)
}

// getSoftFieldNameUpdate checks and returns the field name for record updating time.
// If there's no field name for storing updating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameUpdated(table ...string) (field string) {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.UpdatedAt != "" {
		return m.getSoftFieldName(tableName, append([]string{config.UpdatedAt}, updatedFiledNames...))
	}
	return m.getSoftFieldName(tableName, updatedFiledNames)
}

// getSoftFieldNameDelete checks and returns the field name for record deleting time.
// If there's no field name for storing deleting time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameDeleted(table ...string) (field string) {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.UpdatedAt != "" {
		return m.getSoftFieldName(tableName, append([]string{config.DeletedAt}, deletedFiledNames...))
	}
	return m.getSoftFieldName(tableName, deletedFiledNames)
}

// getSoftFieldName retrieves and returns the field name of the table for possible key.
func (m *Model) getSoftFieldName(table string, keys []string) (field string) {
	fieldsMap, _ := m.db.TableFields(table)
	if len(fieldsMap) > 0 {
		for _, key := range keys {
			field, _ = gutil.MapPossibleItemByKey(
				gconv.Map(fieldsMap), key,
			)
			if field != "" {
				return
			}
		}
	}
	return
}

// getConditionForSoftDeleting retrieves and returns the condition string for soft deleting.
// It supports multiple tables string like:
// "user u, user_detail ud"
// "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid)"
// "user LEFT JOIN user_detail ON(user_detail.uid=user.uid)"
// "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid) LEFT JOIN user_stats us ON(us.uid=u.uid)"
func (m *Model) getConditionForSoftDeleting() string {
	if m.unscoped {
		return ""
	}
	conditionArray := garray.NewStrArray()
	if gstr.Contains(m.tables, " JOIN ") {
		// Base table.
		match, _ := gregex.MatchString(`(.+?) [A-Z]+ JOIN`, m.tables)
		conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
		// Multiple joined tables, exclude the sub query sql which contains char '(' and ')'.
		matches, _ := gregex.MatchAllString(`JOIN ([^()]+?) ON`, m.tables)
		for _, match := range matches {
			conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
		}
	}
	if conditionArray.Len() == 0 && gstr.Contains(m.tables, ",") {
		// Multiple base tables.
		for _, s := range gstr.SplitAndTrim(m.tables, ",") {
			conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(s))
		}
	}
	conditionArray.FilterEmpty()
	if conditionArray.Len() > 0 {
		return conditionArray.Join(" AND ")
	}
	// Only one table.
	if fieldName := m.getSoftFieldNameDeleted(); fieldName != "" {
		return fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(fieldName))
	}
	return ""
}

// getConditionOfTableStringForSoftDeleting does something as its name describes.
func (m *Model) getConditionOfTableStringForSoftDeleting(s string) string {
	var (
		field  = ""
		table  = ""
		array1 = gstr.SplitAndTrim(s, " ")
		array2 = gstr.SplitAndTrim(array1[0], ".")
	)
	if len(array2) >= 2 {
		table = array2[1]
	} else {
		table = array2[0]
	}
	field = m.getSoftFieldNameDeleted(table)
	if field == "" {
		return ""
	}
	if len(array1) >= 3 {
		return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[2]), m.db.QuoteWord(field))
	}
	if len(array1) >= 2 {
		return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[1]), m.db.QuoteWord(field))
	}
	return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(table), m.db.QuoteWord(field))
}

// getPrimaryTableName parses and returns the primary table name.
func (m *Model) getPrimaryTableName() string {
	array1 := gstr.SplitAndTrim(m.tables, ",")
	array2 := gstr.SplitAndTrim(array1[0], " ")
	array3 := gstr.SplitAndTrim(array2[0], ".")
	if len(array3) >= 2 {
		return array3[1]
	}
	return array3[0]
}
<commit_msg>if CreatedAt/UpdatedAt/DeletedAt field name configured, just use it, ignore the default field names<commit_after>// Copyright 2020 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"fmt"
	"github.com/gogf/gf/container/garray"
	"github.com/gogf/gf/text/gregex"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gutil"
)

var (
	createdFiledNames = []string{"created_at", "create_at"} // Default filed names of table for automatic-filled created datetime.
	updatedFiledNames = []string{"updated_at", "update_at"} // Default filed names of table for automatic-filled updated datetime.
	deletedFiledNames = []string{"deleted_at", "delete_at"} // Default filed names of table for automatic-filled deleted datetime.
)

// Unscoped disables the auto-update time feature for insert, update and delete options.
func (m *Model) Unscoped() *Model {
	model := m.getModel()
	model.unscoped = true
	return model
}

// getSoftFieldNameCreate checks and returns the field name for record creating time.
// If there's no field name for storing creating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameCreated(table ...string) string {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.CreatedAt != "" {
		return m.getSoftFieldName(tableName, []string{config.CreatedAt})
	}
	return m.getSoftFieldName(tableName, createdFiledNames)
}

// getSoftFieldNameUpdate checks and returns the field name for record updating time.
// If there's no field name for storing updating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameUpdated(table ...string) (field string) {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.UpdatedAt != "" {
		return m.getSoftFieldName(tableName, []string{config.UpdatedAt})
	}
	return m.getSoftFieldName(tableName, updatedFiledNames)
}

// getSoftFieldNameDelete checks and returns the field name for record deleting time.
// If there's no field name for storing deleting time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameDeleted(table ...string) (field string) {
	tableName := ""
	if len(table) > 0 {
		tableName = table[0]
	} else {
		tableName = m.getPrimaryTableName()
	}
	config := m.db.GetConfig()
	if config.UpdatedAt != "" {
		return m.getSoftFieldName(tableName, []string{config.DeletedAt})
	}
	return m.getSoftFieldName(tableName, deletedFiledNames)
}

// getSoftFieldName retrieves and returns the field name of the table for possible key.
func (m *Model) getSoftFieldName(table string, keys []string) (field string) {
	fieldsMap, _ := m.db.TableFields(table)
	if len(fieldsMap) > 0 {
		for _, key := range keys {
			field, _ = gutil.MapPossibleItemByKey(
				gconv.Map(fieldsMap), key,
			)
			if field != "" {
				return
			}
		}
	}
	return
}

// getConditionForSoftDeleting retrieves and returns the condition string for soft deleting.
// It supports multiple tables string like:
// "user u, user_detail ud"
// "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid)"
// "user LEFT JOIN user_detail ON(user_detail.uid=user.uid)"
// "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid) LEFT JOIN user_stats us ON(us.uid=u.uid)"
func (m *Model) getConditionForSoftDeleting() string {
	if m.unscoped {
		return ""
	}
	conditionArray := garray.NewStrArray()
	if gstr.Contains(m.tables, " JOIN ") {
		// Base table.
		match, _ := gregex.MatchString(`(.+?) [A-Z]+ JOIN`, m.tables)
		conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
		// Multiple joined tables, exclude the sub query sql which contains char '(' and ')'.
		matches, _ := gregex.MatchAllString(`JOIN ([^()]+?) ON`, m.tables)
		for _, match := range matches {
			conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
		}
	}
	if conditionArray.Len() == 0 && gstr.Contains(m.tables, ",") {
		// Multiple base tables.
		for _, s := range gstr.SplitAndTrim(m.tables, ",") {
			conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(s))
		}
	}
	conditionArray.FilterEmpty()
	if conditionArray.Len() > 0 {
		return conditionArray.Join(" AND ")
	}
	// Only one table.
	if fieldName := m.getSoftFieldNameDeleted(); fieldName != "" {
		return fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(fieldName))
	}
	return ""
}

// getConditionOfTableStringForSoftDeleting does something as its name describes.
func (m *Model) getConditionOfTableStringForSoftDeleting(s string) string {
	var (
		field  = ""
		table  = ""
		array1 = gstr.SplitAndTrim(s, " ")
		array2 = gstr.SplitAndTrim(array1[0], ".")
	)
	if len(array2) >= 2 {
		table = array2[1]
	} else {
		table = array2[0]
	}
	field = m.getSoftFieldNameDeleted(table)
	if field == "" {
		return ""
	}
	if len(array1) >= 3 {
		return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[2]), m.db.QuoteWord(field))
	}
	if len(array1) >= 2 {
		return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[1]), m.db.QuoteWord(field))
	}
	return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(table), m.db.QuoteWord(field))
}

// getPrimaryTableName parses and returns the primary table name.
func (m *Model) getPrimaryTableName() string {
	array1 := gstr.SplitAndTrim(m.tables, ",")
	array2 := gstr.SplitAndTrim(array1[0], " ")
	array3 := gstr.SplitAndTrim(array2[0], ".")
	if len(array3) >= 2 {
		return array3[1]
	}
	return array3[0]
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/engine"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
	"github.com/docker/docker/pkg/parsers"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libcontainer/label"
)

func (daemon *Daemon) ContainerCreate(job *engine.Job) engine.Status {
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx contanercreate called 111111111")
	out := engine.NewOutput()
	remoteInfo, _ := out.AddEnv()
	logrus.Debugf(remoteInfo.GetInt("Containers"))
	remoteInfo.GetInt("Containers")
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx contanercreate called22222222222")
	var name string
	if len(job.Args) == 1 {
		name = job.Args[0]
	} else if len(job.Args) > 1 {
		return job.Errorf("Usage: %s", job.Name)
	}
	config := runconfig.ContainerConfigFromJob(job)
	if config.Memory != 0 && config.Memory < 4194304 {
		return job.Errorf("Minimum memory limit allowed is 4MB")
	}
	if config.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
		job.Errorf("Your kernel does not support memory limit capabilities. Limitation discarded.\n")
		config.Memory = 0
	}
	if config.Memory > 0 && !daemon.SystemConfig().SwapLimit {
		job.Errorf("Your kernel does not support swap limit capabilities. Limitation discarded.\n")
		config.MemorySwap = -1
	}

	var hostConfig *runconfig.HostConfig
	if job.EnvExists("HostConfig") {
		hostConfig = runconfig.ContainerHostConfigFromJob(job)
	} else {
		// Older versions of the API don't provide a HostConfig.
		hostConfig = nil
	}

	container, buildWarnings, err := daemon.Create(config, hostConfig, name)
	if err != nil {
		if daemon.Graph().IsNotExist(err) {
			_, tag := parsers.ParseRepositoryTag(config.Image)
			if tag == "" {
				tag = graph.DEFAULTTAG
			}
			return job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
		}
		return job.Error(err)
	}
	if !container.Config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
		job.Errorf("IPv4 forwarding is disabled.\n")
	}
	container.LogEvent("create")

	job.Printf("%s\n", container.ID)

	for _, warning := range buildWarnings {
		job.Errorf("%s\n", warning)
	}

	return engine.StatusOK
}

// Create creates a new container from the given configuration with a given name.
func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx create called inside of daemon package")
	var (
		container *Container
		warnings  []string
		img       *image.Image
		imgID     string
		err       error
	)

	if config.Image != "" {
		img, err = daemon.repositories.LookupImage(config.Image)
		if err != nil {
			return nil, nil, err
		}
		if err = img.CheckDepth(); err != nil {
			return nil, nil, err
		}
		imgID = img.ID
	}

	if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
		return nil, nil, err
	}
	if hostConfig != nil && hostConfig.SecurityOpt == nil {
		hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode)
		if err != nil {
			return nil, nil, err
		}
	}
	if container, err = daemon.newContainer(name, config, imgID); err != nil {
		return nil, nil, err
	}
	if err := daemon.Register(container); err != nil {
		return nil, nil, err
	}
	if err := daemon.createRootfs(container); err != nil {
		return nil, nil, err
	}
	if hostConfig != nil {
		if err := daemon.setHostConfig(container, hostConfig); err != nil {
			return nil, nil, err
		}
	}
	if err := container.Mount(); err != nil {
		return nil, nil, err
	}
	defer container.Unmount()
	if err := container.prepareVolumes(); err != nil {
		return nil, nil, err
	}
	if err := container.ToDisk(); err != nil {
		return nil, nil, err
	}
	return container, warnings, nil
}

func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode) ([]string, error) {
	if ipcMode.IsHost() {
		return label.DisableSecOpt(), nil
	}
	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
		c := daemon.Get(ipcContainer)
		if c == nil {
			return nil, fmt.Errorf("no such container to join IPC: %s", ipcContainer)
		}
		if !c.IsRunning() {
			return nil, fmt.Errorf("cannot join IPC of a non running container: %s", ipcContainer)
		}

		return label.DupSecOpt(c.ProcessLabel), nil
	}
	return nil, nil
}
<commit_msg>changed<commit_after>package daemon

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/engine"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
	"github.com/docker/docker/pkg/parsers"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libcontainer/label"
)

func (daemon *Daemon) ContainerCreate(job *engine.Job) engine.Status {
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx contanercreate called 111111111")
	out := engine.NewOutput()
	remoteInfo, _ := out.AddEnv()
	NumberofContaienrs := remoteInfo.GetInt("Containers")
	remoteInfo.GetInt("Containers")
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx contanercreate called22222222222")
	var name string
	if len(job.Args) == 1 {
		name = job.Args[0]
	} else if len(job.Args) > 1 {
		return job.Errorf("Usage: %s", job.Name)
	}
	config := runconfig.ContainerConfigFromJob(job)
	if config.Memory != 0 && config.Memory < 4194304 {
		return job.Errorf("Minimum memory limit allowed is 4MB")
	}
	if config.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
		job.Errorf("Your kernel does not support memory limit capabilities. Limitation discarded.\n")
		config.Memory = 0
	}
	if config.Memory > 0 && !daemon.SystemConfig().SwapLimit {
		job.Errorf("Your kernel does not support swap limit capabilities. Limitation discarded.\n")
		config.MemorySwap = -1
	}

	var hostConfig *runconfig.HostConfig
	if job.EnvExists("HostConfig") {
		hostConfig = runconfig.ContainerHostConfigFromJob(job)
	} else {
		// Older versions of the API don't provide a HostConfig.
		hostConfig = nil
	}

	container, buildWarnings, err := daemon.Create(config, hostConfig, name)
	if err != nil {
		if daemon.Graph().IsNotExist(err) {
			_, tag := parsers.ParseRepositoryTag(config.Image)
			if tag == "" {
				tag = graph.DEFAULTTAG
			}
			return job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
		}
		return job.Error(err)
	}
	if !container.Config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
		job.Errorf("IPv4 forwarding is disabled.\n")
	}
	container.LogEvent("create")

	job.Printf("%s\n", container.ID)

	for _, warning := range buildWarnings {
		job.Errorf("%s\n", warning)
	}

	return engine.StatusOK
}

// Create creates a new container from the given configuration with a given name.
func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
	logrus.Debugf("xxxxxxxxxxxxxxxxxxxxxxxxxxxx create called inside of daemon package")
	var (
		container *Container
		warnings  []string
		img       *image.Image
		imgID     string
		err       error
	)

	if config.Image != "" {
		img, err = daemon.repositories.LookupImage(config.Image)
		if err != nil {
			return nil, nil, err
		}
		if err = img.CheckDepth(); err != nil {
			return nil, nil, err
		}
		imgID = img.ID
	}

	if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
		return nil, nil, err
	}
	if hostConfig != nil && hostConfig.SecurityOpt == nil {
		hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode)
		if err != nil {
			return nil, nil, err
		}
	}
	if container, err = daemon.newContainer(name, config, imgID); err != nil {
		return nil, nil, err
	}
	if err := daemon.Register(container); err != nil {
		return nil, nil, err
	}
	if err := daemon.createRootfs(container); err != nil {
		return nil, nil, err
	}
	if hostConfig != nil {
		if err := daemon.setHostConfig(container, hostConfig); err != nil {
			return nil, nil, err
		}
	}
	if err := container.Mount(); err != nil {
		return nil, nil, err
	}
	defer container.Unmount()
	if err := container.prepareVolumes(); err != nil {
		return nil, nil, err
	}
	if err := container.ToDisk(); err != nil {
		return nil, nil, err
	}
	return container, warnings, nil
}

func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode) ([]string, error) {
	if ipcMode.IsHost() {
		return label.DisableSecOpt(), nil
	}
	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
		c := daemon.Get(ipcContainer)
		if c == nil {
			return nil, fmt.Errorf("no such container to join IPC: %s", ipcContainer)
		}
		if !c.IsRunning() {
			return nil, fmt.Errorf("cannot join IPC of a non running container: %s", ipcContainer)
		}

		return label.DupSecOpt(c.ProcessLabel), nil
	}
	return nil, nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"github.com/bitly/go-simplejson"
	"github.com/nytlabs/streamtools/blocks"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

const (
	READ_MAX = 1024768
)

var (
	// channel that returns the next ID
	idChan chan string
)

// Daemon keeps track of all the blocks and connections
type Daemon struct {
	blockMap map[string]*blocks.Block
}

// The rootHandler returns information about the whole system
func (d *Daemon) rootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello! this is streamtools")
	fmt.Fprintln(w, "ID: BlockType")
	for id, block := range d.blockMap {
		fmt.Fprintln(w, id+":", block.BlockType)
	}
}

// The createHandler creates new blocks
func (d *Daemon) createHandler(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	var id string
	var blockType string
	fType, typeExists := r.Form["blockType"]
	fID, idExists := r.Form["id"]

	if typeExists == false {
		ApiResponse(w, 500, "MISSING_BLOCKTYPE")
		return
	} else {
		blockType = fType[0]
	}

	_, inLibrary := blocks.Library[blockType]
	if inLibrary == false {
		ApiResponse(w, 500, "INVALID_BLOCKTYPE")
		return
	}

	if idExists == false {
		id = <-idChan
	} else {
		_, notUnique := d.blockMap[fID[0]]
		if notUnique == true {
			ApiResponse(w, 500, "BLOCK_ID_ALREADY_EXISTS")
			return
		} else {
			id = fID[0]
		}
	}

	d.CreateBlock(blockType, id)

	ApiResponse(w, 200, "BLOCK_CREATED")
}

// The connectHandler connects together two blocks
func (d *Daemon) connectHandler(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	from := r.Form["from"][0]
	to := r.Form["to"][0]

	if len(from) == 0 {
		ApiResponse(w, 500, "MISSING_FROM_BLOCK_ID")
		return
	}

	if len(to) == 0 {
		ApiResponse(w, 500, "MISSING_TO_BLOCK_ID")
		return
	}

	_, exists := d.blockMap[from]
	if exists == false {
		ApiResponse(w, 500, "FROM_BLOCK_NOT_FOUND")
		return
	}

	_, exists = d.blockMap[to]
	if exists == false {
		ApiResponse(w, 500, "TO_BLOCK_NOT_FOUND")
		return
	}

	d.CreateConnection(from, to)

	ApiResponse(w, 200, "CONNECTION_CREATED")
}

// The routeHandler deals with any incoming message sent to an arbitrary block endpoint
func (d *Daemon) routeHandler(w http.ResponseWriter, r *http.Request) {
	id := strings.Split(r.URL.Path, "/")[2]
	route := strings.Split(r.URL.Path, "/")[3]
	msg, err := ioutil.ReadAll(io.LimitReader(r.Body, READ_MAX))

	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	ResponseChan := make(chan []byte)
	blockRouteChan := d.blockMap[id].Routes[route]
	blockRouteChan <- blocks.RouteResponse{
		Msg:          msg,
		ResponseChan: ResponseChan,
	}
	respMsg := <-ResponseChan

	DataResponse(w, respMsg)
}

func (d *Daemon) libraryHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "libraryBlob")
}

func (d *Daemon) createRoutes(b *blocks.Block) {
	for _, routeName := range blocks.Library[b.BlockType].RouteNames {
		log.Println("creating route /blocks/" + b.ID + "/" + routeName)
		http.HandleFunc("/blocks/"+b.ID+"/"+routeName, d.routeHandler)
	}
}

func (d *Daemon) CreateConnection(from string, to string) {
	ID := <-idChan
	d.CreateBlock("connection", ID)

	d.blockMap[from].AddChan <- &blocks.OutChanMsg{
		Action:  blocks.CREATE_OUT_CHAN,
		OutChan: d.blockMap[ID].InChan,
		ID:      ID,
	}

	d.blockMap[ID].AddChan <- &blocks.OutChanMsg{
		Action:  blocks.CREATE_OUT_CHAN,
		OutChan: d.blockMap[to].InChan,
		ID:      to,
	}
	log.Println("connected", d.blockMap[from].ID, "to", d.blockMap[to].ID)
}

func (d *Daemon) CreateBlock(name string, ID string) {
	// TODO: Clean this up.
	//
	// In order to avoid data races the blocks held in daemon's blockMap
	// are not the same blocks held in each block routine. When CreateBlock
	// is called, we actually create two blocks: one to store in daemon's
	// blockMap and one to send to the block routine.
	//
	// The block stored in daemon's blockmap doesn't make use of OutChans as
	// a block's OutChans can be dynamically modified when connections are
	// added or deleted. All of the other fields, such as ID, name, and all
	// the channels that go into the block (inChan, Routes) are the SAME
	// in both the daemon blockMap block and the blockroutine block.
	//
	// Becauase of this very minor difference it would be a huge semantic help
	// if the type going to the blockroutines was actually different than the
	// type being kept in daemon's blockmap.
	//
	// Modifications to blocks in daemon's blockMap will obviously not
	// proliferate to blockroutines and all changes (such as adding outchans)
	// can only be done through messages. A future daemon block type might
	// want to restrict how daemon blocks can be used, such as creating
	// getters and no setters. Or perhaps a setter automatically takes care
	// of sending a message to the blockroutine to emulate the manipulation
	// of a single variable.

	// create the block that will be stored in blockMap
	b, _ := blocks.NewBlock(name, ID)
	d.createRoutes(b)
	d.blockMap[b.ID] = b

	// create the block that will be sent to the blockroutine and copy all
	// chan references from the previously created block
	c, _ := blocks.NewBlock(name, ID)
	for k, v := range b.Routes {
		c.Routes[k] = v
	}

	c.InChan = b.InChan
	c.AddChan = b.AddChan

	//create outchans for use only by blockroutine block.
	c.OutChans = make(map[string]chan *simplejson.Json)

	go blocks.Library[name].Routine(c)

	log.Println("started block \"" + ID + "\" of type " + name)
}

func (d *Daemon) Run(port string) {

	// start the ID Service
	idChan = make(chan string)
	go IDService(idChan)

	// start the library service
	blocks.BuildLibrary()

	// initialise the block maps
	d.blockMap = make(map[string]*blocks.Block)

	// instantiate the base handlers
	http.HandleFunc("/", d.rootHandler)
	http.HandleFunc("/create", d.createHandler)
	http.HandleFunc("/connect", d.connectHandler)
	http.HandleFunc("/library", d.libraryHandler)

	// start the http server
	log.Println("starting stream tools on port", port)
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		log.Fatalf(err.Error())
	}
}
<commit_msg>fixing #76<commit_after>package daemon

import (
	"fmt"
	"github.com/bitly/go-simplejson"
	"github.com/nytlabs/streamtools/blocks"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

const (
	READ_MAX = 1024768
)

var (
	// channel that returns the next ID
	idChan chan string
)

// Daemon keeps track of all the blocks and connections
type Daemon struct {
	blockMap map[string]*blocks.Block
}

// The rootHandler returns information about the whole system
func (d *Daemon) rootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello! this is streamtools")
	fmt.Fprintln(w, "ID: BlockType")
	for id, block := range d.blockMap {
		fmt.Fprintln(w, id+":", block.BlockType)
	}
}

// The createHandler creates new blocks
func (d *Daemon) createHandler(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	var id string
	var blockType string
	fType, typeExists := r.Form["blockType"]
	fID, idExists := r.Form["id"]

	if typeExists == false {
		ApiResponse(w, 500, "MISSING_BLOCKTYPE")
		return
	} else {
		blockType = fType[0]
	}

	_, inLibrary := blocks.Library[blockType]
	if inLibrary == false {
		ApiResponse(w, 500, "INVALID_BLOCKTYPE")
		return
	}

	if idExists == false {
		id = <-idChan
	} else {
		_, notUnique := d.blockMap[fID[0]]
		if notUnique == true {
			ApiResponse(w, 500, "BLOCK_ID_ALREADY_EXISTS")
			return
		} else {
			id = fID[0]
		}
	}

	d.CreateBlock(blockType, id)

	ApiResponse(w, 200, "BLOCK_CREATED")
}

// The connectHandler connects together two blocks
func (d *Daemon) connectHandler(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	_, hasFrom := r.Form["from"]
	if hasFrom == false {
		ApiResponse(w, 500, "MISSING_FROM_BLOCK_ID")
		return
	}

	_, hasTo := r.Form["to"]
	if hasTo == false {
		ApiResponse(w, 500, "MISSING_TO_BLOCK_ID")
		return
	}

	from := r.Form["from"][0]
	to := r.Form["to"][0]

	if len(from) == 0 {
		ApiResponse(w, 500, "MISSING_FROM_BLOCK_ID")
		return
	}

	if len(to) == 0 {
		ApiResponse(w, 500, "MISSING_TO_BLOCK_ID")
		return
	}

	_, exists := d.blockMap[from]
	if exists == false {
		ApiResponse(w, 500, "FROM_BLOCK_NOT_FOUND")
		return
	}

	_, exists = d.blockMap[to]
	if exists == false {
		ApiResponse(w, 500, "TO_BLOCK_NOT_FOUND")
		return
	}

	d.CreateConnection(from, to)

	ApiResponse(w, 200, "CONNECTION_CREATED")
}

// The routeHandler deals with any incoming message sent to an arbitrary block endpoint
func (d *Daemon) routeHandler(w http.ResponseWriter, r *http.Request) {
	id := strings.Split(r.URL.Path, "/")[2]
	route := strings.Split(r.URL.Path, "/")[3]
	msg, err := ioutil.ReadAll(io.LimitReader(r.Body, READ_MAX))

	if err != nil {
		ApiResponse(w, 500, "BAD_REQUEST")
		return
	}

	ResponseChan := make(chan []byte)
	blockRouteChan := d.blockMap[id].Routes[route]
	blockRouteChan <- blocks.RouteResponse{
		Msg:          msg,
		ResponseChan: ResponseChan,
	}
	respMsg := <-ResponseChan

	DataResponse(w, respMsg)
}

func (d *Daemon) libraryHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "libraryBlob")
}

func (d *Daemon) createRoutes(b *blocks.Block) {
	for _, routeName := range blocks.Library[b.BlockType].RouteNames {
		log.Println("creating route /blocks/" + b.ID + "/" + routeName)
		http.HandleFunc("/blocks/"+b.ID+"/"+routeName, d.routeHandler)
	}
}

func (d *Daemon) CreateConnection(from string, to string) {
	ID := <-idChan
	d.CreateBlock("connection", ID)

	d.blockMap[from].AddChan <- &blocks.OutChanMsg{
		Action:  blocks.CREATE_OUT_CHAN,
		OutChan: d.blockMap[ID].InChan,
		ID:      ID,
	}

	d.blockMap[ID].AddChan <- &blocks.OutChanMsg{
		Action:  blocks.CREATE_OUT_CHAN,
		OutChan: d.blockMap[to].InChan,
		ID:      to,
	}
	log.Println("connected", d.blockMap[from].ID, "to", d.blockMap[to].ID)
}

func (d *Daemon) CreateBlock(name string, ID string) {
	// TODO: Clean this up.
	//
	// In order to avoid data races the blocks held in daemon's blockMap
	// are not the same blocks held in each block routine. When CreateBlock
	// is called, we actually create two blocks: one to store in daemon's
	// blockMap and one to send to the block routine.
	//
	// The block stored in daemon's blockmap doesn't make use of OutChans as
	// a block's OutChans can be dynamically modified when connections are
	// added or deleted. All of the other fields, such as ID, name, and all
	// the channels that go into the block (inChan, Routes) are the SAME
	// in both the daemon blockMap block and the blockroutine block.
	//
	// Becauase of this very minor difference it would be a huge semantic help
	// if the type going to the blockroutines was actually different than the
	// type being kept in daemon's blockmap.
	//
	// Modifications to blocks in daemon's blockMap will obviously not
	// proliferate to blockroutines and all changes (such as adding outchans)
	// can only be done through messages. A future daemon block type might
	// want to restrict how daemon blocks can be used, such as creating
	// getters and no setters. Or perhaps a setter automatically takes care
	// of sending a message to the blockroutine to emulate the manipulation
	// of a single variable.

	// create the block that will be stored in blockMap
	b, _ := blocks.NewBlock(name, ID)
	d.createRoutes(b)
	d.blockMap[b.ID] = b

	// create the block that will be sent to the blockroutine and copy all
	// chan references from the previously created block
	c, _ := blocks.NewBlock(name, ID)
	for k, v := range b.Routes {
		c.Routes[k] = v
	}

	c.InChan = b.InChan
	c.AddChan = b.AddChan

	//create outchans for use only by blockroutine block.
	c.OutChans = make(map[string]chan *simplejson.Json)

	go blocks.Library[name].Routine(c)

	log.Println("started block \"" + ID + "\" of type " + name)
}

func (d *Daemon) Run(port string) {

	// start the ID Service
	idChan = make(chan string)
	go IDService(idChan)

	// start the library service
	blocks.BuildLibrary()

	// initialise the block maps
	d.blockMap = make(map[string]*blocks.Block)

	// instantiate the base handlers
	http.HandleFunc("/", d.rootHandler)
	http.HandleFunc("/create", d.createHandler)
	http.HandleFunc("/connect", d.connectHandler)
	http.HandleFunc("/library", d.libraryHandler)

	// start the http server
	log.Println("starting stream tools on port", port)
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		log.Fatalf(err.Error())
	}
}
<|endoftext|>