<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"
	"path/filepath"

	"github.com/OpenBazaar/openbazaar-go/cmd"
	"github.com/OpenBazaar/openbazaar-go/core"
	"github.com/ipfs/go-ipfs/repo/fsrepo"
	"github.com/jessevdk/go-flags"
	"github.com/op/go-logging"
)

var log = logging.MustGetLogger("main")

type Opts struct {
	Version bool `short:"v" long:"version" description:"Print the version number and exit"`
}

var opts Opts

var parser = flags.NewParser(&opts, flags.Default)

func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			log.Noticef("Received %s\n", sig)
			log.Info("OpenBazaar Server shutting down...")
			if core.Node != nil {
				if core.Node.MessageRetriever != nil {
					core.Node.RecordAgingNotifier.Stop()
					close(core.Node.MessageRetriever.DoneChan)
					core.Node.MessageRetriever.Wait()
				}
				core.OfflineMessageWaitGroup.Wait()
				core.PublishLock.Lock()
				core.Node.Datastore.Close()
				repoLockFile := filepath.Join(core.Node.RepoPath, fsrepo.LockFile)
				os.Remove(repoLockFile)
				core.Node.Multiwallet.Close()
				core.Node.IpfsNode.Close()
			}
			os.Exit(1)
		}
	}()

	parser.AddCommand("gencerts",
		"Generate certificates",
		"Generate self-singned certificates",
		&cmd.GenerateCertificates{})
	parser.AddCommand("init",
		"initialize a new repo and exit",
		"Initializes a new repo without starting the server",
		&cmd.Init{})
	parser.AddCommand("status",
		"get the repo status",
		"Returns the status of the repo ― Uninitialized, Encrypted, Decrypted. Also returns whether Tor is available.",
		&cmd.Status{})
	parser.AddCommand("setapicreds",
		"set API credentials",
		"The API password field in the config file takes a SHA256 hash of the password. This command will generate the hash for you and save it to the config file.",
		&cmd.SetAPICreds{})
	parser.AddCommand("start",
		"start the OpenBazaar-Server",
		"The start command starts the OpenBazaar-Server",
		&cmd.Start{})
	parser.AddCommand("encryptdatabase",
		"encrypt your database",
		"This command encrypts the database containing your bitcoin private keys, identity key, and contracts",
		&cmd.EncryptDatabase{})
	parser.AddCommand("decryptdatabase",
		"decrypt your database",
		"This command decrypts the database containing your bitcoin private keys, identity key, and contracts.\n [Warning] doing so may put your bitcoins at risk.",
		&cmd.DecryptDatabase{})
	parser.AddCommand("restore",
		"restore user data",
		"This command will attempt to restore user data (profile, listings, ratings, etc) by downloading them from the network. This will only work if the IPNS mapping is still available in the DHT. Optionally it will take a mnemonic seed to restore from.",
		&cmd.Restore{})
	parser.AddCommand("convert",
		"convert this node to a different coin type",
		"This command will convert the node to use a different cryptocurrency",
		&cmd.Convert{})
	if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-v") {
		fmt.Println(core.VERSION)
		return
	}
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}
}
<commit_msg>Fix publish lock in openbazaard.go<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"
	"path/filepath"

	"github.com/OpenBazaar/openbazaar-go/cmd"
	"github.com/OpenBazaar/openbazaar-go/core"
	"github.com/ipfs/go-ipfs/repo/fsrepo"
	"github.com/jessevdk/go-flags"
	"github.com/op/go-logging"
)

var log = logging.MustGetLogger("main")

type Opts struct {
	Version bool `short:"v" long:"version" description:"Print the version number and exit"`
}

var opts Opts

var parser = flags.NewParser(&opts, flags.Default)

func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			log.Noticef("Received %s\n", sig)
			log.Info("OpenBazaar Server shutting down...")
			if core.Node != nil {
				if core.Node.MessageRetriever != nil {
					core.Node.RecordAgingNotifier.Stop()
					close(core.Node.MessageRetriever.DoneChan)
					core.Node.MessageRetriever.Wait()
				}
				core.OfflineMessageWaitGroup.Wait()
				core.Node.PublishLock.Lock()
				core.Node.Datastore.Close()
				repoLockFile := filepath.Join(core.Node.RepoPath, fsrepo.LockFile)
				os.Remove(repoLockFile)
				core.Node.Multiwallet.Close()
				core.Node.IpfsNode.Close()
			}
			os.Exit(1)
		}
	}()

	parser.AddCommand("gencerts",
		"Generate certificates",
		"Generate self-singned certificates",
		&cmd.GenerateCertificates{})
	parser.AddCommand("init",
		"initialize a new repo and exit",
		"Initializes a new repo without starting the server",
		&cmd.Init{})
	parser.AddCommand("status",
		"get the repo status",
		"Returns the status of the repo ― Uninitialized, Encrypted, Decrypted. Also returns whether Tor is available.",
		&cmd.Status{})
	parser.AddCommand("setapicreds",
		"set API credentials",
		"The API password field in the config file takes a SHA256 hash of the password. This command will generate the hash for you and save it to the config file.",
		&cmd.SetAPICreds{})
	parser.AddCommand("start",
		"start the OpenBazaar-Server",
		"The start command starts the OpenBazaar-Server",
		&cmd.Start{})
	parser.AddCommand("encryptdatabase",
		"encrypt your database",
		"This command encrypts the database containing your bitcoin private keys, identity key, and contracts",
		&cmd.EncryptDatabase{})
	parser.AddCommand("decryptdatabase",
		"decrypt your database",
		"This command decrypts the database containing your bitcoin private keys, identity key, and contracts.\n [Warning] doing so may put your bitcoins at risk.",
		&cmd.DecryptDatabase{})
	parser.AddCommand("restore",
		"restore user data",
		"This command will attempt to restore user data (profile, listings, ratings, etc) by downloading them from the network. This will only work if the IPNS mapping is still available in the DHT. Optionally it will take a mnemonic seed to restore from.",
		&cmd.Restore{})
	parser.AddCommand("convert",
		"convert this node to a different coin type",
		"This command will convert the node to use a different cryptocurrency",
		&cmd.Convert{})
	if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-v") {
		fmt.Println(core.VERSION)
		return
	}
	if _, err := parser.Parse(); err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package pack

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

type pointer struct {
	addr reflect.Value
	ttype reflect.Type

}

func (p *pointer) Set(val interface{}) {
	po := *p
	switch vv := val.(type) {
	case string:
		fmt.Println("is string", vv)
		po.addr.SetString(vv)
	case int:
		po.addr.SetInt(int64(vv))
	case float64:
		po.addr.SetFloat(vv)
	case bool:
		po.addr.SetBool(vv)
	case []interface{}:

	default:
		fmt.Println("todo feature")
	}
}

func Packer(b *[]byte, class interface{}) {

	v := reflect.ValueOf(class)

	indirect_type := reflect.Indirect(v).Type()

	//store addr
	name_addr := make(map[string]pointer)
	el := v.Elem()
	for i := 0; i < el.NumField(); i++ {
		name_addr[indirect_type.Field(i).Name] =
			pointer{v.Elem().Field(i), indirect_type}
	}

	var f interface{}
	json.Unmarshal(*b, &f)
	m := f.(map[string]interface{})

	for k, v := range m {
		if q, ok := name_addr[k]; ok {
			p := &q
			p.Set(v)
		}
	}
}
<commit_msg>Remove useless print<commit_after>package pack

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

type pointer struct {
	addr reflect.Value
	ttype reflect.Type

}

func (p *pointer) Set(val interface{}) {
	po := *p
	switch vv := val.(type) {
	case string:
		po.addr.SetString(vv)
	case int:
		po.addr.SetInt(int64(vv))
	case float64:
		po.addr.SetFloat(vv)
	case bool:
		po.addr.SetBool(vv)
	case []interface{}:

	default:
		fmt.Println("todo feature")
	}
}

func Packer(b *[]byte, class interface{}) {

	v := reflect.ValueOf(class)

	indirect_type := reflect.Indirect(v).Type()

	//store addr
	name_addr := make(map[string]pointer)
	el := v.Elem()
	for i := 0; i < el.NumField(); i++ {
		name_addr[indirect_type.Field(i).Name] =
			pointer{v.Elem().Field(i), indirect_type}
	}

	var f interface{}
	json.Unmarshal(*b, &f)
	m := f.(map[string]interface{})

	for k, v := range m {
		if q, ok := name_addr[k]; ok {
			p := &q
			p.Set(v)
		}
	}
}
<|endoftext|>


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

package oglematchers_test

import (
	"errors"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

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

type PanicsTest struct {
	matcherCalled bool
	suppliedCandidate interface{}
	wrappedResult bool
	wrappedError error

	matcher Matcher
}

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

func (t *PanicsTest) SetUp(i *TestInfo) {
	wrapped := &fakeMatcher{
		func(c interface{}) (bool, error) {
			t.matcherCalled = true
			t.suppliedCandidate = c
			return t.wrappedResult, t.wrappedError
		},
		"foo",
	}

	t.matcher = Panics(wrapped)
}

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

func (t *PanicsTest) Description() {
	ExpectThat(t.matcher.Description(), Equals("panics with: foo"))
}

func (t *PanicsTest) CandidateIsNil() {
	res, err := t.matcher.Matches(nil)

	ExpectThat(res, Equals(false))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CandidateIsString() {
	res, err := t.matcher.Matches("taco")

	ExpectThat(res, Equals(false))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CandidateTakesArgs() {
	res, err := t.matcher.Matches(func(i int) string { return "" })

	ExpectThat(res, Equals(false))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CallsFunction() {
	callCount := 0
	t.matcher.Matches(func() string {
		callCount++
		return ""
	})

	ExpectThat(callCount, Equals(1))
}

func (t *PanicsTest) FunctionDoesntPanic() {
	res, err := t.matcher.Matches(func() {})

	ExpectThat(res, Equals(false))
	ExpectThat(err, Error(Equals("which didn't panic")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) CallsWrappedMatcher() {
	expectedErr := 17
	t.wrappedResult = false
	t.wrappedError = errors.New("")
	t.matcher.Matches(func() { panic(expectedErr) })

	ExpectThat(t.suppliedCandidate, Equals(expectedErr))
}

func (t *PanicsTest) WrappedReturnsTrue() {
	t.wrappedResult = true
	res, err := t.matcher.Matches(func() { panic("") })

	ExpectTrue(res)
	ExpectEq(nil, err)
}

func (t *PanicsTest) WrappedReturnsFatalErrorWithoutText() {
	t.wrappedResult = false
	t.wrappedError = NewFatalError("")
	res, err := t.matcher.Matches(func() { panic(17) })

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which panicked with: 17")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsFatalErrorWithText() {
	t.wrappedResult = false
	t.wrappedError = NewFatalError("which blah")
	res, err := t.matcher.Matches(func() { panic(17) })

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsNonFatalErrorWithoutText() {
	t.wrappedResult = false
	t.wrappedError = errors.New("")
	res, err := t.matcher.Matches(func() { panic(17) })

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which panicked with: 17")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsNonFatalErrorWithText() {
	t.wrappedResult = false
	t.wrappedError = errors.New("which blah")
	res, err := t.matcher.Matches(func() { panic(17) })

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
	ExpectFalse(isFatal(err))
}
<commit_msg>Updated PanicsTest.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglematchers_test

import (
	"errors"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

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

type PanicsTest struct {
	matcherCalled bool
	suppliedCandidate interface{}
	wrappedError error

	matcher Matcher
}

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

func (t *PanicsTest) SetUp(i *TestInfo) {
	wrapped := &fakeMatcher{
		func(c interface{}) error {
			t.matcherCalled = true
			t.suppliedCandidate = c
			return t.wrappedError
		},
		"foo",
	}

	t.matcher = Panics(wrapped)
}

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

func (t *PanicsTest) Description() {
	ExpectThat(t.matcher.Description(), Equals("panics with: foo"))
}

func (t *PanicsTest) CandidateIsNil() {
	err := t.matcher.Matches(nil)

	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CandidateIsString() {
	err := t.matcher.Matches("taco")

	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CandidateTakesArgs() {
	err := t.matcher.Matches(func(i int) string { return "" })

	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
	ExpectTrue(isFatal(err))
}

func (t *PanicsTest) CallsFunction() {
	callCount := 0
	t.matcher.Matches(func() string {
		callCount++
		return ""
	})

	ExpectThat(callCount, Equals(1))
}

func (t *PanicsTest) FunctionDoesntPanic() {
	err := t.matcher.Matches(func() {})

	ExpectThat(err, Error(Equals("which didn't panic")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) CallsWrappedMatcher() {
	expectedErr := 17
	t.wrappedError = errors.New("")
	t.matcher.Matches(func() { panic(expectedErr) })

	ExpectThat(t.suppliedCandidate, Equals(expectedErr))
}

func (t *PanicsTest) WrappedReturnsTrue() {
	err := t.matcher.Matches(func() { panic("") })

	ExpectEq(nil, err)
}

func (t *PanicsTest) WrappedReturnsFatalErrorWithoutText() {
	t.wrappedError = NewFatalError("")
	err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsFatalErrorWithText() {
	t.wrappedError = NewFatalError("which blah")
	err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsNonFatalErrorWithoutText() {
	t.wrappedError = errors.New("")
	err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17")))
	ExpectFalse(isFatal(err))
}

func (t *PanicsTest) WrappedReturnsNonFatalErrorWithText() {
	t.wrappedError = errors.New("which blah")
	err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
	ExpectFalse(isFatal(err))
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcs

import (
	"errors"
	"io"
	"net/http"
	"unicode/utf8"

	"golang.org/x/net/context"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// Bucket represents a GCS bucket, pre-bound with a bucket name and necessary
// authorization information.
//
// Each method that may block accepts a context object that is used for
// deadlines and cancellation. Users need not package authorization information
// into the context object (using cloud.WithContext or similar).
type Bucket interface {
	Name() string

	// List the objects in the bucket that meet the criteria defined by the
	// query, returning a result object that contains the results and potentially
	// a cursor for retrieving the next portion of the larger set of results.
	ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error)

	// Create a reader for the contents of the object with the given name. The
	// caller must arrange for the reader to be closed when it is no longer
	// needed.
	NewReader(ctx context.Context, objectName string) (io.ReadCloser, error)

	// Return an ObjectWriter that can be used to create or overwrite an object
	// with the given attributes. attrs.Name must be specified. Otherwise, nil-
	// and zero-valud attributes are ignored.
	//
	// Object names must:
	//
	// *  be non-empty.
	// *  be no longer than 1024 bytes.
	// *  be valid UTF-8.
	// *  not contain the code point U+000A (line feed).
	// *  not contain the code point U+000D (carriage return).
	//
	// See here for authoritative documentation:
	//     https://cloud.google.com/storage/docs/bucket-naming#objectnames
	NewWriter(ctx context.Context, attrs *storage.ObjectAttrs) (ObjectWriter, error)

	// Delete the object with the given name.
	DeleteObject(ctx context.Context, name string) error
}

type bucket struct {
	projID string
	client *http.Client
	name   string
}

func (b *bucket) Name() string {
	return b.name
}

func (b *bucket) ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.ListObjects(authContext, b.name, query)
}

func (b *bucket) NewReader(ctx context.Context, objectName string) (io.ReadCloser, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.NewReader(authContext, b.name, objectName)
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (ObjectWriter, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)

	// As of 2015-02, the wrapped storage package doesn't check this for us,
	// causing silently transformed names:
	//     https://github.com/GoogleCloudPlatform/gcloud-golang/issues/111
	if !utf8.ValidString(attrs.Name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	// Create and initialize the wrapped writer.
	wrapped := storage.NewWriter(authContext, b.name, attrs.Name)
	wrapped.ObjectAttrs = *attrs

	w := &objectWriter{
		wrapped: wrapped,
	}

	return w, nil
}

func (b *bucket) DeleteObject(ctx context.Context, name string) error {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.DeleteObject(authContext, b.name, name)
}
<commit_msg>Declared a new interface for creating objects.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcs

import (
	"errors"
	"io"
	"net/http"
	"unicode/utf8"

	"golang.org/x/net/context"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// A request to create an object, accepted by Bucket.CreateObject.
type CreateObjectRequest struct {
	// Attributes with which the object should be created. The Name field must be
	// set; other zero-valued fields are ignored.
	//
	// Object names must:
	//
	// *  be non-empty.
	// *  be no longer than 1024 bytes.
	// *  be valid UTF-8.
	// *  not contain the code point U+000A (line feed).
	// *  not contain the code point U+000D (carriage return).
	//
	// See here for authoritative documentation:
	//     https://cloud.google.com/storage/docs/bucket-naming#objectnames
	Attrs storage.ObjectAttrs

	// A reader from which to obtain the contents of the object. Must be non-nil.
	// Will be closed when CreateObject returns, regardless of whether it succeeds.
	Contents io.ReadCloser
}

// Bucket represents a GCS bucket, pre-bound with a bucket name and necessary
// authorization information.
//
// Each method that may block accepts a context object that is used for
// deadlines and cancellation. Users need not package authorization information
// into the context object (using cloud.WithContext or similar).
type Bucket interface {
	Name() string

	// List the objects in the bucket that meet the criteria defined by the
	// query, returning a result object that contains the results and potentially
	// a cursor for retrieving the next portion of the larger set of results.
	ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error)

	// Create a reader for the contents of the object with the given name. The
	// caller must arrange for the reader to be closed when it is no longer
	// needed.
	NewReader(ctx context.Context, objectName string) (io.ReadCloser, error)

	// Create or overwrite an object according to the supplied request. The new
	// object is guaranteed to exist immediately for the purposes of reading (and
	// eventually for listing) after this method returns a nil error. It is
	// guaranteed not to exist before req.Contents returns io.EOF.
	CreateObject(ctx context.Context, req *CreateObjectRequest) (*storage.Object, error)

	// Delete the object with the given name.
	DeleteObject(ctx context.Context, name string) error
}

type bucket struct {
	projID string
	client *http.Client
	name   string
}

func (b *bucket) Name() string {
	return b.name
}

func (b *bucket) ListObjects(ctx context.Context, query *storage.Query) (*storage.Objects, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.ListObjects(authContext, b.name, query)
}

func (b *bucket) NewReader(ctx context.Context, objectName string) (io.ReadCloser, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.NewReader(authContext, b.name, objectName)
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (ObjectWriter, error) {
	authContext := cloud.WithContext(ctx, b.projID, b.client)

	// As of 2015-02, the wrapped storage package doesn't check this for us,
	// causing silently transformed names:
	//     https://github.com/GoogleCloudPlatform/gcloud-golang/issues/111
	if !utf8.ValidString(attrs.Name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	// Create and initialize the wrapped writer.
	wrapped := storage.NewWriter(authContext, b.name, attrs.Name)
	wrapped.ObjectAttrs = *attrs

	w := &objectWriter{
		wrapped: wrapped,
	}

	return w, nil
}

func (b *bucket) DeleteObject(ctx context.Context, name string) error {
	authContext := cloud.WithContext(ctx, b.projID, b.client)
	return storage.DeleteObject(authContext, b.name, name)
}
<|endoftext|>


<commit_before>package sprite_sass_test

import (
	"io/ioutil"
	"regexp"
	"strings"
	"testing"

	. "github.com/drewwells/sprite_sass"
)

var rerandom *regexp.Regexp

func init() {
	rerandom = regexp.MustCompile(`-\w{6}(?:\.png)`)
}

func TestParserVar(t *testing.T) {
	p := Parser{}
	fread := fileReader("test/_var.scss")
	output := string(p.Start(fread, "test/"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/var.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}

}

/*func TestParserImporter(t *testing.T) {
	p := Parser{}
	output := string(p.Start("test/import.scss"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/import.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}
}

func TestParseSprite(t *testing.T) {
	p := Parser{}
	output := string(p.Start("test/sprite.scss"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/sprite.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}
}

func TestParseComment(t *testing.T) {
	p := Parser{}
	res := string(p.Start("test/_comment.scss"))
	res = strings.TrimSpace(rerandom.ReplaceAllString(res, ""))
	e := strings.TrimSpace(fileString("test/comment.parser"))

	if res != e {
		t.Errorf("Comment parsing failed was:"+
			"%s\n exp:%s\n", res, e)
	}
}
*/
<commit_msg>Updated parser tests<commit_after>package sprite_sass_test

import (
	"io/ioutil"
	"regexp"
	"strings"
	"testing"

	. "github.com/drewwells/sprite_sass"
)

var rerandom *regexp.Regexp

func init() {
	rerandom = regexp.MustCompile(`-\w{6}(?:\.png)`)
}

func TestParserVar(t *testing.T) {
	p := Parser{}
	fread := fileReader("test/_var.scss")
	output := string(p.Start(fread, "test/"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/var.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}

}

func TestParserImporter(t *testing.T) {
	p := Parser{}
	output := string(p.Start(fileReader("test/import.scss"), "test/"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/import.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}
}

func TestParseSprite(t *testing.T) {
	p := Parser{}
	output := string(p.Start(fileReader("test/sprite.scss"), "test/"))
	output = rerandom.ReplaceAllString(output, "")

	file, _ := ioutil.ReadFile("test/sprite.parser")
	if strings.TrimSpace(string(file)) != strings.TrimSpace(output) {
		t.Errorf("File output did not match, was:\n%s\nexpected:\n%s", output, string(file))
	}
}

func TestParseComment(t *testing.T) {
	p := Parser{}
	res := string(p.Start(fileReader("test/_comment.scss"), "test/"))
	res = strings.TrimSpace(rerandom.ReplaceAllString(res, ""))
	e := strings.TrimSpace(fileString("test/comment.parser"))

	if res != e {
		t.Errorf("Comment parsing failed was:"+
			"%s\n exp:%s\n", res, e)
	}
}
<|endoftext|>


<commit_before>package postal

import (
	"bytes"
	"strings"
	"testing"
)

func TestParse(t *testing.T) {
	actuals := []string{
		`01101,"060  ","0600000","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｲｶﾆｹｲｻｲｶﾞﾅｲﾊﾞｱｲ","北海道","札幌市中央区","以下に掲載がない場合",0,0,0,0,0,0`,
	}
	expects := []*Entry{
		&Entry{
			Code:            "01101",
			OldZip:          "060  ",
			Zip:             "0600000",
			Pref:            Name{"北海道", "ﾎｯｶｲﾄﾞｳ"},
			Region:          Name{"札幌市中央区", "ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ"},
			Town:            Name{"", ""},
			IsPartialTown:   false,
			IsLargeTown:     false,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
	}
	parseTest(t, actuals, expects, "\n")
}

func TestParseSplitted(t *testing.T) {
	actuals := []string{
		`02206,"01855","0185501","ｱｵﾓﾘｹﾝ","ﾄﾜﾀﾞｼ","ｵｸｾ(ｱｵﾌﾞﾅ､ｺﾀﾀﾐｲｼ､ﾄﾜﾀﾞ､ﾄﾜﾀﾞｺﾊﾝｳﾀﾙﾍﾞ､ﾄﾜﾀﾞｺﾊﾝﾈﾉｸﾁ､","青森県","十和田市","奥瀬（青撫、小畳石、十和田、十和田湖畔宇樽部、十和田湖畔子ノ口、",1,1,0,0,0,0`,
		`02206,"01855","0185501","ｱｵﾓﾘｹﾝ","ﾄﾜﾀﾞｼ","ﾄﾜﾀﾞｺﾊﾝﾔｽﾐﾔ)","青森県","十和田市","十和田湖畔休屋）",1,1,0,0,0,0`,
	}
	expects := []*Entry{
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬青撫", "ｵｸｾｱｵﾌﾞﾅ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬小畳石", "ｵｸｾｺﾀﾀﾐｲｼ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田", "ｵｸｾﾄﾜﾀﾞ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔宇樽部", "ｵｸｾﾄﾜﾀﾞｺﾊﾝｳﾀﾙﾍﾞ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔子ノ口", "ｵｸｾﾄﾜﾀﾞｺﾊﾝﾈﾉｸﾁ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔休屋", "ｵｸｾﾄﾜﾀﾞｺﾊﾝﾔｽﾐﾔ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
	}
	parseTest(t, actuals, expects, "\n")
}

func parseTest(t *testing.T, actuals []string, expects []*Entry, newline string) {
	c := make(chan *Entry)
	ec := make(chan error)
	s := strings.Join(actuals, newline)
	fin := bytes.NewBufferString(s)
	go Parse(c, ec, fin)
	for _, expect := range expects {
		select {
		case err := <-ec:
			t.Errorf("Parse() = %v; Expect not error", err)
		case entry := <-c:
			if entry == nil {
				t.Errorf("Parse() = nil; Expect not nil")
				return
			}
			if entry.Code != expect.Code {
				t.Errorf("Parse(): Code = %q; Expect %q", entry.Code, expect.Code)
			}
			if entry.OldZip != expect.OldZip {
				t.Errorf("Parse(): OldZip = %q; Expect %q", entry.OldZip, expect.OldZip)
			}
			if entry.Zip != expect.Zip {
				t.Errorf("Parse(): Zip = %q; Expect %q", entry.Zip, expect.Zip)
			}
			if !entry.Pref.Equal(expect.Pref) {
				t.Errorf("Parse(): Pref = %q; Expect %q", entry.Pref, expect.Pref)
			}
			if !entry.Region.Equal(expect.Region) {
				t.Errorf("Parse(): Region = %q; Expect %q", entry.Region, expect.Region)
			}
			if !entry.Town.Equal(expect.Town) {
				t.Errorf("Parse(): Town = %q; Expect %q", entry.Town, expect.Town)
			}
			if entry.IsPartialTown != expect.IsPartialTown {
				t.Errorf("Parse(): IsPartialTown = %q; Expect %q", entry.IsPartialTown, expect.IsPartialTown)
			}
			if entry.IsLargeTown != expect.IsLargeTown {
				t.Errorf("Parse(): IsLargeTown = %q; Expect %q", entry.IsLargeTown, expect.IsLargeTown)
			}
			if entry.IsBlockedScheme != expect.IsBlockedScheme {
				t.Errorf("Parse(): IsBlockedScheme = %q; Expect %q", entry.IsBlockedScheme, expect.IsBlockedScheme)
			}
			if entry.IsOverlappedZip != expect.IsOverlappedZip {
				t.Errorf("Parse(): IsOverlappedZip = %q; Expect %q", entry.IsOverlappedZip, expect.IsOverlappedZip)
			}
			if entry.Status != expect.Status {
				t.Errorf("Parse(): Status = %q; Expect %q", entry.Status, expect.Status)
			}
			if entry.Reason != expect.Reason {
				t.Errorf("Parse(): Reason = %q; Expect %q", entry.Reason, expect.Reason)
			}
		}
	}
}
<commit_msg>テストコード追加<commit_after>package postal

import (
	"bytes"
	"strings"
	"testing"
)

func TestParse(t *testing.T) {
	actuals := []string{
		`01101,"060  ","0600000","ﾎｯｶｲﾄﾞｳ","ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ","ｲｶﾆｹｲｻｲｶﾞﾅｲﾊﾞｱｲ","北海道","札幌市中央区","以下に掲載がない場合",0,0,0,0,0,0`,
	}
	expects := []*Entry{
		&Entry{
			Code:            "01101",
			OldZip:          "060  ",
			Zip:             "0600000",
			Pref:            Name{"北海道", "ﾎｯｶｲﾄﾞｳ"},
			Region:          Name{"札幌市中央区", "ｻｯﾎﾟﾛｼﾁｭｳｵｳｸ"},
			Town:            Name{"", ""},
			IsPartialTown:   false,
			IsLargeTown:     false,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
	}
	parseTest(t, actuals, expects, "\n")
}

func TestParseSplitted(t *testing.T) {
	actuals := []string{
		`02206,"01855","0185501","ｱｵﾓﾘｹﾝ","ﾄﾜﾀﾞｼ","ｵｸｾ(ｱｵﾌﾞﾅ､ｺﾀﾀﾐｲｼ､ﾄﾜﾀﾞ､ﾄﾜﾀﾞｺﾊﾝｳﾀﾙﾍﾞ､ﾄﾜﾀﾞｺﾊﾝﾈﾉｸﾁ､","青森県","十和田市","奥瀬（青撫、小畳石、十和田、十和田湖畔宇樽部、十和田湖畔子ノ口、",1,1,0,0,0,0`,
		`02206,"01855","0185501","ｱｵﾓﾘｹﾝ","ﾄﾜﾀﾞｼ","ﾄﾜﾀﾞｺﾊﾝﾔｽﾐﾔ)","青森県","十和田市","十和田湖畔休屋）",1,1,0,0,0,0`,
	}
	expects := []*Entry{
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬青撫", "ｵｸｾｱｵﾌﾞﾅ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬小畳石", "ｵｸｾｺﾀﾀﾐｲｼ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田", "ｵｸｾﾄﾜﾀﾞ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔宇樽部", "ｵｸｾﾄﾜﾀﾞｺﾊﾝｳﾀﾙﾍﾞ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔子ノ口", "ｵｸｾﾄﾜﾀﾞｺﾊﾝﾈﾉｸﾁ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
		&Entry{
			Code:            "02206",
			OldZip:          "01855",
			Zip:             "0185501",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬十和田湖畔休屋", "ｵｸｾﾄﾜﾀﾞｺﾊﾝﾔｽﾐﾔ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
	}
	parseTest(t, actuals, expects, "\n")
}

func TestParseOthers(t *testing.T) {
	actuals := []string{
		`02206,"03403","0340301","ｱｵﾓﾘｹﾝ","ﾄﾜﾀﾞｼ","ｵｸｾ(ｿﾉﾀ)","青森県","十和田市","奥瀬（その他）",1,1,0,0,0,0`,
	}
	expects := []*Entry{
		&Entry{
			Code:            "02206",
			OldZip:          "03403",
			Zip:             "0340301",
			Pref:            Name{"青森県", "ｱｵﾓﾘｹﾝ"},
			Region:          Name{"十和田市", "ﾄﾜﾀﾞｼ"},
			Town:            Name{"奥瀬", "ｵｸｾ"},
			IsPartialTown:   true,
			IsLargeTown:     true,
			IsBlockedScheme: false,
			IsOverlappedZip: false,
			Status:          StatusNotModified,
			Reason:          ReasonNotModified,
		},
	}
	parseTest(t, actuals, expects, "\n")
}

func parseTest(t *testing.T, actuals []string, expects []*Entry, newline string) {
	c := make(chan *Entry)
	ec := make(chan error)
	s := strings.Join(actuals, newline)
	fin := bytes.NewBufferString(s)
	go Parse(c, ec, fin)
	for _, expect := range expects {
		select {
		case err := <-ec:
			t.Errorf("Parse() = %v; Expect not error", err)
		case entry := <-c:
			if entry == nil {
				t.Errorf("Parse() = nil; Expect not nil")
				return
			}
			if entry.Code != expect.Code {
				t.Errorf("Parse(): Code = %q; Expect %q", entry.Code, expect.Code)
			}
			if entry.OldZip != expect.OldZip {
				t.Errorf("Parse(): OldZip = %q; Expect %q", entry.OldZip, expect.OldZip)
			}
			if entry.Zip != expect.Zip {
				t.Errorf("Parse(): Zip = %q; Expect %q", entry.Zip, expect.Zip)
			}
			if !entry.Pref.Equal(expect.Pref) {
				t.Errorf("Parse(): Pref = %q; Expect %q", entry.Pref, expect.Pref)
			}
			if !entry.Region.Equal(expect.Region) {
				t.Errorf("Parse(): Region = %q; Expect %q", entry.Region, expect.Region)
			}
			if !entry.Town.Equal(expect.Town) {
				t.Errorf("Parse(): Town = %q; Expect %q", entry.Town, expect.Town)
			}
			if entry.IsPartialTown != expect.IsPartialTown {
				t.Errorf("Parse(): IsPartialTown = %q; Expect %q", entry.IsPartialTown, expect.IsPartialTown)
			}
			if entry.IsLargeTown != expect.IsLargeTown {
				t.Errorf("Parse(): IsLargeTown = %q; Expect %q", entry.IsLargeTown, expect.IsLargeTown)
			}
			if entry.IsBlockedScheme != expect.IsBlockedScheme {
				t.Errorf("Parse(): IsBlockedScheme = %q; Expect %q", entry.IsBlockedScheme, expect.IsBlockedScheme)
			}
			if entry.IsOverlappedZip != expect.IsOverlappedZip {
				t.Errorf("Parse(): IsOverlappedZip = %q; Expect %q", entry.IsOverlappedZip, expect.IsOverlappedZip)
			}
			if entry.Status != expect.Status {
				t.Errorf("Parse(): Status = %q; Expect %q", entry.Status, expect.Status)
			}
			if entry.Reason != expect.Reason {
				t.Errorf("Parse(): Reason = %q; Expect %q", entry.Reason, expect.Reason)
			}
		}
	}
}
<|endoftext|>


<commit_before>/* Licensed to Elodina Inc. 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 zipkin

import (
	"github.com/elodina/siesta"
	producer "github.com/elodina/siesta-producer"
	"github.com/spacemonkeygo/monotime"
	"golang.org/x/net/context"
	"gopkg.in/spacemonkeygo/monitor.v1/trace"
	"gopkg.in/spacemonkeygo/monitor.v1/trace/gen-go/zipkin"
)

type TraceConfig struct {
	ServiceName         string
	SampleRate          float64
	BrokerList          []string
	Topic               string
	Ip                  int32
	Port                int16
	KafkaProducerConfig *producer.ProducerConfig
}

type Tracer struct {
	manager   *trace.SpanManager
	collector *KafkaCollector
}

func NewTraceConfig(serviceName string, sampleRate float64, brokerList []string) *TraceConfig {
	producerConfig := producer.NewProducerConfig()
	producerConfig.BatchSize = 200
	producerConfig.ClientID = "zipkin"
	return &TraceConfig{
		serviceName,
		sampleRate,
		brokerList,
		"zipkin",
		127*256*256*256 + 1, // TODO: should find out actual local IP by default
		0,
		producerConfig,
	}
}

func NewTracer(config *TraceConfig) (*Tracer, error) {
	producerConfig := config.KafkaProducerConfig
	kafkaConnectorConfig := siesta.NewConnectorConfig()
	kafkaConnectorConfig.BrokerList = config.BrokerList
	connector, err := siesta.NewDefaultConnector(kafkaConnectorConfig)
	if err != nil {
		return nil, err
	}
	kafkaProducer := producer.NewKafkaProducer(producerConfig, producer.ByteSerializer, producer.ByteSerializer, connector)

	tracer := &Tracer{trace.NewSpanManager(), &KafkaCollector{kafkaProducer, config.Topic}}
	tracer.manager.Configure(config.SampleRate, false, &zipkin.Endpoint{
		Ipv4:        config.Ip,
		Port:        config.Port,
		ServiceName: config.ServiceName})
	tracer.manager.RegisterTraceCollector(tracer.collector)
	return tracer, nil
}

func (t *Tracer) InitServer(spanName string, r trace.Request) context.Context {
	ctx := t.createContextFromRequest(spanName, r)

	Annotate(ctx, zipkin.SERVER_RECV)

	return ctx
}

func (t *Tracer) TraceClient(ctx *context.Context, spanName string) func(*error) {
	return t.manager.TraceWithSpanNamed(ctx, spanName)
}

func (t *Tracer) TraceClientSent(ctx context.Context, spanName string) {
	t.manager.TraceWithSpanNamed(&ctx, spanName)
	t.CollectFromContext(ctx)
}

func Annotate(ctx context.Context, v string) {
	if span, ok := trace.SpanFromContext(ctx); ok {
		span.AnnotateTimestamp(v, monotime.Now(), nil, nil)
	}
}

func (t *Tracer) Collect(s *trace.Span) {
	if !s.TraceDisabled() {
		data := s.Export()
		t.collector.Collect(data)
	}
}

func (t *Tracer) CollectFromContext(ctx context.Context) {
	if span, ok := trace.SpanFromContext(ctx); ok {
		t.Collect(span)
	}
}

func (t *Tracer) createContextFromRequest(spanName string, r trace.Request) context.Context {
	span := t.manager.NewSpanFromRequest(spanName, r)
	return trace.ContextWithSpan(context.Background(), span)
}

func SampledSpanInfo(ctx context.Context) (s *trace.Span, ok bool) {
	currentSpan, ok := trace.SpanFromContext(ctx)
	return currentSpan, ok && !currentSpan.TraceDisabled()
}
<commit_msg>Use existing kafka producer if needed.<commit_after>/* Licensed to Elodina Inc. 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 zipkin

import (
	"github.com/elodina/siesta"
	producer "github.com/elodina/siesta-producer"
	"github.com/spacemonkeygo/monotime"
	"golang.org/x/net/context"
	"gopkg.in/spacemonkeygo/monitor.v1/trace"
	"gopkg.in/spacemonkeygo/monitor.v1/trace/gen-go/zipkin"
)

var localhost int32 = 127*256*256*256 + 1

type TraceConfig struct {
	KafkaProducer       *producer.KafkaProducer
	ServiceName         string
	SampleRate          float64
	BrokerList          []string
	Topic               string
	Ip                  int32
	Port                int16
	KafkaProducerConfig *producer.ProducerConfig
}

type Tracer struct {
	manager   *trace.SpanManager
	collector *KafkaCollector
}

func NewTraceConfigWithProducer(serviceName string, samplaRate float64, kafkaProducer *producer.KafkaProducer) *TraceConfig {
	return &TraceConfig{
		KafkaProducer: kafkaProducer,
		ServiceName:   serviceName,
		SampleRate:    samplaRate,
		Topic:         "zipkin",
		Ip:            localhost,
		Port:          0,
	}
}

func NewTraceConfig(serviceName string, sampleRate float64, brokerList []string) *TraceConfig {
	producerConfig := producer.NewProducerConfig()
	producerConfig.BatchSize = 200
	producerConfig.ClientID = "zipkin"
	return &TraceConfig{
		ServiceName:         serviceName,
		SampleRate:          sampleRate,
		BrokerList:          brokerList,
		Topic:               "zipkin",
		Ip:                  localhost, // TODO: should find out actual local IP by default
		Port:                0,
		KafkaProducerConfig: producerConfig,
	}
}

func NewTracer(config *TraceConfig) (*Tracer, error) {
	var kafkaProducer *producer.KafkaProducer
	if config.KafkaProducer != nil {
		kafkaProducer = config.KafkaProducer
	} else {
		producerConfig := config.KafkaProducerConfig
		kafkaConnectorConfig := siesta.NewConnectorConfig()
		kafkaConnectorConfig.BrokerList = config.BrokerList
		connector, err := siesta.NewDefaultConnector(kafkaConnectorConfig)
		if err != nil {
			return nil, err
		}
		kafkaProducer = producer.NewKafkaProducer(producerConfig, producer.ByteSerializer, producer.ByteSerializer, connector)
	}

	tracer := &Tracer{trace.NewSpanManager(), &KafkaCollector{kafkaProducer, config.Topic}}
	tracer.manager.Configure(config.SampleRate, false, &zipkin.Endpoint{
		Ipv4:        config.Ip,
		Port:        config.Port,
		ServiceName: config.ServiceName})
	tracer.manager.RegisterTraceCollector(tracer.collector)
	return tracer, nil
}

func (t *Tracer) InitServer(spanName string, r trace.Request) context.Context {
	ctx := t.createContextFromRequest(spanName, r)

	Annotate(ctx, zipkin.SERVER_RECV)

	return ctx
}

func (t *Tracer) TraceClient(ctx *context.Context, spanName string) func(*error) {
	return t.manager.TraceWithSpanNamed(ctx, spanName)
}

func (t *Tracer) TraceClientSent(ctx context.Context, spanName string) {
	t.manager.TraceWithSpanNamed(&ctx, spanName)
	t.CollectFromContext(ctx)
}

func Annotate(ctx context.Context, v string) {
	if span, ok := trace.SpanFromContext(ctx); ok {
		span.AnnotateTimestamp(v, monotime.Now(), nil, nil)
	}
}

func (t *Tracer) Collect(s *trace.Span) {
	if !s.TraceDisabled() {
		data := s.Export()
		t.collector.Collect(data)
	}
}

func (t *Tracer) CollectFromContext(ctx context.Context) {
	if span, ok := trace.SpanFromContext(ctx); ok {
		t.Collect(span)
	}
}

func (t *Tracer) createContextFromRequest(spanName string, r trace.Request) context.Context {
	span := t.manager.NewSpanFromRequest(spanName, r)
	return trace.ContextWithSpan(context.Background(), span)
}

func SampledSpanInfo(ctx context.Context) (s *trace.Span, ok bool) {
	currentSpan, ok := trace.SpanFromContext(ctx)
	return currentSpan, ok && !currentSpan.TraceDisabled()
}
<|endoftext|>


<commit_before>package persist

import (
	"fmt"
	"log"
	"os"

	"github.com/NebulousLabs/Sia/build"
)

// logFileWrapper wraps a log file to perform sanity checks on the Write and
// Close functions. An error will be returned if Close is called multiple times
// or if Write is called after Close has been called.
type logFileWrapper struct {
	closed bool // Flag is set after Close is called.
	file   *os.File
}

// newLogFileWrapper returns a logFileWrapper that has been initialized with
// the input file.
func newLogFileWrapper(f *os.File) *logFileWrapper {
	return &logFileWrapper{file: f}
}

// Close closes the log file wrapper.
func (lfw *logFileWrapper) Close() error {
	// Sanity check - close should not have been called yet.
	if build.DEBUG && lfw.closed {
		panic("cannot close the logger after it has been closed")
	}
	lfw.closed = true
	return lfw.file.Close()
}

// Write takes the input data and writes it to the file.
func (lfw *logFileWrapper) Write(b []byte) (int, error) {
	// Sanity check - close should not have been called yet.
	if build.DEBUG && lfw.closed {
		panic("cannot write to the logger after it has been closed")
	}
	return lfw.file.Write(b)
}

// Logger is a wrapper for the standard library logger that enforces logging
// into a file with the Sia-standard settings.
type Logger struct {
	*log.Logger
	logFileWrapper *logFileWrapper
}

// NewLogger returns a logger that can be closed. Calls should not be made to
// the logger after 'Close' has been called.
func NewLogger(logFilename string) (*Logger, error) {
	logFile, err := os.OpenFile(logFilename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0660)
	if err != nil {
		return nil, err
	}
	lfw := newLogFileWrapper(logFile)
	logger := log.New(lfw, "", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile|log.LUTC)
	logger.Println("STARTUP: Logging has started.")
	return &Logger{Logger: logger, logFileWrapper: lfw}, nil
}

// Close terminates the Logger.
func (l *Logger) Close() error {
	l.Println("SHUTDOWN: Logging has terminated.")
	return l.logFileWrapper.Close()
}

// Critical will panic if debug mode is activated, and will log the statement
// otherwise.
func (l *Logger) Critical(v ...interface{}) {
	s := fmt.Sprintln(v...)
	os.Stderr.WriteString("Severe Error: " + s)
	l.Println("CRITICAL:", s)
	if build.DEBUG {
		panic(s)
	}
}
<commit_msg>sync persist.Logger<commit_after>package persist

import (
	"fmt"
	"log"
	"os"

	"github.com/NebulousLabs/Sia/build"
)

// logFileWrapper wraps a log file to perform sanity checks on the Write and
// Close functions. An error will be returned if Close is called multiple times
// or if Write is called after Close has been called.
type logFileWrapper struct {
	closed bool // Flag is set after Close is called.
	file   *os.File
}

// newLogFileWrapper returns a logFileWrapper that has been initialized with
// the input file.
func newLogFileWrapper(f *os.File) *logFileWrapper {
	return &logFileWrapper{file: f}
}

// Close closes the log file wrapper.
func (lfw *logFileWrapper) Close() error {
	// Sanity check - close should not have been called yet.
	if build.DEBUG && lfw.closed {
		panic("cannot close the logger after it has been closed")
	}
	// Ensure that all data has actually hit the disk.
	if err := lfw.file.Sync(); err != nil {
		return err
	}
	lfw.closed = true
	return lfw.file.Close()
}

// Write takes the input data and writes it to the file.
func (lfw *logFileWrapper) Write(b []byte) (int, error) {
	// Sanity check - close should not have been called yet.
	if build.DEBUG && lfw.closed {
		panic("cannot write to the logger after it has been closed")
	}
	return lfw.file.Write(b)
}

// Logger is a wrapper for the standard library logger that enforces logging
// into a file with the Sia-standard settings.
type Logger struct {
	*log.Logger
	logFileWrapper *logFileWrapper
}

// NewLogger returns a logger that can be closed. Calls should not be made to
// the logger after 'Close' has been called.
func NewLogger(logFilename string) (*Logger, error) {
	logFile, err := os.OpenFile(logFilename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0660)
	if err != nil {
		return nil, err
	}
	lfw := newLogFileWrapper(logFile)
	logger := log.New(lfw, "", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile|log.LUTC)
	logger.Println("STARTUP: Logging has started.")
	return &Logger{Logger: logger, logFileWrapper: lfw}, nil
}

// Close terminates the Logger.
func (l *Logger) Close() error {
	l.Println("SHUTDOWN: Logging has terminated.")
	return l.logFileWrapper.Close()
}

// Critical will panic if debug mode is activated, and will log the statement
// otherwise.
func (l *Logger) Critical(v ...interface{}) {
	s := fmt.Sprintln(v...)
	os.Stderr.WriteString("Severe Error: " + s)
	l.Println("CRITICAL:", s)
	if build.DEBUG {
		panic(s)
	}
}
<|endoftext|>


<commit_before>/**
Copyright (c) 2015 The PipeScript Contributors (see AUTHORS)
Licensed under the MIT license.
**/

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/connectordb/pipescript"
	"github.com/connectordb/pipescript/bytestreams"
	"github.com/connectordb/pipescript/transforms"

	"github.com/codegangsta/cli"
)

func getReader(s string) (*os.File, error) {
	if s == "STDIN" || s == "" {
		return os.Stdin, nil
	}
	return os.Open(s)
}

func getWriter(s string) (*os.File, error) {
	if s == "STDOUT" || s == "" {
		return os.Stdout, nil
	}
	return os.Create(s)
}

func runner(c *cli.Context, str string) {

	r, err := getReader(c.String("input"))
	if err != nil {
		log.Fatal(err)
	}
	w, err := getWriter(c.String("output"))
	if err != nil {
		log.Fatal(err)
	}
	// Now get the pipescript
	s, err := pipescript.Parse(str)
	if err != nil {
		log.Fatal(fmt.Errorf("%s\nIf using bash, make sure that '$' has spaces around it so that it is not mistaken for a bash variable.\n", err.Error()))
	}

	// Now set up the datapoint reader
	var dpr pipescript.DatapointIterator
	switch c.String("ifmt") {
	case "dp":

		dpr, err = bytestreams.NewDatapointReader(r)
		if err != nil {
			log.Fatal(err)
		}
	case "json":
		dpr, err = bytestreams.NewJSONDatapointReader(r, c.String("timestamp"), c.Bool("notimestamp"))
		if err != nil {
			log.Fatal(err)
		}
	case "csv":
		dpr, err = bytestreams.NewCSVDatapointReader(r, c.String("timestamp"), c.Bool("notimestamp"))
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("Unrecognized input format")
	}

	s.SetInput(dpr)

	// Now set the output json stream writer
	var jr io.Reader
	if !c.Bool("minify") {
		jr, err = bytestreams.NewJsonReader(s, "[\n", ",\n", "\n]", "", "  ")
	} else {
		jr, err = bytestreams.NewJsonArrayReader(s)
	}
	if err != nil {
		log.Fatal(err)
	}
	if _, err = io.Copy(w, jr); err != nil {
		log.Fatal(err)
	}

	// End with newline on stdout
	if w == os.Stdout {
		w.WriteString("\n")
	}

}

func main() {
	transforms.Register()

	app := cli.NewApp()
	app.Name = "pipes"
	app.Usage = "Run the PipeScript data analysis engine on your given datasets."
	app.Version = pipescript.Version

	app.Copyright = "This software is available under the MIT license"

	app.Usage = "pipes <transform or command> [command options]"

	transformArray := make([]cli.Command, 0, len(pipescript.TransformRegistry)+1)

	// We add the dump markdown option
	transformArray = append(transformArray, cli.Command{
		Name:  "dumpdocs",
		Usage: "dumpdocs dumps the markdown documentation files for all transforms to the given directory.",
		Action: func(c *cli.Context) error {
			p, err := filepath.Abs(c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			os.MkdirAll(p, 0777)
			for key := range pipescript.TransformRegistry {
				t := pipescript.TransformRegistry[key]
				err = ioutil.WriteFile(filepath.Join(p, key+".md"), []byte(t.Documentation), 0644)
				if err != nil {
					log.Fatal(err)
				}
			}
			return nil
		},
	})

	for key := range pipescript.TransformRegistry {
		t := pipescript.TransformRegistry[key]
		desc := t.Description
		if len(desc) > 60 {
			desc = desc[0:60] + "..."
		}
		transformArray = append(transformArray, cli.Command{
			Name:  t.Name,
			Usage: desc,
			Action: func(c *cli.Context) error {
				b, err := json.MarshalIndent(t, "", "  ")
				if err != nil {
					log.Fatal(err)
				}
				fmt.Printf("%s\n", string(b))
				return nil
			},
		})
	}

	app.Commands = []cli.Command{
		{
			Name:    "transforms",
			Aliases: []string{"t"},
			Usage:   "Documentation for specific transforms",
			//Action:  createDatabaseCallback,
			Subcommands: transformArray,
		},
		{
			Name:    "run",
			Aliases: []string{"r"},
			Usage:   "Run a transform.",
			Action: func(c *cli.Context) {
				runner(c, c.Args().First())
			},
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "input,i",
					Value: "STDIN",
					Usage: "The input file to perform analysis on.",
				},
				cli.StringFlag{
					Name:  "output,o",
					Value: "STDOUT",
					Usage: "File to write as output",
				},
				cli.BoolFlag{
					Name:  "minify,m",
					Usage: "Whether to indent the json for easy reading",
				},
				cli.BoolFlag{
					Name:  "notimestamp",
					Usage: "If set, does not look for a timestamp field in input",
				},
				cli.StringFlag{
					Name:  "ifmt",
					Value: "dp",
					Usage: "The data format to use for input data (dp,csv,json)",
				},
				cli.StringFlag{
					Name:  "timestamp",
					Value: "",
					Usage: "Allows to explicitly set the field name to use for timestamp values",
				},
			},
		},
	}

	app.Run(os.Args)

}
<commit_msg>Added docs link in undocumented transform dump<commit_after>/**
Copyright (c) 2015 The PipeScript Contributors (see AUTHORS)
Licensed under the MIT license.
**/

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/connectordb/pipescript"
	"github.com/connectordb/pipescript/bytestreams"
	"github.com/connectordb/pipescript/transforms"

	"github.com/codegangsta/cli"
)

func getReader(s string) (*os.File, error) {
	if s == "STDIN" || s == "" {
		return os.Stdin, nil
	}
	return os.Open(s)
}

func getWriter(s string) (*os.File, error) {
	if s == "STDOUT" || s == "" {
		return os.Stdout, nil
	}
	return os.Create(s)
}

func runner(c *cli.Context, str string) {

	r, err := getReader(c.String("input"))
	if err != nil {
		log.Fatal(err)
	}
	w, err := getWriter(c.String("output"))
	if err != nil {
		log.Fatal(err)
	}
	// Now get the pipescript
	s, err := pipescript.Parse(str)
	if err != nil {
		log.Fatal(fmt.Errorf("%s\nIf using bash, make sure that '$' has spaces around it so that it is not mistaken for a bash variable.\n", err.Error()))
	}

	// Now set up the datapoint reader
	var dpr pipescript.DatapointIterator
	switch c.String("ifmt") {
	case "dp":

		dpr, err = bytestreams.NewDatapointReader(r)
		if err != nil {
			log.Fatal(err)
		}
	case "json":
		dpr, err = bytestreams.NewJSONDatapointReader(r, c.String("timestamp"), c.Bool("notimestamp"))
		if err != nil {
			log.Fatal(err)
		}
	case "csv":
		dpr, err = bytestreams.NewCSVDatapointReader(r, c.String("timestamp"), c.Bool("notimestamp"))
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("Unrecognized input format")
	}

	s.SetInput(dpr)

	// Now set the output json stream writer
	var jr io.Reader
	if !c.Bool("minify") {
		jr, err = bytestreams.NewJsonReader(s, "[\n", ",\n", "\n]", "", "  ")
	} else {
		jr, err = bytestreams.NewJsonArrayReader(s)
	}
	if err != nil {
		log.Fatal(err)
	}
	if _, err = io.Copy(w, jr); err != nil {
		log.Fatal(err)
	}

	// End with newline on stdout
	if w == os.Stdout {
		w.WriteString("\n")
	}

}

func main() {
	transforms.Register()

	app := cli.NewApp()
	app.Name = "pipes"
	app.Usage = "Run the PipeScript data analysis engine on your given datasets."
	app.Version = pipescript.Version

	app.Copyright = "This software is available under the MIT license"

	app.Usage = "pipes <transform or command> [command options]"

	transformArray := make([]cli.Command, 0, len(pipescript.TransformRegistry)+1)

	// We add the dump markdown option
	transformArray = append(transformArray, cli.Command{
		Name:  "dumpdocs",
		Usage: "dumpdocs dumps the markdown documentation files for all transforms to the given directory.",
		Action: func(c *cli.Context) error {
			p, err := filepath.Abs(c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			os.MkdirAll(p, 0777)
			for key := range pipescript.TransformRegistry {
				t := pipescript.TransformRegistry[key]
				docs := t.Documentation
				if docs == "" {
					docs = "*This transform is currently undocumented. You can help out by [adding documentation](https://github.com/connectordb/pipescript/tree/master/resources/docs/transforms)*"
				}
				title := "# " + key + "\n\n"
				err = ioutil.WriteFile(filepath.Join(p, key+".md"), []byte(title+docs), 0644)
				if err != nil {
					log.Fatal(err)
				}
			}
			return nil
		},
	})

	for key := range pipescript.TransformRegistry {
		t := pipescript.TransformRegistry[key]
		desc := t.Description
		if len(desc) > 60 {
			desc = desc[0:60] + "..."
		}
		transformArray = append(transformArray, cli.Command{
			Name:  t.Name,
			Usage: desc,
			Action: func(c *cli.Context) error {
				b, err := json.MarshalIndent(t, "", "  ")
				if err != nil {
					log.Fatal(err)
				}
				fmt.Printf("%s\n", string(b))
				return nil
			},
		})
	}

	app.Commands = []cli.Command{
		{
			Name:    "transforms",
			Aliases: []string{"t"},
			Usage:   "Documentation for specific transforms",
			//Action:  createDatabaseCallback,
			Subcommands: transformArray,
		},
		{
			Name:    "run",
			Aliases: []string{"r"},
			Usage:   "Run a transform.",
			Action: func(c *cli.Context) {
				runner(c, c.Args().First())
			},
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "input,i",
					Value: "STDIN",
					Usage: "The input file to perform analysis on.",
				},
				cli.StringFlag{
					Name:  "output,o",
					Value: "STDOUT",
					Usage: "File to write as output",
				},
				cli.BoolFlag{
					Name:  "minify,m",
					Usage: "Whether to indent the json for easy reading",
				},
				cli.BoolFlag{
					Name:  "notimestamp",
					Usage: "If set, does not look for a timestamp field in input",
				},
				cli.StringFlag{
					Name:  "ifmt",
					Value: "dp",
					Usage: "The data format to use for input data (dp,csv,json)",
				},
				cli.StringFlag{
					Name:  "timestamp",
					Value: "",
					Usage: "Allows to explicitly set the field name to use for timestamp values",
				},
			},
		},
	}

	app.Run(os.Args)

}
<|endoftext|>


<commit_before>package api

import (
	"encoding/base64"
	"errors"
	"fmt"
	neturl "net/url"
	"time"

	"github.com/gin-gonic/gin"

	"github.com/sosedoff/pgweb/pkg/bookmarks"
	"github.com/sosedoff/pgweb/pkg/client"
	"github.com/sosedoff/pgweb/pkg/command"
	"github.com/sosedoff/pgweb/pkg/connection"
	"github.com/sosedoff/pgweb/pkg/shared"
)

var (
	DbClient   *client.Client
	DbSessions = map[string]*client.Client{}
)

func DB(c *gin.Context) *client.Client {
	if command.Opts.Sessions {
		return DbSessions[getSessionId(c.Request)]
	} else {
		return DbClient
	}
}

func setClient(c *gin.Context, newClient *client.Client) error {
	currentClient := DB(c)
	if currentClient != nil {
		currentClient.Close()
	}

	if !command.Opts.Sessions {
		DbClient = newClient
		return nil
	}

	sessionId := getSessionId(c.Request)
	if sessionId == "" {
		return errors.New("Session ID is required")
	}

	DbSessions[sessionId] = newClient
	return nil
}

func GetHome(c *gin.Context) {
	serveStaticAsset("/index.html", c)
}

func GetAsset(c *gin.Context) {
	serveStaticAsset(c.Params.ByName("path"), c)
}

func GetSessions(c *gin.Context) {
	// In debug mode endpoint will return a lot of sensitive information
	// like full database connection string and all query history.
	if command.Opts.Debug {
		c.JSON(200, DbSessions)
		return
	}

	c.JSON(200, map[string]int{"sessions": len(DbSessions)})
}

func Connect(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	var sshInfo *shared.SSHInfo
	url := c.Request.FormValue("url")

	if url == "" {
		c.JSON(400, Error{"Url parameter is required"})
		return
	}

	opts := command.Options{Url: url}
	url, err := connection.FormatUrl(opts)

	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	if c.Request.FormValue("ssh") != "" {
		sshInfo = parseSshInfo(c)
	}

	cl, err := client.NewFromUrl(url, sshInfo)
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	err = cl.Test()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	info, err := cl.Info()
	if err == nil {
		err = setClient(c, cl)
		if err != nil {
			cl.Close()
			c.JSON(400, Error{err.Error()})
			return
		}
	}

	c.JSON(200, info.Format()[0])
}

func SwitchDb(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	name := c.Request.URL.Query().Get("db")
	if name == "" {
		name = c.Request.FormValue("db")
	}
	if name == "" {
		c.JSON(400, Error{"Database name is not provided"})
		return
	}

	conn := DB(c)
	if conn == nil {
		c.JSON(400, Error{"Not connected"})
		return
	}

	currentUrl, err := neturl.Parse(conn.ConnectionString)
	if err != nil {
		c.JSON(400, Error{"Unable to parse current connection string"})
		return
	}

	currentUrl.Path = name

	cl, err := client.NewFromUrl(currentUrl.String(), nil)
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	err = cl.Test()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	info, err := cl.Info()
	if err == nil {
		err = setClient(c, cl)
		if err != nil {
			cl.Close()
			c.JSON(400, Error{err.Error()})
			return
		}
	}

	conn.Close()

	c.JSON(200, info.Format()[0])
}

func Disconnect(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	conn := DB(c)

	if conn == nil {
		c.JSON(400, Error{"Not connected"})
		return
	}

	err := conn.Close()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	c.JSON(200, map[string]bool{"success": true})
}

func GetDatabases(c *gin.Context) {
	names, err := DB(c).Databases()
	serveResult(names, err, c)
}

func GetObjects(c *gin.Context) {
	result, err := DB(c).Objects()
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	objects := client.ObjectsFromResult(result)
	c.JSON(200, objects)
}

func RunQuery(c *gin.Context) {
	query := cleanQuery(c.Request.FormValue("query"))

	if query == "" {
		c.JSON(400, NewError(errors.New("Query parameter is missing")))
		return
	}

	HandleQuery(query, c)
}

func ExplainQuery(c *gin.Context) {
	query := cleanQuery(c.Request.FormValue("query"))

	if query == "" {
		c.JSON(400, NewError(errors.New("Query parameter is missing")))
		return
	}

	HandleQuery(fmt.Sprintf("EXPLAIN ANALYZE %s", query), c)
}

func GetSchemas(c *gin.Context) {
	res, err := DB(c).Schemas()
	serveResult(res, err, c)
}

func GetTable(c *gin.Context) {
	var res *client.Result
	var err error

	if c.Request.FormValue("type") == "materialized_view" {
		res, err = DB(c).MaterializedView(c.Params.ByName("table"))
	} else {
		res, err = DB(c).Table(c.Params.ByName("table"))
	}

	serveResult(res, err, c)
}

func GetTableRows(c *gin.Context) {
	offset, err := parseIntFormValue(c, "offset", 0)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	limit, err := parseIntFormValue(c, "limit", 100)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	opts := client.RowsOptions{
		Limit:      limit,
		Offset:     offset,
		SortColumn: c.Request.FormValue("sort_column"),
		SortOrder:  c.Request.FormValue("sort_order"),
		Where:      c.Request.FormValue("where"),
	}

	res, err := DB(c).TableRows(c.Params.ByName("table"), opts)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	countRes, err := DB(c).TableRowsCount(c.Params.ByName("table"), opts)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	numFetch := int64(opts.Limit)
	numOffset := int64(opts.Offset)
	numRows := countRes.Rows[0][0].(int64)
	numPages := numRows / numFetch

	if numPages*numFetch < numRows {
		numPages++
	}

	res.Pagination = &client.Pagination{
		Rows:    numRows,
		Page:    (numOffset / numFetch) + 1,
		Pages:   numPages,
		PerPage: numFetch,
	}

	serveResult(res, err, c)
}

func GetTableInfo(c *gin.Context) {
	res, err := DB(c).TableInfo(c.Params.ByName("table"))

	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	c.JSON(200, res.Format()[0])
}

func GetHistory(c *gin.Context) {
	c.JSON(200, DB(c).History)
}

func GetConnectionInfo(c *gin.Context) {
	res, err := DB(c).Info()

	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	info := res.Format()[0]
	info["session_lock"] = command.Opts.LockSession

	c.JSON(200, info)
}

func GetActivity(c *gin.Context) {
	res, err := DB(c).Activity()
	serveResult(res, err, c)
}

func GetTableIndexes(c *gin.Context) {
	res, err := DB(c).TableIndexes(c.Params.ByName("table"))
	serveResult(res, err, c)
}

func GetTableConstraints(c *gin.Context) {
	res, err := DB(c).TableConstraints(c.Params.ByName("table"))
	serveResult(res, err, c)
}

func HandleQuery(query string, c *gin.Context) {
	rawQuery, err := base64.StdEncoding.DecodeString(desanitize64(query))
	if err == nil {
		query = string(rawQuery)
	}

	result, err := DB(c).Query(query)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	format := getQueryParam(c, "format")
	filename := getQueryParam(c, "filename")

	if filename == "" {
		filename = fmt.Sprintf("pgweb-%v.%v", time.Now().Unix(), format)
	}

	if format != "" {
		c.Writer.Header().Set("Content-disposition", "attachment;filename="+filename)
	}

	switch format {
	case "csv":
		c.Data(200, "text/csv", result.CSV())
	case "json":
		c.Data(200, "application/json", result.JSON())
	case "xml":
		c.XML(200, result)
	default:
		c.JSON(200, result)
	}
}

func GetBookmarks(c *gin.Context) {
	bookmarks, err := bookmarks.ReadAll(bookmarks.Path(command.Opts.BookmarksDir))
	serveResult(bookmarks, err, c)
}

func GetInfo(c *gin.Context) {
	info := map[string]string{
		"version":    command.VERSION,
		"git_sha":    command.GitCommit,
		"build_time": command.BuildTime,
	}

	c.JSON(200, info)
}
<commit_msg>api: properly check for errors<commit_after>package api

import (
	"encoding/base64"
	"errors"
	"fmt"
	neturl "net/url"
	"time"

	"github.com/gin-gonic/gin"

	"github.com/sosedoff/pgweb/pkg/bookmarks"
	"github.com/sosedoff/pgweb/pkg/client"
	"github.com/sosedoff/pgweb/pkg/command"
	"github.com/sosedoff/pgweb/pkg/connection"
	"github.com/sosedoff/pgweb/pkg/shared"
)

var (
	DbClient   *client.Client
	DbSessions = map[string]*client.Client{}
)

func DB(c *gin.Context) *client.Client {
	if command.Opts.Sessions {
		return DbSessions[getSessionId(c.Request)]
	} else {
		return DbClient
	}
}

func setClient(c *gin.Context, newClient *client.Client) error {
	currentClient := DB(c)
	if currentClient != nil {
		currentClient.Close()
	}

	if !command.Opts.Sessions {
		DbClient = newClient
		return nil
	}

	sessionId := getSessionId(c.Request)
	if sessionId == "" {
		return errors.New("Session ID is required")
	}

	DbSessions[sessionId] = newClient
	return nil
}

func GetHome(c *gin.Context) {
	serveStaticAsset("/index.html", c)
}

func GetAsset(c *gin.Context) {
	serveStaticAsset(c.Params.ByName("path"), c)
}

func GetSessions(c *gin.Context) {
	// In debug mode endpoint will return a lot of sensitive information
	// like full database connection string and all query history.
	if command.Opts.Debug {
		c.JSON(200, DbSessions)
		return
	}

	c.JSON(200, map[string]int{"sessions": len(DbSessions)})
}

func Connect(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	var sshInfo *shared.SSHInfo
	url := c.Request.FormValue("url")

	if url == "" {
		c.JSON(400, Error{"Url parameter is required"})
		return
	}

	opts := command.Options{Url: url}
	url, err := connection.FormatUrl(opts)

	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	if c.Request.FormValue("ssh") != "" {
		sshInfo = parseSshInfo(c)
	}

	cl, err := client.NewFromUrl(url, sshInfo)
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	err = cl.Test()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	info, err := cl.Info()
	if err == nil {
		err = setClient(c, cl)
	}
	if err != nil {
		cl.Close()
		c.JSON(400, Error{err.Error()})
		return
	}

	c.JSON(200, info.Format()[0])
}

func SwitchDb(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	name := c.Request.URL.Query().Get("db")
	if name == "" {
		name = c.Request.FormValue("db")
	}
	if name == "" {
		c.JSON(400, Error{"Database name is not provided"})
		return
	}

	conn := DB(c)
	if conn == nil {
		c.JSON(400, Error{"Not connected"})
		return
	}

	currentUrl, err := neturl.Parse(conn.ConnectionString)
	if err != nil {
		c.JSON(400, Error{"Unable to parse current connection string"})
		return
	}

	currentUrl.Path = name

	cl, err := client.NewFromUrl(currentUrl.String(), nil)
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	err = cl.Test()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	info, err := cl.Info()
	if err == nil {
		err = setClient(c, cl)
	}
	if err != nil {
		cl.Close()
		c.JSON(400, Error{err.Error()})
		return
	}

	conn.Close()

	c.JSON(200, info.Format()[0])
}

func Disconnect(c *gin.Context) {
	if command.Opts.LockSession {
		c.JSON(400, Error{"Session is locked"})
		return
	}

	conn := DB(c)

	if conn == nil {
		c.JSON(400, Error{"Not connected"})
		return
	}

	err := conn.Close()
	if err != nil {
		c.JSON(400, Error{err.Error()})
		return
	}

	c.JSON(200, map[string]bool{"success": true})
}

func GetDatabases(c *gin.Context) {
	names, err := DB(c).Databases()
	serveResult(names, err, c)
}

func GetObjects(c *gin.Context) {
	result, err := DB(c).Objects()
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	objects := client.ObjectsFromResult(result)
	c.JSON(200, objects)
}

func RunQuery(c *gin.Context) {
	query := cleanQuery(c.Request.FormValue("query"))

	if query == "" {
		c.JSON(400, NewError(errors.New("Query parameter is missing")))
		return
	}

	HandleQuery(query, c)
}

func ExplainQuery(c *gin.Context) {
	query := cleanQuery(c.Request.FormValue("query"))

	if query == "" {
		c.JSON(400, NewError(errors.New("Query parameter is missing")))
		return
	}

	HandleQuery(fmt.Sprintf("EXPLAIN ANALYZE %s", query), c)
}

func GetSchemas(c *gin.Context) {
	res, err := DB(c).Schemas()
	serveResult(res, err, c)
}

func GetTable(c *gin.Context) {
	var res *client.Result
	var err error

	if c.Request.FormValue("type") == "materialized_view" {
		res, err = DB(c).MaterializedView(c.Params.ByName("table"))
	} else {
		res, err = DB(c).Table(c.Params.ByName("table"))
	}

	serveResult(res, err, c)
}

func GetTableRows(c *gin.Context) {
	offset, err := parseIntFormValue(c, "offset", 0)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	limit, err := parseIntFormValue(c, "limit", 100)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	opts := client.RowsOptions{
		Limit:      limit,
		Offset:     offset,
		SortColumn: c.Request.FormValue("sort_column"),
		SortOrder:  c.Request.FormValue("sort_order"),
		Where:      c.Request.FormValue("where"),
	}

	res, err := DB(c).TableRows(c.Params.ByName("table"), opts)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	countRes, err := DB(c).TableRowsCount(c.Params.ByName("table"), opts)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	numFetch := int64(opts.Limit)
	numOffset := int64(opts.Offset)
	numRows := countRes.Rows[0][0].(int64)
	numPages := numRows / numFetch

	if numPages*numFetch < numRows {
		numPages++
	}

	res.Pagination = &client.Pagination{
		Rows:    numRows,
		Page:    (numOffset / numFetch) + 1,
		Pages:   numPages,
		PerPage: numFetch,
	}

	serveResult(res, err, c)
}

func GetTableInfo(c *gin.Context) {
	res, err := DB(c).TableInfo(c.Params.ByName("table"))

	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	c.JSON(200, res.Format()[0])
}

func GetHistory(c *gin.Context) {
	c.JSON(200, DB(c).History)
}

func GetConnectionInfo(c *gin.Context) {
	res, err := DB(c).Info()

	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	info := res.Format()[0]
	info["session_lock"] = command.Opts.LockSession

	c.JSON(200, info)
}

func GetActivity(c *gin.Context) {
	res, err := DB(c).Activity()
	serveResult(res, err, c)
}

func GetTableIndexes(c *gin.Context) {
	res, err := DB(c).TableIndexes(c.Params.ByName("table"))
	serveResult(res, err, c)
}

func GetTableConstraints(c *gin.Context) {
	res, err := DB(c).TableConstraints(c.Params.ByName("table"))
	serveResult(res, err, c)
}

func HandleQuery(query string, c *gin.Context) {
	rawQuery, err := base64.StdEncoding.DecodeString(desanitize64(query))
	if err == nil {
		query = string(rawQuery)
	}

	result, err := DB(c).Query(query)
	if err != nil {
		c.JSON(400, NewError(err))
		return
	}

	format := getQueryParam(c, "format")
	filename := getQueryParam(c, "filename")

	if filename == "" {
		filename = fmt.Sprintf("pgweb-%v.%v", time.Now().Unix(), format)
	}

	if format != "" {
		c.Writer.Header().Set("Content-disposition", "attachment;filename="+filename)
	}

	switch format {
	case "csv":
		c.Data(200, "text/csv", result.CSV())
	case "json":
		c.Data(200, "application/json", result.JSON())
	case "xml":
		c.XML(200, result)
	default:
		c.JSON(200, result)
	}
}

func GetBookmarks(c *gin.Context) {
	bookmarks, err := bookmarks.ReadAll(bookmarks.Path(command.Opts.BookmarksDir))
	serveResult(bookmarks, err, c)
}

func GetInfo(c *gin.Context) {
	info := map[string]string{
		"version":    command.VERSION,
		"git_sha":    command.GitCommit,
		"build_time": command.BuildTime,
	}

	c.JSON(200, info)
}
<|endoftext|>


<commit_before>// Package run manages Read, Write and Signal goroutines.
package run

import (
	"context"
	"fmt"
	"os"

	"github.com/mediocregopher/radix/v3"
	"golang.org/x/sync/errgroup"

	"github.com/stickermule/rump/pkg/config"
	"github.com/stickermule/rump/pkg/file"
	"github.com/stickermule/rump/pkg/message"
	"github.com/stickermule/rump/pkg/redis"
	"github.com/stickermule/rump/pkg/signal"
)

// Exit helper
func exit(e error) {
	fmt.Println(e)
	os.Exit(1)
}

// Run orchestrate the Reader, Writer and Signal handler.
func Run(cfg config.Config) {
	// create ErrGroup to manage goroutines
	ctx, cancel := context.WithCancel(context.Background())
	g, gctx := errgroup.WithContext(ctx)

	// Start signal handling goroutine
	g.Go(func() error {
		return signal.Run(gctx, cancel)
	})

	// Create shared message bus
	ch := make(message.Bus, 100)

	// Create and run either a Redis or File Source reader.
	if cfg.Source.IsRedis {
		db, err := radix.NewPool("tcp", cfg.Source.URI, 1)
		if err != nil {
			exit(err)
		}
		source := redis.New(db, ch)
		g.Go(func() error {
			return source.Read()
		})
	} else {
		source := file.New(cfg.Source.URI, ch)
		g.Go(func() error {
			return source.Read()
		})
	}

	// Create and run either a Redis or File Target writer.
	if cfg.Target.IsRedis {
		db, err := radix.NewPool("tcp", cfg.Target.URI, 1)
		if err != nil {
			exit(err)
		}
		target := redis.New(db, ch)
		g.Go(func() error {
			defer cancel()
			return target.Write()
		})
	} else {
		target := file.New(cfg.Target.URI, ch)
		g.Go(func() error {
			defer cancel()
			return target.Write()
		})
	}

	// Block and wait for goroutines
	err := g.Wait()
	if err != nil && err != context.Canceled {
		fmt.Printf("error: %v\n", err)
		os.Exit(1)
	} else {
		fmt.Println("done")
	}
}
<commit_msg>style: add line breaks<commit_after>// Package run manages Read, Write and Signal goroutines.
package run

import (
	"context"
	"fmt"
	"os"

	"github.com/mediocregopher/radix/v3"
	"golang.org/x/sync/errgroup"

	"github.com/stickermule/rump/pkg/config"
	"github.com/stickermule/rump/pkg/file"
	"github.com/stickermule/rump/pkg/message"
	"github.com/stickermule/rump/pkg/redis"
	"github.com/stickermule/rump/pkg/signal"
)

// Exit helper
func exit(e error) {
	fmt.Println(e)
	os.Exit(1)
}

// Run orchestrate the Reader, Writer and Signal handler.
func Run(cfg config.Config) {
	// create ErrGroup to manage goroutines
	ctx, cancel := context.WithCancel(context.Background())
	g, gctx := errgroup.WithContext(ctx)

	// Start signal handling goroutine
	g.Go(func() error {
		return signal.Run(gctx, cancel)
	})

	// Create shared message bus
	ch := make(message.Bus, 100)

	// Create and run either a Redis or File Source reader.
	if cfg.Source.IsRedis {
		db, err := radix.NewPool("tcp", cfg.Source.URI, 1)
		if err != nil {
			exit(err)
		}

		source := redis.New(db, ch)

		g.Go(func() error {
			return source.Read()
		})
	} else {
		source := file.New(cfg.Source.URI, ch)

		g.Go(func() error {
			return source.Read()
		})
	}

	// Create and run either a Redis or File Target writer.
	if cfg.Target.IsRedis {
		db, err := radix.NewPool("tcp", cfg.Target.URI, 1)
		if err != nil {
			exit(err)
		}

		target := redis.New(db, ch)

		g.Go(func() error {
			defer cancel()
			return target.Write()
		})
	} else {
		target := file.New(cfg.Target.URI, ch)

		g.Go(func() error {
			defer cancel()
			return target.Write()
		})
	}

	// Block and wait for goroutines
	err := g.Wait()
	if err != nil && err != context.Canceled {
		fmt.Printf("error: %v\n", err)
		os.Exit(1)
	} else {
		fmt.Println("done")
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2022, the Drone Plugins project authors.
// Please see the AUTHORS file for details. All rights reserved.
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.

package plugin

import (
	"encoding/base64"
	"encoding/json"
	"io"
	"io/ioutil"
	"os"
)

func writeCard(path string, card interface{}) {
	data, _ := json.Marshal(card)
	switch {
	case path == "/dev/stdout":
		writeCardTo(os.Stdout, data)
	case path == "/dev/stderr":
		writeCardTo(os.Stderr, data)
	case path != "":
		ioutil.WriteFile(path, data, 0644)
	}
}

func writeCardTo(out io.Writer, data []byte) {
	encoded := base64.StdEncoding.EncodeToString(data)
	io.WriteString(out, "\u001B]1338;")
	io.WriteString(out, encoded)
	io.WriteString(out, "\u001B]0m")
	io.WriteString(out, "\n")
}
<commit_msg>Fix lints in util.og<commit_after>// Copyright (c) 2022, the Drone Plugins project authors.
// Please see the AUTHORS file for details. All rights reserved.
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.

package plugin

import (
	"encoding/base64"
	"encoding/json"
	"io"
	"os"
)

//nolint:errcheck
func writeCard(path string, card interface{}) {
	data, _ := json.Marshal(card)
	switch {
	case path == "/dev/stdout":
		writeCardTo(os.Stdout, data)
	case path == "/dev/stderr":
		writeCardTo(os.Stderr, data)
	case path != "":
		os.WriteFile(path, data, 0644) //nolint:gomnd
	}
}

//nolint:errcheck
func writeCardTo(out io.Writer, data []byte) {
	encoded := base64.StdEncoding.EncodeToString(data)
	io.WriteString(out, "\u001B]1338;")
	io.WriteString(out, encoded)
	io.WriteString(out, "\u001B]0m")
	io.WriteString(out, "\n")
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	restful "github.com/emicklei/go-restful"
	"github.com/emicklei/go-restful/swagger"
	"github.com/garyburd/redigo/redis"
	"github.com/the42/ogdat/database"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

const AppID = "5bcbfc24-8e7e-4105-99c4-dd47e7e5094a"
const watcherappid = "a6545f8f-e0c9-4917-83c7-3e47bd1e0247"

var logger *log.Logger

type analyser struct {
	dbcon analyserdb
	pool  *redis.Pool
}

func NewAnalyser(dbcon *sql.DB, pool *redis.Pool) *analyser {
	analyser := &analyser{dbcon: analyserdb{DBConn: database.DBConn{Appid: AppID, DBer: dbcon}}, pool: pool}
	return analyser
}

func isonlyweb() bool {
	boolval, err := strconv.ParseBool(os.Getenv("ONLYWEB"))
	if err != nil {
		return false
	}
	return boolval
}

func getredisconnect() string {
	const redisurl = "REDISCLOUD_URL"
	const redisdb = "ANALYSER_REDISDB"

	return os.Getenv(redisurl) + "/" + os.Getenv(redisdb)
}

func portbinding() string {
	if port := os.Getenv("PORT"); port != "" {
		return port
	}
	return "8080"
}

func discoveryhost() string {
	if host := os.Getenv("DISCOVERYURL"); host != "" {
		return host
	}
	return "http://localhost"
}

func apibasepath() string {
	if basepath := os.Getenv("APIBASEPATH"); basepath != "" {
		return basepath
	}
	return "/api"
}

func getheartbeatinterval() int {

	if i, err := strconv.Atoi(os.Getenv("HEARTBEAT_INTERVAL")); err == nil {
		return i
	}
	return 60 // Minutes
}

func heartbeat(interval int) chan bool {
	retchan := make(chan bool)
	go func() {
		for {
			dbconn, err := database.GetDatabaseConnection()
			if err != nil {
				logger.Panicln(err)
			}
			db := &database.DBConn{DBer: dbconn, Appid: AppID}
			if err := db.HeartBeat(); err != nil {
				logger.Panicln(err)
			}
			dbconn.Close()
			logger.Printf("Watchdog beating every %d minute\n", interval)
			retchan <- true
			time.Sleep(time.Duration(interval) * time.Minute)
		}
	}()
	return retchan
}

func main() {
	dbcon, err := database.GetDatabaseConnection()
	if err != nil {
		logger.Panicln(err)
	}
	defer dbcon.Close()
	analyser := NewAnalyser(dbcon, redis.NewPool(func() (redis.Conn, error) { return database.GetRedisConnection(getredisconnect()) }, 10))

	var datachange, urlchange chan []byte
	var heartbeatchannel chan bool

	if !isonlyweb() {
		heartbeatchannel = heartbeat(getheartbeatinterval())

		<-heartbeatchannel // Wait for the first heartbeat, so the logging in the database is properly set up
		if err := analyser.populatedatasetinfo(); err != nil {
			logger.Panicln(err)
		}
		datachange = analyser.listenredischannel(watcherappid + ":DataChange")
		urlchange = analyser.listenredischannel(watcherappid + ":UrlChange")
	}

	restful.DefaultResponseMimeType = restful.MIME_JSON
	restful.EnableContentEncoding = true
	restful.Add(NewAnalyseOGDATRESTService(analyser))

	config := swagger.Config{
		WebServicesUrl:  discoveryhost(),
		ApiPath:         "/swaggerdoc",
		SwaggerPath:     "/doc/",
		SwaggerFilePath: "swagger-ui/dist/",
		WebServices:     restful.RegisteredWebServices()} // you control what services are visible
	swagger.InstallSwaggerService(config)

	logger.Printf("analyser (%s) listening on port %s\n", AppID, portbinding())
	go logger.Fatal(http.ListenAndServe(":"+portbinding(), nil))

	if !isonlyweb() {
		populatedatasetinfo := func() {
			if err := analyser.populatedatasetinfo(); err != nil {
				logger.Panicln(err)
			}
		}
		for {
			select {
			case <-urlchange:
				populatedatasetinfo()
			case <-datachange:
				populatedatasetinfo()
			case <-heartbeatchannel:
				logger.Println("Idle")
			}
		}
	}
}

func init() {
	logger = log.New(os.Stderr, filepath.Base(os.Args[0])+": ", log.LstdFlags)
}
<commit_msg>an API base path may be empty<commit_after>package main

import (
	"database/sql"
	restful "github.com/emicklei/go-restful"
	"github.com/emicklei/go-restful/swagger"
	"github.com/garyburd/redigo/redis"
	"github.com/the42/ogdat/database"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

const AppID = "5bcbfc24-8e7e-4105-99c4-dd47e7e5094a"
const watcherappid = "a6545f8f-e0c9-4917-83c7-3e47bd1e0247"

var logger *log.Logger

type analyser struct {
	dbcon analyserdb
	pool  *redis.Pool
}

func NewAnalyser(dbcon *sql.DB, pool *redis.Pool) *analyser {
	analyser := &analyser{dbcon: analyserdb{DBConn: database.DBConn{Appid: AppID, DBer: dbcon}}, pool: pool}
	return analyser
}

func isonlyweb() bool {
	boolval, err := strconv.ParseBool(os.Getenv("ONLYWEB"))
	if err != nil {
		return false
	}
	return boolval
}

func getredisconnect() string {
	const redisurl = "REDISCLOUD_URL"
	const redisdb = "ANALYSER_REDISDB"

	return os.Getenv(redisurl) + "/" + os.Getenv(redisdb)
}

func portbinding() string {
	if port := os.Getenv("PORT"); port != "" {
		return port
	}
	return "8080"
}

func discoveryhost() string {
	if host := os.Getenv("DISCOVERYURL"); host != "" {
		return host
	}
	return "http://localhost"
}

func apibasepath() string {
	return os.Getenv("APIBASEPATH")
}

func getheartbeatinterval() int {

	if i, err := strconv.Atoi(os.Getenv("HEARTBEAT_INTERVAL")); err == nil {
		return i
	}
	return 60 // Minutes
}

func heartbeat(interval int) chan bool {
	retchan := make(chan bool)
	go func() {
		for {
			dbconn, err := database.GetDatabaseConnection()
			if err != nil {
				logger.Panicln(err)
			}
			db := &database.DBConn{DBer: dbconn, Appid: AppID}
			if err := db.HeartBeat(); err != nil {
				logger.Panicln(err)
			}
			dbconn.Close()
			logger.Printf("Watchdog beating every %d minute\n", interval)
			retchan <- true
			time.Sleep(time.Duration(interval) * time.Minute)
		}
	}()
	return retchan
}

func main() {
	dbcon, err := database.GetDatabaseConnection()
	if err != nil {
		logger.Panicln(err)
	}
	defer dbcon.Close()
	analyser := NewAnalyser(dbcon, redis.NewPool(func() (redis.Conn, error) { return database.GetRedisConnection(getredisconnect()) }, 10))

	var datachange, urlchange chan []byte
	var heartbeatchannel chan bool

	if !isonlyweb() {
		heartbeatchannel = heartbeat(getheartbeatinterval())

		<-heartbeatchannel // Wait for the first heartbeat, so the logging in the database is properly set up
		if err := analyser.populatedatasetinfo(); err != nil {
			logger.Panicln(err)
		}
		datachange = analyser.listenredischannel(watcherappid + ":DataChange")
		urlchange = analyser.listenredischannel(watcherappid + ":UrlChange")
	}

	restful.DefaultResponseMimeType = restful.MIME_JSON
	restful.EnableContentEncoding = true
	restful.Add(NewAnalyseOGDATRESTService(analyser))

	config := swagger.Config{
		WebServicesUrl:  discoveryhost(),
		ApiPath:         "/swaggerdoc",
		SwaggerPath:     "/doc/",
		SwaggerFilePath: "swagger-ui/dist/",
		WebServices:     restful.RegisteredWebServices()} // you control what services are visible
	swagger.InstallSwaggerService(config)

	logger.Printf("analyser (%s) listening on port %s\n", AppID, portbinding())
	go logger.Fatal(http.ListenAndServe(":"+portbinding(), nil))

	if !isonlyweb() {
		populatedatasetinfo := func() {
			if err := analyser.populatedatasetinfo(); err != nil {
				logger.Panicln(err)
			}
		}
		for {
			select {
			case <-urlchange:
				populatedatasetinfo()
			case <-datachange:
				populatedatasetinfo()
			case <-heartbeatchannel:
				logger.Println("Idle")
			}
		}
	}
}

func init() {
	logger = log.New(os.Stderr, filepath.Base(os.Args[0])+": ", log.LstdFlags)
}
<|endoftext|>


<commit_before>package acl

import (
	"fmt"

	"github.com/armon/go-radix"
)

var (
	// allowAll is a singleton policy which allows all actions
	allowAll ACL

	// denyAll is a singleton policy which denies all actions
	denyAll ACL
)

func init() {
	// Setup the singletons
	allowAll = &StaticACL{defaultAllow: true}
	denyAll = &StaticACL{defaultAllow: false}
}

// ACL is the interface for policy enforcement.
type ACL interface {
	KeyRead(string) bool
	KeyWrite(string) bool
}

// StaticACL is used to implement a base ACL policy. It either
// allows or denies all requests. This can be used as a parent
// ACL to act in a blacklist or whitelist mode.
type StaticACL struct {
	defaultAllow bool
}

func (s *StaticACL) KeyRead(string) bool {
	return s.defaultAllow
}

func (s *StaticACL) KeyWrite(string) bool {
	return s.defaultAllow
}

// AllowAll returns an ACL rule that allows all operations
func AllowAll() ACL {
	return allowAll
}

// DenyAll returns an ACL rule that denies all operations
func DenyAll() ACL {
	return denyAll
}

// PolicyACL is used to wrap a set of ACL policies to provide
// the ACL interface.
type PolicyACL struct {
	// parent is used to resolve policy if we have
	// no matching rule.
	parent ACL

	// keyRead contains the read policies
	keyRead *radix.Tree

	// keyWrite contains the write policies
	keyWrite *radix.Tree
}

// New is used to construct a policy based ACL from a set of policies
// and a parent policy to resolve missing cases.
func New(parent ACL, policy *Policy) (*PolicyACL, error) {
	p := &PolicyACL{
		parent:   parent,
		keyRead:  radix.New(),
		keyWrite: radix.New(),
	}

	// Load the key policy
	for _, kp := range policy.Keys {
		switch kp.Policy {
		case KeyPolicyDeny:
			p.keyRead.Insert(kp.Prefix, false)
			p.keyWrite.Insert(kp.Prefix, false)
		case KeyPolicyRead:
			p.keyRead.Insert(kp.Prefix, true)
			p.keyWrite.Insert(kp.Prefix, false)
		case KeyPolicyWrite:
			p.keyRead.Insert(kp.Prefix, true)
			p.keyWrite.Insert(kp.Prefix, true)
		default:
			return nil, fmt.Errorf("Invalid key policy: %#v", kp)
		}
	}
	return p, nil
}

// KeyRead returns if a key is allowed to be read
func (p *PolicyACL) KeyRead(key string) bool {
	// Look for a matching rule
	_, rule, ok := p.keyRead.LongestPrefix(key)
	if ok {
		return rule.(bool)
	}

	// No matching rule, use the parent.
	return p.parent.KeyRead(key)
}

// KeyWrite returns if a key is allowed to be written
func (p *PolicyACL) KeyWrite(key string) bool {
	// Look for a matching rule
	_, rule, ok := p.keyWrite.LongestPrefix(key)
	if ok {
		return rule.(bool)
	}

	// No matching rule, use the parent.
	return p.parent.KeyWrite(key)
}
<commit_msg>acl: Use only a single Radix tree per ACL<commit_after>package acl

import (
	"github.com/armon/go-radix"
)

var (
	// allowAll is a singleton policy which allows all actions
	allowAll ACL

	// denyAll is a singleton policy which denies all actions
	denyAll ACL
)

func init() {
	// Setup the singletons
	allowAll = &StaticACL{defaultAllow: true}
	denyAll = &StaticACL{defaultAllow: false}
}

// ACL is the interface for policy enforcement.
type ACL interface {
	KeyRead(string) bool
	KeyWrite(string) bool
}

// StaticACL is used to implement a base ACL policy. It either
// allows or denies all requests. This can be used as a parent
// ACL to act in a blacklist or whitelist mode.
type StaticACL struct {
	defaultAllow bool
}

func (s *StaticACL) KeyRead(string) bool {
	return s.defaultAllow
}

func (s *StaticACL) KeyWrite(string) bool {
	return s.defaultAllow
}

// AllowAll returns an ACL rule that allows all operations
func AllowAll() ACL {
	return allowAll
}

// DenyAll returns an ACL rule that denies all operations
func DenyAll() ACL {
	return denyAll
}

// PolicyACL is used to wrap a set of ACL policies to provide
// the ACL interface.
type PolicyACL struct {
	// parent is used to resolve policy if we have
	// no matching rule.
	parent ACL

	// keyRules contains the key policies
	keyRules *radix.Tree
}

// New is used to construct a policy based ACL from a set of policies
// and a parent policy to resolve missing cases.
func New(parent ACL, policy *Policy) (*PolicyACL, error) {
	p := &PolicyACL{
		parent:   parent,
		keyRules: radix.New(),
	}

	// Load the key policy
	for _, kp := range policy.Keys {
		p.keyRules.Insert(kp.Prefix, kp.Policy)
	}
	return p, nil
}

// KeyRead returns if a key is allowed to be read
func (p *PolicyACL) KeyRead(key string) bool {
	// Look for a matching rule
	_, rule, ok := p.keyRules.LongestPrefix(key)
	if ok {
		switch rule.(string) {
		case KeyPolicyRead:
			return true
		case KeyPolicyWrite:
			return true
		default:
			return false
		}
	}

	// No matching rule, use the parent.
	return p.parent.KeyRead(key)
}

// KeyWrite returns if a key is allowed to be written
func (p *PolicyACL) KeyWrite(key string) bool {
	// Look for a matching rule
	_, rule, ok := p.keyRules.LongestPrefix(key)
	if ok {
		switch rule.(string) {
		case KeyPolicyWrite:
			return true
		default:
			return false
		}
	}

	// No matching rule, use the parent.
	return p.parent.KeyWrite(key)
}
<|endoftext|>