<commit_before>// Copyright 2016 TiKV Project Authors.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package pdctl

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/chzyer/readline"
	"github.com/mattn/go-shellwords"
	"github.com/spf13/cobra"
	"github.com/tikv/pd/server"
	"github.com/tikv/pd/tools/pd-ctl/pdctl/command"
)

var (
	readlineCompleter *readline.PrefixCompleter
)

func init() {
	cobra.EnablePrefixMatching = true
}

// GetRootCmd is exposed for integration tests. But it can be embedded into another suite, too.
func GetRootCmd() *cobra.Command {
	rootCmd := &cobra.Command{
		Use:   "pd-ctl",
		Short: "Placement Driver control",
	}

	rootCmd.PersistentFlags().StringP("pd", "u", "http://127.0.0.1:2379", "address of pd")
	rootCmd.PersistentFlags().String("cacert", "", "path of file that contains list of trusted SSL CAs")
	rootCmd.PersistentFlags().String("cert", "", "path of file that contains X509 certificate in PEM format")
	rootCmd.PersistentFlags().String("key", "", "path of file that contains X509 key in PEM format")

	rootCmd.AddCommand(
		command.NewConfigCommand(),
		command.NewRegionCommand(),
		command.NewStoreCommand(),
		command.NewStoresCommand(),
		command.NewMemberCommand(),
		command.NewExitCommand(),
		command.NewLabelCommand(),
		command.NewPingCommand(),
		command.NewOperatorCommand(),
		command.NewSchedulerCommand(),
		command.NewTSOCommand(),
		command.NewHotSpotCommand(),
		command.NewClusterCommand(),
		command.NewHealthCommand(),
		command.NewLogCommand(),
		command.NewPluginCommand(),
		command.NewServiceGCSafepointCommand(),
		command.NewCompletionCommand(),
	)

	rootCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
	rootCmd.SilenceErrors = true

	rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
		CAPath, err := cmd.Flags().GetString("cacert")
		if err == nil && len(CAPath) != 0 {
			certPath, err := cmd.Flags().GetString("cert")
			if err != nil {
				return err
			}

			keyPath, err := cmd.Flags().GetString("key")
			if err != nil {
				return err
			}

			if err := command.InitHTTPSClient(CAPath, certPath, keyPath); err != nil {
				rootCmd.Println(err)
				return err
			}
		}
		return nil
	}

	return rootCmd
}

// MainStart start main command
func MainStart(args []string) {
	rootCmd := GetRootCmd()

	rootCmd.Flags().BoolP("interact", "i", false, "Run pdctl with readline.")
	rootCmd.Flags().BoolP("version", "V", false, "Print version information and exit.")
	// TODO: deprecated
	rootCmd.Flags().BoolP("detach", "d", true, "Run pdctl without readline.")

	rootCmd.Run = func(cmd *cobra.Command, args []string) {
		if v, err := cmd.Flags().GetBool("version"); err == nil && v {
			server.PrintPDInfo()
			return
		}
		if v, err := cmd.Flags().GetBool("interact"); err == nil && v {
			loop()
		}
	}

	rootCmd.SetArgs(args)
	rootCmd.ParseFlags(args)
	rootCmd.SetOutput(os.Stdout)

	readlineCompleter = readline.NewPrefixCompleter(genCompleter(rootCmd)...)

	if err := rootCmd.Execute(); err != nil {
		rootCmd.Println(err)
		os.Exit(1)
	}
}

func loop() {
	l, err := readline.NewEx(&readline.Config{
		Prompt:            "\033[31m»\033[0m ",
		HistoryFile:       "/tmp/readline.tmp",
		AutoComplete:      readlineCompleter,
		InterruptPrompt:   "^C",
		EOFPrompt:         "^D",
		HistorySearchFold: true,
	})
	if err != nil {
		panic(err)
	}
	defer l.Close()

	rootCmd := GetRootCmd()
	rootCmd.SetOutput(os.Stdout)

	for {
		line, err := l.Readline()
		if err != nil {
			if err == readline.ErrInterrupt {
				break
			} else if err == io.EOF {
				break
			}
			continue
		}
		if line == "exit" {
			os.Exit(0)
		}
		args, err := shellwords.Parse(line)
		if err != nil {
			fmt.Printf("parse command err: %v\n", err)
			continue
		}

		rootCmd.SetArgs(args)
		rootCmd.ParseFlags(args)

		if err := rootCmd.Execute(); err != nil {
			rootCmd.Println(err)
			os.Exit(1)
		}
	}
}

func genCompleter(cmd *cobra.Command) []readline.PrefixCompleterInterface {
	pc := []readline.PrefixCompleterInterface{}

	for _, v := range cmd.Commands() {
		if v.HasFlags() {
			flagsPc := []readline.PrefixCompleterInterface{}
			flagUsages := strings.Split(strings.Trim(v.Flags().FlagUsages(), " "), "\n")
			for i := 0; i < len(flagUsages)-1; i++ {
				flagsPc = append(flagsPc, readline.PcItem(strings.Split(strings.Trim(flagUsages[i], " "), " ")[0]))
			}
			flagsPc = append(flagsPc, genCompleter(v)...)
			pc = append(pc, readline.PcItem(strings.Split(v.Use, " ")[0], flagsPc...))
		} else {
			pc = append(pc, readline.PcItem(strings.Split(v.Use, " ")[0], genCompleter(v)...))
		}
	}
	return pc
}
<commit_msg>pd-ctl: try to fix interactive mode (#3782)<commit_after>// Copyright 2016 TiKV Project Authors.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package pdctl

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/chzyer/readline"
	"github.com/mattn/go-shellwords"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/tikv/pd/server"
	"github.com/tikv/pd/tools/pd-ctl/pdctl/command"
)

func init() {
	cobra.EnablePrefixMatching = true
}

// GetRootCmd is exposed for integration tests. But it can be embedded into another suite, too.
func GetRootCmd() *cobra.Command {
	rootCmd := &cobra.Command{
		Use:   "pd-ctl",
		Short: "Placement Driver control",
	}

	rootCmd.PersistentFlags().StringP("pd", "u", "http://127.0.0.1:2379", "address of pd")
	rootCmd.PersistentFlags().String("cacert", "", "path of file that contains list of trusted SSL CAs")
	rootCmd.PersistentFlags().String("cert", "", "path of file that contains X509 certificate in PEM format")
	rootCmd.PersistentFlags().String("key", "", "path of file that contains X509 key in PEM format")

	rootCmd.AddCommand(
		command.NewConfigCommand(),
		command.NewRegionCommand(),
		command.NewStoreCommand(),
		command.NewStoresCommand(),
		command.NewMemberCommand(),
		command.NewExitCommand(),
		command.NewLabelCommand(),
		command.NewPingCommand(),
		command.NewOperatorCommand(),
		command.NewSchedulerCommand(),
		command.NewTSOCommand(),
		command.NewHotSpotCommand(),
		command.NewClusterCommand(),
		command.NewHealthCommand(),
		command.NewLogCommand(),
		command.NewPluginCommand(),
		command.NewServiceGCSafepointCommand(),
		command.NewCompletionCommand(),
	)

	rootCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
	rootCmd.SilenceErrors = true

	rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
		CAPath, err := cmd.Flags().GetString("cacert")
		if err == nil && len(CAPath) != 0 {
			certPath, err := cmd.Flags().GetString("cert")
			if err != nil {
				return err
			}

			keyPath, err := cmd.Flags().GetString("key")
			if err != nil {
				return err
			}

			if err := command.InitHTTPSClient(CAPath, certPath, keyPath); err != nil {
				rootCmd.Println(err)
				return err
			}
		}
		return nil
	}

	return rootCmd
}

// MainStart start main command
func MainStart(args []string) {
	rootCmd := GetRootCmd()

	rootCmd.Flags().BoolP("interact", "i", false, "Run pdctl with readline.")
	rootCmd.Flags().BoolP("version", "V", false, "Print version information and exit.")
	// TODO: deprecated
	rootCmd.Flags().BoolP("detach", "d", true, "Run pdctl without readline.")

	rootCmd.Run = func(cmd *cobra.Command, args []string) {
		if v, err := cmd.Flags().GetBool("version"); err == nil && v {
			server.PrintPDInfo()
			return
		}
		if v, err := cmd.Flags().GetBool("interact"); err == nil && v {
			readlineCompleter := readline.NewPrefixCompleter(genCompleter(cmd)...)
			loop(cmd.PersistentFlags(), readlineCompleter)
		}
	}

	rootCmd.SetArgs(args)
	rootCmd.ParseFlags(args)
	rootCmd.SetOutput(os.Stdout)

	if err := rootCmd.Execute(); err != nil {
		rootCmd.Println(err)
		os.Exit(1)
	}
}

func loop(persistentFlags *pflag.FlagSet, readlineCompleter readline.AutoCompleter) {
	l, err := readline.NewEx(&readline.Config{
		Prompt:            "\033[31m»\033[0m ",
		HistoryFile:       "/tmp/readline.tmp",
		AutoComplete:      readlineCompleter,
		InterruptPrompt:   "^C",
		EOFPrompt:         "^D",
		HistorySearchFold: true,
	})
	if err != nil {
		panic(err)
	}
	defer l.Close()

	getREPLCmd := func() *cobra.Command {
		rootCmd := GetRootCmd()
		persistentFlags.VisitAll(func(flag *pflag.Flag) {
			if flag.Changed {
				rootCmd.PersistentFlags().Set(flag.Name, flag.Value.String())
			}
		})
		rootCmd.LocalFlags().MarkHidden("pd")
		rootCmd.LocalFlags().MarkHidden("cacert")
		rootCmd.LocalFlags().MarkHidden("cert")
		rootCmd.LocalFlags().MarkHidden("key")
		rootCmd.SetOutput(os.Stdout)
		return rootCmd
	}

	for {
		line, err := l.Readline()
		if err != nil {
			if err == readline.ErrInterrupt {
				break
			} else if err == io.EOF {
				break
			}
			continue
		}
		if line == "exit" {
			os.Exit(0)
		}
		args, err := shellwords.Parse(line)
		if err != nil {
			fmt.Printf("parse command err: %v\n", err)
			continue
		}

		rootCmd := getREPLCmd()
		rootCmd.SetArgs(args)
		rootCmd.ParseFlags(args)
		if err := rootCmd.Execute(); err != nil {
			rootCmd.Println(err)
		}
	}
}

func genCompleter(cmd *cobra.Command) []readline.PrefixCompleterInterface {
	pc := []readline.PrefixCompleterInterface{}

	for _, v := range cmd.Commands() {
		if v.HasFlags() {
			flagsPc := []readline.PrefixCompleterInterface{}
			flagUsages := strings.Split(strings.Trim(v.Flags().FlagUsages(), " "), "\n")
			for i := 0; i < len(flagUsages)-1; i++ {
				flagsPc = append(flagsPc, readline.PcItem(strings.Split(strings.Trim(flagUsages[i], " "), " ")[0]))
			}
			flagsPc = append(flagsPc, genCompleter(v)...)
			pc = append(pc, readline.PcItem(strings.Split(v.Use, " ")[0], flagsPc...))
		} else {
			pc = append(pc, readline.PcItem(strings.Split(v.Use, " ")[0], genCompleter(v)...))
		}
	}
	return pc
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel

import (
	"testing"
	"time"

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

type mockIncomingCall struct {
	callerName string
}

func (m *mockIncomingCall) CallerName() string {
	return m.callerName
}

var (
	cn = "hello"
)

func TestWrapContextForTest(t *testing.T) {
	call := &mockIncomingCall{callerName: cn}
	ctx, cancel := NewContext(time.Second)
	defer cancel()
	actual := WrapContextForTest(ctx, call)
	assert.Equal(t, call, CurrentCall(actual), "Incorrect call object returned.")
}

func TestCurrentCallWithNilResult(t *testing.T) {
	ctx, cancel := NewContext(time.Second)
	defer cancel()
	call := CurrentCall(ctx)
	assert.Nil(t, call, "Should return nil.")
}
<commit_msg>Update context_test to use testutils/FakeIncomingCall<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel_test

import (
	"testing"
	"time"

	. "github.com/uber/tchannel/golang"

	"github.com/stretchr/testify/assert"
	"github.com/uber/tchannel/golang/testutils"
)

var cn = "hello"

func TestWrapContextForTest(t *testing.T) {
	call := testutils.NewIncomingCall(cn)
	ctx, cancel := NewContext(time.Second)
	defer cancel()
	actual := WrapContextForTest(ctx, call)
	assert.Equal(t, call, CurrentCall(actual), "Incorrect call object returned.")
}

func TestCurrentCallWithNilResult(t *testing.T) {
	ctx, cancel := NewContext(time.Second)
	defer cancel()
	call := CurrentCall(ctx)
	assert.Nil(t, call, "Should return nil.")
}
<|endoftext|>


<commit_before>package ipfs

import (
	"bytes"
	"context"
	"encoding/base64"
	"errors"
	"golang.org/x/net/proxy"
	"io/ioutil"
	"net/http"
	"time"

	"gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid"
	peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer"
	routing "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing"
	ropts "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing/options"
	pstore "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore"
)

var apiRouterHTTPClient = &http.Client{
	Timeout: time.Second * 30,
}

// ensure APIRouter satisfies the interface
var _ routing.IpfsRouting = &APIRouter{}

// ErrNotStarted is returned if a method is called before the router
// is started using the Start() method.
var ErrNotStarted = errors.New("API router not started")

// APIRouter is a routing.IpfsRouting compliant struct backed by an API. It only
// provides the features offerened by routing.ValueStore and marks the others as
// unsupported.
type APIRouter struct {
	uri     string
	started chan (struct{})
}

// NewAPIRouter creates a new APIRouter backed by the given URI.
func NewAPIRouter(uri string) APIRouter {
	return APIRouter{uri: uri, started: make(chan (struct{}))}
}

func (r *APIRouter) Start(proxyDialer proxy.Dialer) {
	if proxyDialer != nil {
		tbTransport := &http.Transport{Dial: proxyDialer.Dial}
		apiRouterHTTPClient.Transport = tbTransport
	}
	close(r.started)
}

// Bootstrap is a no-op. We don't need any setup to query the API.
func (r APIRouter) Bootstrap(_ context.Context) error {
	return nil
}

// PutValue writes the given value to the API for the given key
func (r APIRouter) PutValue(ctx context.Context, key string, value []byte, opts ...ropts.Option) error {
    select {
        case <- r.started:
        default:
            return ErrNotStarted
    }

	req, err := http.NewRequest("PUT", r.pathForKey(key), bytes.NewBuffer(value))
	if err != nil {
		return err
	}

	_, err = apiRouterHTTPClient.Do(req)
	return err
}

// GetValue reads the value for the given key
func (r APIRouter) GetValue(ctx context.Context, key string, opts ...ropts.Option) ([]byte, error) {
    select {
        case <- r.started:
        default:
            return nil, ErrNotStarted
    }

	resp, err := apiRouterHTTPClient.Get(r.pathForKey(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

// GetValues reads the value for the given key. The API does not return multiple
// values.
func (r APIRouter) GetValues(ctx context.Context, key string, opts ...ropts.Option) ([]byte, error) {
    select {
        case <- r.started:
        default:
            return nil, ErrNotStarted
    }

	return r.GetValue(ctx, key, opts...)
}

// SearchValue returns the value for the given key. It return either an error or
// a closed channel containing one value.
func (r APIRouter) SearchValue(ctx context.Context, key string, opts ...ropts.Option) (<-chan []byte, error) {
	value, err := r.GetValue(ctx, key, opts...)
	if err != nil {
		return nil, err
	}

	valueCh := make(chan []byte, 1)
	valueCh <- value
	close(valueCh)
	return valueCh, nil
}

// FindPeer is unsupported
func (r APIRouter) FindPeer(_ context.Context, id peer.ID) (pstore.PeerInfo, error) {
	return pstore.PeerInfo{}, routing.ErrNotSupported
}

// FindProvidersAsync is unsupported
func (r APIRouter) FindProvidersAsync(_ context.Context, _ cid.Cid, _ int) <-chan pstore.PeerInfo {
	return nil
}

// Provide is unsupported
func (r APIRouter) Provide(_ context.Context, _ cid.Cid, _ bool) error {
	return routing.ErrNotSupported
}

func (r APIRouter) pathForKey(key string) string {
	return r.uri + "/value/" + base64.URLEncoding.EncodeToString([]byte(key))
}
<commit_msg>TWEAK: Make APIRouter calls block until started instead of returning an error.<commit_after>package ipfs

import (
	"bytes"
	"context"
	"encoding/base64"
	"errors"
	"golang.org/x/net/proxy"
	"io/ioutil"
	"net/http"
	"time"

	"gx/ipfs/QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN/go-cid"
	peer "gx/ipfs/QmYVXrKrKHDC9FobgmcmshCDyWwdrfwfanNQN4oxJ9Fk3h/go-libp2p-peer"
	routing "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing"
	ropts "gx/ipfs/QmYxUdYY9S6yg5tSPVin5GFTvtfsLauVcr7reHDD3dM8xf/go-libp2p-routing/options"
	pstore "gx/ipfs/QmaCTz9RkrU13bm9kMB54f7atgqM4qkjDZpRwRoJiWXEqs/go-libp2p-peerstore"
)

var apiRouterHTTPClient = &http.Client{
	Timeout: time.Second * 30,
}

// ensure APIRouter satisfies the interface
var _ routing.IpfsRouting = &APIRouter{}

// ErrNotStarted is returned if a method is called before the router
// is started using the Start() method.
var ErrNotStarted = errors.New("API router not started")

// APIRouter is a routing.IpfsRouting compliant struct backed by an API. It only
// provides the features offerened by routing.ValueStore and marks the others as
// unsupported.
type APIRouter struct {
	uri     string
	started chan (struct{})
}

// NewAPIRouter creates a new APIRouter backed by the given URI.
func NewAPIRouter(uri string) APIRouter {
	return APIRouter{uri: uri, started: make(chan (struct{}))}
}

func (r *APIRouter) Start(proxyDialer proxy.Dialer) {
	if proxyDialer != nil {
		tbTransport := &http.Transport{Dial: proxyDialer.Dial}
		apiRouterHTTPClient.Transport = tbTransport
	}
	close(r.started)
}

// Bootstrap is a no-op. We don't need any setup to query the API.
func (r APIRouter) Bootstrap(_ context.Context) error {
	return nil
}

// PutValue writes the given value to the API for the given key
func (r APIRouter) PutValue(ctx context.Context, key string, value []byte, opts ...ropts.Option) error {
	<-r.started
	req, err := http.NewRequest("PUT", r.pathForKey(key), bytes.NewBuffer(value))
	if err != nil {
		return err
	}

	_, err = apiRouterHTTPClient.Do(req)
	return err
}

// GetValue reads the value for the given key
func (r APIRouter) GetValue(ctx context.Context, key string, opts ...ropts.Option) ([]byte, error) {
	<-r.started
	resp, err := apiRouterHTTPClient.Get(r.pathForKey(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

// GetValues reads the value for the given key. The API does not return multiple
// values.
func (r APIRouter) GetValues(ctx context.Context, key string, opts ...ropts.Option) ([]byte, error) {
	<-r.started
	return r.GetValue(ctx, key, opts...)
}

// SearchValue returns the value for the given key. It return either an error or
// a closed channel containing one value.
func (r APIRouter) SearchValue(ctx context.Context, key string, opts ...ropts.Option) (<-chan []byte, error) {
	value, err := r.GetValue(ctx, key, opts...)
	if err != nil {
		return nil, err
	}

	valueCh := make(chan []byte, 1)
	valueCh <- value
	close(valueCh)
	return valueCh, nil
}

// FindPeer is unsupported
func (r APIRouter) FindPeer(_ context.Context, id peer.ID) (pstore.PeerInfo, error) {
	return pstore.PeerInfo{}, routing.ErrNotSupported
}

// FindProvidersAsync is unsupported
func (r APIRouter) FindProvidersAsync(_ context.Context, _ cid.Cid, _ int) <-chan pstore.PeerInfo {
	return nil
}

// Provide is unsupported
func (r APIRouter) Provide(_ context.Context, _ cid.Cid, _ bool) error {
	return routing.ErrNotSupported
}

func (r APIRouter) pathForKey(key string) string {
	return r.uri + "/value/" + base64.URLEncoding.EncodeToString([]byte(key))
}
<|endoftext|>


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

package main

import (
	"fmt"
	"github.com/ligato/cn-infra/logging"
	log "github.com/ligato/cn-infra/logging/logrus"
	"github.com/ligato/cn-infra/messaging/kafka/client"
	"github.com/ligato/cn-infra/messaging/kafka/mux"
	"os"
	"os/signal"
)

func main() {
	log.SetLevel(logging.DebugLevel)
	mx, err := mux.InitMultiplexer("", "default")
	if err != nil {
		os.Exit(1)
	}
	cn := mx.NewConnection("plugin")
	cn.SendSyncString("test", "key", "value")

	succCh := make(chan *client.ProducerMessage)
	errCh := make(chan *client.ProducerError)
	signalChan := make(chan os.Signal)
	signal.Notify(signalChan, os.Interrupt)

	cn.SendAsyncString("test", "key", "async!!", "meta", succCh, errCh)

	select {
	case success := <-succCh:
		fmt.Println("Successfully send async msg", success.Metadata)
	case err := <-errCh:
		fmt.Println("Error while sending async msg", err.Err, err.Msg.Metadata)
	}

	consumerChan := make(chan *client.ConsumerMessage)
	err = cn.ConsumeTopic("test", consumerChan)
	mx.Start()
	if err == nil {
		fmt.Println("Consuming test partition")
	eventLoop:
		for {
			select {
			case msg := <-consumerChan:
				fmt.Println(string(msg.Key), string(msg.Value))
			case <-signalChan:
				break eventLoop
			}
		}
	}

	mx.Close()
}
<commit_msg>messaging/kafka: fix example<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"github.com/ligato/cn-infra/logging"
	log "github.com/ligato/cn-infra/logging/logrus"
	"github.com/ligato/cn-infra/messaging/kafka/client"
	"github.com/ligato/cn-infra/messaging/kafka/mux"
	"os"
	"os/signal"
)

func main() {
	log.SetLevel(logging.DebugLevel)
	mx, err := mux.InitMultiplexer("", "default")
	if err != nil {
		os.Exit(1)
	}
	cn := mx.NewConnection("plugin")
	cn.SendSyncString("test", "key", "value")

	succCh := make(chan *client.ProducerMessage)
	errCh := make(chan *client.ProducerError)
	signalChan := make(chan os.Signal)
	signal.Notify(signalChan, os.Interrupt)

	cn.SendAsyncString("test", "key", "async!!", "meta", succCh, errCh)

	select {
	case success := <-succCh:
		fmt.Println("Successfully send async msg", success.Metadata)
	case err := <-errCh:
		fmt.Println("Error while sending async msg", err.Err, err.Msg.Metadata)
	}

	consumerChan := make(chan *client.ConsumerMessage)
	err = cn.ConsumeTopic(consumerChan, "test")
	mx.Start()
	if err == nil {
		fmt.Println("Consuming test partition")
	eventLoop:
		for {
			select {
			case msg := <-consumerChan:
				fmt.Println(string(msg.Key), string(msg.Value))
			case <-signalChan:
				break eventLoop
			}
		}
	}

	mx.Close()
}
<|endoftext|>


<commit_before>//This utility prints all zones in irc channels. Useful if you want to see how it will look
package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"time"

	irc "github.com/ugjka/dumbirc"
	c "github.com/ugjka/newyearsbot/common"
)

const ircNick = "HNYbotTest"
const ircName = "newyears2"
const ircServer = "irc.freenode.net:7000"

var ircChannel = []string{"#ugjkatest2"}

func main() {
	var zones c.TZS
	file, err := os.Open("../tz.json")
	if err != nil {
		log.Fatal(err)
	}
	content, err := ioutil.ReadAll(file)
	if err != nil {
		log.Fatal(err)
	}
	json.Unmarshal(content, &zones)
	sort.Sort(sort.Reverse(zones))

	ircobj := irc.New(ircNick, ircName, ircServer, true)
	ircobj.AddCallback(irc.WELCOME, func(msg irc.Message) {
		ircobj.Join(ircChannel)
	})

	ircobj.AddCallback(irc.PING, func(msg irc.Message) {
		ircobj.Pong()
	})

	ircobj.AddCallback(irc.NICKTAKEN, func(msg irc.Message) {
		ircobj.Nick += "_"
		ircobj.NewNick(ircobj.Nick)
	})
	ircobj.Start()
	go func() {
		for {
			time.Sleep(time.Minute)
			ircobj.Ping()
		}
	}()
	go func() {
		log.Println(<-ircobj.Errchan)
		os.Exit(1)
	}()
	time.Sleep(time.Second * 30)

	for _, k := range zones {
		time.Sleep(time.Second * 2)
		ircobj.PrivMsg(ircChannel[0], "Next New Year in 29 minutes 57 seconds in "+k.String())
		time.Sleep(time.Second * 1)
		ircobj.PrivMsg(ircChannel[0], "Happy New Year in "+k.String())
	}

}
<commit_msg>improve ircprinttz<commit_after>//This utility prints all zones in irc channels. Useful if you want to see how it will look
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"sync"
	"time"

	irc "github.com/ugjka/dumbirc"
	c "github.com/ugjka/newyearsbot/common"
)

var usage = `Test utility for debugging that post all newyears on a specified channel

CMD Options:
-chans			comma seperated list of irc channels to join
-tzpath			path to tz database (../tz.json)
-ircserver		irc server to use irc.example.com:7000 (must be TLS enabled)
-botnick		nick for the bot `

//Custom flag to get irc channelsn to join
var ircChansFlag c.IrcChans

func init() {
	flag.Var(&ircChansFlag, "chans", "comma seperated list of irc channels to join")
}

const ircName = "nyebottest"

var ircChannel = []string{"#ugjkatest"}
var once sync.Once
var start = make(chan bool)

func main() {
	//flags
	tzdatapath := flag.String("tzpath", "../tz.json", "path to tz.json")
	ircServer := flag.String("ircserver", "irc.freenode.net:7000", "Irc server to use, must be TLS")
	ircNick := flag.String("botnick", "HNYbot18", "Irc Nick for the bot")
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, fmt.Sprintf(usage))
	}
	flag.Parse()
	if len(ircChansFlag) > 0 {
		ircChannel = ircChansFlag
	}
	//Check if tz.json exists
	if _, err := os.Stat(*tzdatapath); os.IsNotExist(err) {
		fmt.Fprintf(os.Stderr, "Error: file %s does not exist\n", *tzdatapath)
		os.Exit(1)
	}
	var zones c.TZS
	file, err := os.Open(*tzdatapath)
	if err != nil {
		log.Fatal(err)
	}
	content, err := ioutil.ReadAll(file)
	if err != nil {
		log.Fatal(err)
	}
	json.Unmarshal(content, &zones)
	sort.Sort(sort.Reverse(zones))

	ircobj := irc.New(*ircNick, ircName, *ircServer, true)
	ircobj.AddCallback(irc.WELCOME, func(msg irc.Message) {
		ircobj.Join(ircChannel)
		//Prevent early start
		once.Do(func() {
			start <- true
		})
	})

	ircobj.AddCallback(irc.PING, func(msg irc.Message) {
		ircobj.Pong()
	})

	ircobj.AddCallback(irc.NICKTAKEN, func(msg irc.Message) {
		ircobj.Nick += "_"
		ircobj.NewNick(ircobj.Nick)
	})
	ircobj.Start()
	go func() {
		for {
			time.Sleep(time.Minute)
			ircobj.Ping()
		}
	}()
	go func() {
		log.Println(<-ircobj.Errchan)
		os.Exit(1)
	}()
	<-start

	for _, k := range zones {
		time.Sleep(time.Second * 2)
		ircobj.PrivMsg(ircChannel[0], "Next New Year in 29 minutes 57 seconds in "+k.String())
		time.Sleep(time.Second * 1)
		ircobj.PrivMsg(ircChannel[0], "Happy New Year in "+k.String())
	}

}
<|endoftext|>


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

package android

import (
	"flag"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"runtime"

	"v.io/jiri/collect"
	"v.io/jiri/jiri"
	"v.io/jiri/profiles"
	"v.io/jiri/runutil"
	"v.io/x/lib/envvar"
)

const (
	profileName        = "android"
	ndkDownloadBaseURL = "https://dl.google.com/android/ndk"
)

type versionSpec struct {
	ndkDownloadURL string
	// seq's chain may be already in progress.
	ndkExtract  func(seq *runutil.Sequence, src, dst string) *runutil.Sequence
	ndkAPILevel int
}

func ndkArch() (string, error) {
	switch runtime.GOARCH {
	case "386":
		return "x86", nil
	case "amd64":
		return "x86_64", nil
	default:
		return "", fmt.Errorf("NDK unsupported for GOARCH %s", runtime.GOARCH)
	}
}

func tarExtract(seq *runutil.Sequence, src, dst string) *runutil.Sequence {
	return seq.Run("tar", "-C", dst, "-xjf", src)
}

func selfExtract(seq *runutil.Sequence, src, dst string) *runutil.Sequence {
	return seq.Chmod(src, profiles.DefaultDirPerm).Run(src, "-y", "-o"+dst)
}

func init() {
	arch, err := ndkArch()
	if err != nil {
		fmt.Fprintf(os.Stderr, "WARNING: android profile not supported: %v\n", err)
		return
	}
	m := &Manager{
		versionInfo: profiles.NewVersionInfo(profileName, map[string]interface{}{
			"3": &versionSpec{
				ndkDownloadURL: fmt.Sprintf("%s/android-ndk-r9d-%s-%s.tar.bz2", ndkDownloadBaseURL, runtime.GOOS, arch),
				ndkExtract:     tarExtract,
				ndkAPILevel:    9,
			},
			"4": &versionSpec{
				ndkDownloadURL: fmt.Sprintf("%s/android-ndk-r10e-%s-%s.bin", ndkDownloadBaseURL, runtime.GOOS, arch),
				ndkExtract:     selfExtract,
				ndkAPILevel:    16,
			},
		}, "3"),
	}
	profiles.Register(profileName, m)
}

type Manager struct {
	root, androidRoot, ndkRoot jiri.RelPath
	versionInfo                *profiles.VersionInfo
	spec                       versionSpec
}

func (Manager) Name() string {
	return profileName
}

func (m Manager) String() string {
	return fmt.Sprintf("%s[%s]", profileName, m.versionInfo.Default())
}

func (m Manager) Info() string {
	return `
The android profile provides support for cross-compiling from linux or darwin
to android. It only supports one target 'arm-android' and will assume that
as the default value if one is not supplied. It installs the android NDK
and a go compiler configured to use it.`
}

func (m Manager) VersionInfo() *profiles.VersionInfo {
	return m.versionInfo
}

func (m *Manager) AddFlags(flags *flag.FlagSet, action profiles.Action) {
}

func (m *Manager) initForTarget(jirix *jiri.X, action string, root jiri.RelPath, target *profiles.Target) error {
	if !target.IsSet() {
		def := *target
		target.Set("arm-android")
		fmt.Fprintf(jirix.Stdout(), "Default target %v reinterpreted as: %v\n", def, target)
	} else {
		if target.Arch() != "arm" && target.OS() != "android" {
			return fmt.Errorf("this profile can only be %v as arm-android and not as %v", action, target)
		}
	}
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return err
	}
	m.root = root
	m.androidRoot = root.Join("android")
	m.ndkRoot = m.androidRoot.Join("ndk-toolchain")
	return nil
}

func (m *Manager) Install(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
	if err := m.initForTarget(jirix, "installed", root, &target); err != nil {
		return err
	}
	if p := profiles.LookupProfileTarget(profileName, target); p != nil {
		fmt.Fprintf(jirix.Stdout(), "%v %v is already installed as %v\n", profileName, target, p)
		return nil
	}
	if err := m.installAndroidNDK(jirix); err != nil {
		return err
	}
	profiles.InstallProfile(profileName, string(m.androidRoot))
	if err := profiles.AddProfileTarget(profileName, target); err != nil {
		return err
	}

	// Install android targets for other profiles.
	dependency := target
	dependency.SetVersion("2")
	if err := m.installAndroidBaseTargets(jirix, dependency); err != nil {
		return err
	}

	// Merge the target and baseProfile environments.
	env := envvar.VarsFromSlice(target.Env.Vars)
	baseProfileEnv := profiles.EnvFromProfile(target, "base")
	profiles.MergeEnv(profiles.ProfileMergePolicies(), env, baseProfileEnv)
	target.Env.Vars = env.ToSlice()
	target.InstallationDir = string(m.ndkRoot)
	profiles.InstallProfile(profileName, string(m.androidRoot))
	return profiles.UpdateProfileTarget(profileName, target)
}

func (m *Manager) Uninstall(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
	if err := m.initForTarget(jirix, "uninstalled", root, &target); err != nil {
		return err
	}
	target.Env.Vars = append(target.Env.Vars, "GOARM=7")
	if err := profiles.EnsureProfileTargetIsUninstalled(jirix, "base", root, target); err != nil {
		return err
	}
	if err := jirix.NewSeq().RemoveAll(m.androidRoot.Abs(jirix)).Done(); err != nil {
		return err
	}
	profiles.RemoveProfileTarget(profileName, target)
	return nil
}

// installAndroidNDK installs the android NDK toolchain.
func (m *Manager) installAndroidNDK(jirix *jiri.X) (e error) {
	// Install dependencies.
	var pkgs []string
	switch runtime.GOOS {
	case "linux":
		pkgs = []string{"ant", "autoconf", "bzip2", "default-jdk", "gawk", "lib32z1", "lib32stdc++6"}
	case "darwin":
		pkgs = []string{"ant", "autoconf", "gawk"}
	default:
		return fmt.Errorf("unsupported OS: %s", runtime.GOOS)
	}
	if err := profiles.InstallPackages(jirix, pkgs); err != nil {
		return err
	}
	// Download Android NDK.
	installNdkFn := func() error {
		s := jirix.NewSeq()
		tmpDir, err := s.TempDir("", "")
		if err != nil {
			return fmt.Errorf("TempDir() failed: %v", err)
		}
		defer collect.Error(func() error { return jirix.NewSeq().RemoveAll(tmpDir).Done() }, &e)
		extractDir, err := s.TempDir(tmpDir, "extract")
		if err != nil {
			return err
		}
		local := filepath.Join(tmpDir, path.Base(m.spec.ndkDownloadURL))
		s.Run("curl", "-Lo", local, m.spec.ndkDownloadURL)
		files, err := m.spec.ndkExtract(s, local, extractDir).
			ReadDir(extractDir)
		if err != nil {
			return err
		}
		if len(files) != 1 {
			return fmt.Errorf("expected one directory under %s, got: %v", extractDir, files)
		}
		ndkBin := filepath.Join(extractDir, files[0].Name(), "build", "tools", "make-standalone-toolchain.sh")
		ndkArgs := []string{ndkBin, fmt.Sprintf("--platform=android-%d", m.spec.ndkAPILevel), "--arch=arm", "--install-dir=" + m.ndkRoot.Abs(jirix)}
		return s.Last("bash", ndkArgs...)
	}
	return profiles.AtomicAction(jirix, installNdkFn, m.ndkRoot.Abs(jirix), "Download Android NDK")
}

// installAndroidTargets installs android targets for other profiles, currently
// just the base profile (i.e. go and syncbase.)
func (m *Manager) installAndroidBaseTargets(jirix *jiri.X, target profiles.Target) (e error) {
	env := fmt.Sprintf("ANDROID_NDK_DIR=%s,GOARM=7", m.ndkRoot.Symbolic())
	androidTarget, err := profiles.NewTargetWithEnv(target.String(), env)
	if err != nil {
		return err
	}
	return profiles.EnsureProfileTargetIsInstalled(jirix, "base", m.root, androidTarget)
}
<commit_msg>v.io/jiri/runtil: return Sequence and not *Sequence...<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package android

import (
	"flag"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"runtime"

	"v.io/jiri/collect"
	"v.io/jiri/jiri"
	"v.io/jiri/profiles"
	"v.io/jiri/runutil"
	"v.io/x/lib/envvar"
)

const (
	profileName        = "android"
	ndkDownloadBaseURL = "https://dl.google.com/android/ndk"
)

type versionSpec struct {
	ndkDownloadURL string
	// seq's chain may be already in progress.
	ndkExtract  func(seq runutil.Sequence, src, dst string) runutil.Sequence
	ndkAPILevel int
}

func ndkArch() (string, error) {
	switch runtime.GOARCH {
	case "386":
		return "x86", nil
	case "amd64":
		return "x86_64", nil
	default:
		return "", fmt.Errorf("NDK unsupported for GOARCH %s", runtime.GOARCH)
	}
}

func tarExtract(seq runutil.Sequence, src, dst string) runutil.Sequence {
	return seq.Run("tar", "-C", dst, "-xjf", src)
}

func selfExtract(seq runutil.Sequence, src, dst string) runutil.Sequence {
	return seq.Chmod(src, profiles.DefaultDirPerm).Run(src, "-y", "-o"+dst)
}

func init() {
	arch, err := ndkArch()
	if err != nil {
		fmt.Fprintf(os.Stderr, "WARNING: android profile not supported: %v\n", err)
		return
	}
	m := &Manager{
		versionInfo: profiles.NewVersionInfo(profileName, map[string]interface{}{
			"3": &versionSpec{
				ndkDownloadURL: fmt.Sprintf("%s/android-ndk-r9d-%s-%s.tar.bz2", ndkDownloadBaseURL, runtime.GOOS, arch),
				ndkExtract:     tarExtract,
				ndkAPILevel:    9,
			},
			"4": &versionSpec{
				ndkDownloadURL: fmt.Sprintf("%s/android-ndk-r10e-%s-%s.bin", ndkDownloadBaseURL, runtime.GOOS, arch),
				ndkExtract:     selfExtract,
				ndkAPILevel:    16,
			},
		}, "3"),
	}
	profiles.Register(profileName, m)
}

type Manager struct {
	root, androidRoot, ndkRoot jiri.RelPath
	versionInfo                *profiles.VersionInfo
	spec                       versionSpec
}

func (Manager) Name() string {
	return profileName
}

func (m Manager) String() string {
	return fmt.Sprintf("%s[%s]", profileName, m.versionInfo.Default())
}

func (m Manager) Info() string {
	return `
The android profile provides support for cross-compiling from linux or darwin
to android. It only supports one target 'arm-android' and will assume that
as the default value if one is not supplied. It installs the android NDK
and a go compiler configured to use it.`
}

func (m Manager) VersionInfo() *profiles.VersionInfo {
	return m.versionInfo
}

func (m *Manager) AddFlags(flags *flag.FlagSet, action profiles.Action) {
}

func (m *Manager) initForTarget(jirix *jiri.X, action string, root jiri.RelPath, target *profiles.Target) error {
	if !target.IsSet() {
		def := *target
		target.Set("arm-android")
		fmt.Fprintf(jirix.Stdout(), "Default target %v reinterpreted as: %v\n", def, target)
	} else {
		if target.Arch() != "arm" && target.OS() != "android" {
			return fmt.Errorf("this profile can only be %v as arm-android and not as %v", action, target)
		}
	}
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return err
	}
	m.root = root
	m.androidRoot = root.Join("android")
	m.ndkRoot = m.androidRoot.Join("ndk-toolchain")
	return nil
}

func (m *Manager) Install(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
	if err := m.initForTarget(jirix, "installed", root, &target); err != nil {
		return err
	}
	if p := profiles.LookupProfileTarget(profileName, target); p != nil {
		fmt.Fprintf(jirix.Stdout(), "%v %v is already installed as %v\n", profileName, target, p)
		return nil
	}
	if err := m.installAndroidNDK(jirix); err != nil {
		return err
	}
	profiles.InstallProfile(profileName, string(m.androidRoot))
	if err := profiles.AddProfileTarget(profileName, target); err != nil {
		return err
	}

	// Install android targets for other profiles.
	dependency := target
	dependency.SetVersion("2")
	if err := m.installAndroidBaseTargets(jirix, dependency); err != nil {
		return err
	}

	// Merge the target and baseProfile environments.
	env := envvar.VarsFromSlice(target.Env.Vars)
	baseProfileEnv := profiles.EnvFromProfile(target, "base")
	profiles.MergeEnv(profiles.ProfileMergePolicies(), env, baseProfileEnv)
	target.Env.Vars = env.ToSlice()
	target.InstallationDir = string(m.ndkRoot)
	profiles.InstallProfile(profileName, string(m.androidRoot))
	return profiles.UpdateProfileTarget(profileName, target)
}

func (m *Manager) Uninstall(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
	if err := m.initForTarget(jirix, "uninstalled", root, &target); err != nil {
		return err
	}
	target.Env.Vars = append(target.Env.Vars, "GOARM=7")
	if err := profiles.EnsureProfileTargetIsUninstalled(jirix, "base", root, target); err != nil {
		return err
	}
	if err := jirix.NewSeq().RemoveAll(m.androidRoot.Abs(jirix)).Done(); err != nil {
		return err
	}
	profiles.RemoveProfileTarget(profileName, target)
	return nil
}

// installAndroidNDK installs the android NDK toolchain.
func (m *Manager) installAndroidNDK(jirix *jiri.X) (e error) {
	// Install dependencies.
	var pkgs []string
	switch runtime.GOOS {
	case "linux":
		pkgs = []string{"ant", "autoconf", "bzip2", "default-jdk", "gawk", "lib32z1", "lib32stdc++6"}
	case "darwin":
		pkgs = []string{"ant", "autoconf", "gawk"}
	default:
		return fmt.Errorf("unsupported OS: %s", runtime.GOOS)
	}
	if err := profiles.InstallPackages(jirix, pkgs); err != nil {
		return err
	}
	// Download Android NDK.
	installNdkFn := func() error {
		s := jirix.NewSeq()
		tmpDir, err := s.TempDir("", "")
		if err != nil {
			return fmt.Errorf("TempDir() failed: %v", err)
		}
		defer collect.Error(func() error { return jirix.NewSeq().RemoveAll(tmpDir).Done() }, &e)
		extractDir, err := s.TempDir(tmpDir, "extract")
		if err != nil {
			return err
		}
		local := filepath.Join(tmpDir, path.Base(m.spec.ndkDownloadURL))
		s.Run("curl", "-Lo", local, m.spec.ndkDownloadURL)
		files, err := m.spec.ndkExtract(s, local, extractDir).
			ReadDir(extractDir)
		if err != nil {
			return err
		}
		if len(files) != 1 {
			return fmt.Errorf("expected one directory under %s, got: %v", extractDir, files)
		}
		ndkBin := filepath.Join(extractDir, files[0].Name(), "build", "tools", "make-standalone-toolchain.sh")
		ndkArgs := []string{ndkBin, fmt.Sprintf("--platform=android-%d", m.spec.ndkAPILevel), "--arch=arm", "--install-dir=" + m.ndkRoot.Abs(jirix)}
		return s.Last("bash", ndkArgs...)
	}
	return profiles.AtomicAction(jirix, installNdkFn, m.ndkRoot.Abs(jirix), "Download Android NDK")
}

// installAndroidTargets installs android targets for other profiles, currently
// just the base profile (i.e. go and syncbase.)
func (m *Manager) installAndroidBaseTargets(jirix *jiri.X, target profiles.Target) (e error) {
	env := fmt.Sprintf("ANDROID_NDK_DIR=%s,GOARM=7", m.ndkRoot.Symbolic())
	androidTarget, err := profiles.NewTargetWithEnv(target.String(), env)
	if err != nil {
		return err
	}
	return profiles.EnsureProfileTargetIsInstalled(jirix, "base", m.root, androidTarget)
}
<|endoftext|>


<commit_before>// Copyright 2013 Matthew Baird
// 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 elastigo

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// Search performs a very basic search on an index via the request URI API.
//
// params:
//   @index:  the elasticsearch index
//   @_type:  optional ("" if not used) search specific type in this index
//   @args:   a map of URL parameters. Allows all the URI-request parameters allowed by ElasticSearch.
//   @query:  this can be one of 3 types:
//              1)  string value that is valid elasticsearch
//              2)  io.Reader that can be set in body (also valid elasticsearch string syntax..)
//              3)  other type marshalable to json (also valid elasticsearch json)
//
//   out, err := Search(true, "github", map[string]interface{} {"from" : 10}, qryType)
//
// http://www.elasticsearch.org/guide/reference/api/search/uri-request.html
func (c *Conn) Search(index string, _type string, args map[string]interface{}, query interface{}) (SearchResult, error) {
	var uriVal string
	var retval SearchResult
	if len(_type) > 0 && _type != "*" {
		uriVal = fmt.Sprintf("/%s/%s/_search", index, _type)
	} else {
		uriVal = fmt.Sprintf("/%s/_search", index)
	}
	body, err := c.DoCommand("POST", uriVal, args, query)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	retval.RawJSON = body
	return retval, err
}

func (c *Conn) Suggest(index string, args map[string]interface{}, query interface{}) (SuggestResults, error) {
	uriVal := fmt.Sprintf("/%s/_suggest", index)
	body, err := c.DoCommand("POST", uriVal, args, query)
	var retval SuggestResults
	if err != nil {
		return retval, err
	}
	jsonErr := json.Unmarshal([]byte(body), &retval.body)
	if jsonErr != nil {
		return retval, jsonErr
	}
	shards := retval.body["_shards"]
	if shards == nil {
		return retval, fmt.Errorf("Expect response to contain _shards field, got: %s", body)
	}
	jsonErr = json.Unmarshal(shards, &retval.ShardStatus)
	if jsonErr != nil {
		return retval, jsonErr
	}
	if len(retval.ShardStatus.Failures) > 0 {
		return retval, fmt.Errorf("Got the following errors:\n%s", failures(retval.ShardStatus.Failures))
	}
	return retval, nil
}

type SuggestResults struct {
	body        map[string]json.RawMessage
	ShardStatus Status
}

func (s SuggestResults) Result(suggestName string) ([]Suggestion, error) {
	var suggestions []Suggestion
	query := s.body[suggestName]
	if query == nil {
		return nil, fmt.Errorf("No such suggest name found")
	}
	err := json.Unmarshal(query, &suggestions)
	if err != nil {
		return nil, err
	}
	return suggestions, nil
}

// SearchUri performs the simplest possible query in url string
// params:
//   @index:  the elasticsearch index
//   @_type:  optional ("" if not used) search specific type in this index
//   @args: a map of URL parameters. Most important one is q
//
//   out, err := SearchUri("github","", map[string]interface{} { "q" : `user:kimchy`})
//
// produces a request like this:    host:9200/github/_search?q=user:kimchy"
//
// http://www.elasticsearch.org/guide/reference/api/search/uri-request.html
func (c *Conn) SearchUri(index, _type string, args map[string]interface{}) (SearchResult, error) {
	var uriVal string
	var retval SearchResult
	if len(_type) > 0 && _type != "*" {
		uriVal = fmt.Sprintf("/%s/%s/_search", index, _type)
	} else {
		uriVal = fmt.Sprintf("/%s/_search", index)
	}
	//log.Println(uriVal)
	body, err := c.DoCommand("GET", uriVal, args, nil)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	retval.RawJSON = body
	return retval, err
}

func (c *Conn) Scroll(args map[string]interface{}, scroll_id string) (SearchResult, error) {
	var url string
	var retval SearchResult

	if _, ok := args["scroll"]; !ok {
		return retval, fmt.Errorf("Cannot call scroll without 'scroll' in arguments")
	}

	url = "/_search/scroll"

	body, err := c.DoCommand("POST", url, args, scroll_id)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	return retval, err
}

type SuggestionOption struct {
	Payload json.RawMessage `json:"payload"`
	Score   Float32Nullable `json:"score,omitempty"`
	Text    string          `json:"text"`
}

type Suggestion struct {
	Length  int                `json:"length"`
	Offset  int                `json:"offset"`
	Options []SuggestionOption `json:"options"`
	Text    string             `json:"text"`
}

type Suggestions map[string][]Suggestion

type SearchResult struct {
	RawJSON      []byte
	Took         int             `json:"took"`
	TimedOut     bool            `json:"timed_out"`
	ShardStatus  Status          `json:"_shards"`
	Hits         Hits            `json:"hits"`
	Facets       json.RawMessage `json:"facets,omitempty"` // structure varies on query
	ScrollId     string          `json:"_scroll_id,omitempty"`
	Aggregations json.RawMessage `json:"aggregations,omitempty"` // structure varies on query
	Suggestions  Suggestions     `json:"suggest,omitempty"`
}

func (s *SearchResult) String() string {
	return fmt.Sprintf("<Results took=%v Timeout=%v hitct=%v />", s.Took, s.TimedOut, s.Hits.Total)
}

type Hits struct {
	Total int `json:"total"`
	//	MaxScore float32 `json:"max_score"`
	Hits []Hit `json:"hits"`
}

func (h *Hits) Len() int {
	return len(h.Hits)
}

type Highlight map[string][]string

// TTL is a wrapper around time.Time that converts a number of milliseconds in the future to time.Time
type TTL struct{ time.Time }

func (t *TTL) UnmarshalJSON(data []byte) (err error) {
	var millisecondsInFuture int64
	if err = json.Unmarshal(data, &millisecondsInFuture); err == nil {
		t.Time = time.Now().Add(time.Duration(millisecondsInFuture) * time.Millisecond)
		return
	}
	return
}

type Hit struct {
	Index       string           `json:"_index"`
	Type        string           `json:"_type,omitempty"`
	Id          string           `json:"_id"`
	Score       Float32Nullable  `json:"_score,omitempty"` // Filters (no query) dont have score, so is null
	Source      *json.RawMessage `json:"_source"`          // marshalling left to consumer
	TTL         *TTL             `json:"_ttl,omitempty"`
	Fields      *json.RawMessage `json:"fields"` // when a field arg is passed to ES, instead of _source it returns fields
	Explanation *Explanation     `json:"_explanation,omitempty"`
	Highlight   *Highlight       `json:"highlight,omitempty"`
	Sort        []interface{}    `json:"sort,omitempty"`
}

func (e *Explanation) String(indent string) string {
	if len(e.Details) == 0 {
		return fmt.Sprintf("%s>>>  %v = %s", indent, e.Value, strings.Replace(e.Description, "\n", "", -1))
	} else {
		detailStrs := make([]string, 0)
		for _, detail := range e.Details {
			detailStrs = append(detailStrs, fmt.Sprintf("%s", detail.String(indent+"| ")))
		}
		return fmt.Sprintf("%s%v = %s(\n%s\n%s)", indent, e.Value, strings.Replace(e.Description, "\n", "", -1), strings.Join(detailStrs, "\n"), indent)
	}
}

// Elasticsearch returns some invalid (according to go) json, with floats having...
//
// json: cannot unmarshal null into Go value of type float32 (see last field.)
//
// "hits":{"total":6808,"max_score":null,
//    "hits":[{"_index":"10user","_type":"user","_id":"751820","_score":null,
type Float32Nullable float32

func (i *Float32Nullable) UnmarshalJSON(data []byte) error {
	if len(data) == 0 || string(data) == "null" {
		return nil
	}

	if in, err := strconv.ParseFloat(string(data), 32); err != nil {
		return err
	} else {
		*i = Float32Nullable(in)
	}
	return nil
}
<commit_msg>Fix period<commit_after>// Copyright 2013 Matthew Baird
// 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 elastigo

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// Search performs a very basic search on an index via the request URI API.
//
// params:
//   @index:  the elasticsearch index
//   @_type:  optional ("" if not used) search specific type in this index
//   @args:   a map of URL parameters. Allows all the URI-request parameters allowed by ElasticSearch.
//   @query:  this can be one of 3 types:
//              1)  string value that is valid elasticsearch
//              2)  io.Reader that can be set in body (also valid elasticsearch string syntax..)
//              3)  other type marshalable to json (also valid elasticsearch json)
//
//   out, err := Search(true, "github", map[string]interface{} {"from" : 10}, qryType)
//
// http://www.elasticsearch.org/guide/reference/api/search/uri-request.html
func (c *Conn) Search(index string, _type string, args map[string]interface{}, query interface{}) (SearchResult, error) {
	var uriVal string
	var retval SearchResult
	if len(_type) > 0 && _type != "*" {
		uriVal = fmt.Sprintf("/%s/%s/_search", index, _type)
	} else {
		uriVal = fmt.Sprintf("/%s/_search", index)
	}
	body, err := c.DoCommand("POST", uriVal, args, query)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	retval.RawJSON = body
	return retval, err
}

func (c *Conn) Suggest(index string, args map[string]interface{}, query interface{}) (SuggestResults, error) {
	uriVal := fmt.Sprintf("/%s/_suggest", index)
	body, err := c.DoCommand("POST", uriVal, args, query)
	var retval SuggestResults
	if err != nil {
		return retval, err
	}
	jsonErr := json.Unmarshal([]byte(body), &retval.body)
	if jsonErr != nil {
		return retval, jsonErr
	}
	shards := retval.body["_shards"]
	if shards == nil {
		return retval, fmt.Errorf("Expect response to contain _shards field, got: %s", body)
	}
	jsonErr = json.Unmarshal(shards, &retval.ShardStatus)
	if jsonErr != nil {
		return retval, jsonErr
	}
	if len(retval.ShardStatus.Failures) > 0 {
		return retval, fmt.Errorf("Got the following errors:\n%s", failures(retval.ShardStatus.Failures))
	}
	return retval, nil
}

type SuggestResults struct {
	body        map[string]json.RawMessage
	ShardStatus Status
}

func (s SuggestResults) Result(suggestName string) ([]Suggestion, error) {
	var suggestions []Suggestion
	query := s.body[suggestName]
	if query == nil {
		return nil, fmt.Errorf("No such suggest name found")
	}
	err := json.Unmarshal(query, &suggestions)
	if err != nil {
		return nil, err
	}
	return suggestions, nil
}

// SearchUri performs the simplest possible query in url string
// params:
//   @index:  the elasticsearch index
//   @_type:  optional ("" if not used) search specific type in this index
//   @args: a map of URL parameters. Most important one is q
//
//   out, err := SearchUri("github","", map[string]interface{} { "q" : `user:kimchy`})
//
// produces a request like this:    host:9200/github/_search?q=user:kimchy"
//
// http://www.elasticsearch.org/guide/reference/api/search/uri-request.html
func (c *Conn) SearchUri(index, _type string, args map[string]interface{}) (SearchResult, error) {
	var uriVal string
	var retval SearchResult
	if len(_type) > 0 && _type != "*" {
		uriVal = fmt.Sprintf("/%s/%s/_search", index, _type)
	} else {
		uriVal = fmt.Sprintf("/%s/_search", index)
	}
	//log.Println(uriVal)
	body, err := c.DoCommand("GET", uriVal, args, nil)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	retval.RawJSON = body
	return retval, err
}

func (c *Conn) Scroll(args map[string]interface{}, scroll_id string) (SearchResult, error) {
	var url string
	var retval SearchResult

	if _, ok := args["scroll"]; !ok {
		return retval, fmt.Errorf("Cannot call scroll without 'scroll' in arguments")
	}

	url = "/_search/scroll"

	body, err := c.DoCommand("POST", url, args, scroll_id)
	if err != nil {
		return retval, err
	}
	if err == nil {
		// marshall into json
		jsonErr := json.Unmarshal([]byte(body), &retval)
		if jsonErr != nil {
			return retval, jsonErr
		}
	}
	return retval, err
}

type SuggestionOption struct {
	Payload json.RawMessage `json:"payload"`
	Score   Float32Nullable `json:"score,omitempty"`
	Text    string          `json:"text"`
}

type Suggestion struct {
	Length  int                `json:"length"`
	Offset  int                `json:"offset"`
	Options []SuggestionOption `json:"options"`
	Text    string             `json:"text"`
}

type Suggestions map[string][]Suggestion

type SearchResult struct {
	RawJSON      []byte
	Took         int             `json:"took"`
	TimedOut     bool            `json:"timed_out"`
	ShardStatus  Status          `json:"_shards"`
	Hits         Hits            `json:"hits"`
	Facets       json.RawMessage `json:"facets,omitempty"` // structure varies on query
	ScrollId     string          `json:"_scroll_id,omitempty"`
	Aggregations json.RawMessage `json:"aggregations,omitempty"` // structure varies on query
	Suggestions  Suggestions     `json:"suggest,omitempty"`
}

func (s *SearchResult) String() string {
	return fmt.Sprintf("<Results took=%v Timeout=%v hitct=%v />", s.Took, s.TimedOut, s.Hits.Total)
}

type Hits struct {
	Total int `json:"total"`
	//	MaxScore float32 `json:"max_score"`
	Hits []Hit `json:"hits"`
}

func (h *Hits) Len() int {
	return len(h.Hits)
}

type Highlight map[string][]string

// TTL is a wrapper around time.Time that converts a number of milliseconds in the future to a time.Time.
type TTL struct{ time.Time }

func (t *TTL) UnmarshalJSON(data []byte) (err error) {
	var millisecondsInFuture int64
	if err = json.Unmarshal(data, &millisecondsInFuture); err == nil {
		t.Time = time.Now().Add(time.Duration(millisecondsInFuture) * time.Millisecond)
		return
	}
	return
}

type Hit struct {
	Index       string           `json:"_index"`
	Type        string           `json:"_type,omitempty"`
	Id          string           `json:"_id"`
	Score       Float32Nullable  `json:"_score,omitempty"` // Filters (no query) dont have score, so is null
	Source      *json.RawMessage `json:"_source"`          // marshalling left to consumer
	TTL         *TTL             `json:"_ttl,omitempty"`
	Fields      *json.RawMessage `json:"fields"` // when a field arg is passed to ES, instead of _source it returns fields
	Explanation *Explanation     `json:"_explanation,omitempty"`
	Highlight   *Highlight       `json:"highlight,omitempty"`
	Sort        []interface{}    `json:"sort,omitempty"`
}

func (e *Explanation) String(indent string) string {
	if len(e.Details) == 0 {
		return fmt.Sprintf("%s>>>  %v = %s", indent, e.Value, strings.Replace(e.Description, "\n", "", -1))
	} else {
		detailStrs := make([]string, 0)
		for _, detail := range e.Details {
			detailStrs = append(detailStrs, fmt.Sprintf("%s", detail.String(indent+"| ")))
		}
		return fmt.Sprintf("%s%v = %s(\n%s\n%s)", indent, e.Value, strings.Replace(e.Description, "\n", "", -1), strings.Join(detailStrs, "\n"), indent)
	}
}

// Elasticsearch returns some invalid (according to go) json, with floats having...
//
// json: cannot unmarshal null into Go value of type float32 (see last field.)
//
// "hits":{"total":6808,"max_score":null,
//    "hits":[{"_index":"10user","_type":"user","_id":"751820","_score":null,
type Float32Nullable float32

func (i *Float32Nullable) UnmarshalJSON(data []byte) error {
	if len(data) == 0 || string(data) == "null" {
		return nil
	}

	if in, err := strconv.ParseFloat(string(data), 32); err != nil {
		return err
	} else {
		*i = Float32Nullable(in)
	}
	return nil
}
<|endoftext|>


<commit_before>package g

import (
	"encoding/json"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"sync"

	"github.com/toolkits/file"
)

type HttpConfig struct {
	Enabled bool   `json:"enabled"`
	Listen  string `json:"listen"`
	Cookie  string `json:"cookie"`
}

type TimeoutConfig struct {
	Conn  int64 `json:"conn"`
	Read  int64 `json:"read"`
	Write int64 `json:"write"`
}

type CacheConfig struct {
	Enabled bool           `json:"enabled"`
	Redis   string         `json:"redis"`
	Idle    int            `json:"idle"`
	Max     int            `json:"max"`
	Timeout *TimeoutConfig `json:"timeout"`
}

type UicConfig struct {
	Addr string `json:"addr"`
	Idle int    `json:"idle"`
	Max  int    `json:"max"`
}

type GraphDBConfig struct {
	Addr           string `json:"addr"`
	Idle           int    `json:"idle"`
	Max            int    `json:"max"`
	Limit          int    `json:"limit"`
	LimitHostGroup int    `json:"limitHostGroup"`
}
type FalconPortalConfig struct {
	Addr  string `json:"addr"`
	Idle  int    `json:"idle"`
	Max   int    `json:"max"`
	Limit int    `json:"limit"`
}

type ShortcutConfig struct {
	FalconPortal     string `json:"falconPortal"`
	FalconDashboard  string `json:"falconDashboard"`
	GrafanaDashboard string `json:"grafanaDashboard"`
	FalconAlarm      string `json:"falconAlarm"`
}

type LdapConfig struct {
	Enabled    bool     `json:"enabled"`
	Addr       string   `json:"addr"`
	BindDN     string   `json:"bindDN"`
	BaseDN     string   `json:"baseDN`
	BindPasswd string   `json:"bindPasswd"`
	UserField  string   `json:"userField"`
	Attributes []string `json:attributes`
}

type ApiConfig struct {
	Key      string `json:"key"`
	Redirect string `json:"redirect"`
	Login    string `json:"login"`
	Access   string `json:"access"`
	Role     string `json:"role"`
	Logout   string `json:"logout"`
}

type GraphConfig struct {
	ConnTimeout int32             `json:"connTimeout"`
	CallTimeout int32             `json:"callTimeout"`
	MaxConns    int32             `json:"maxConns"`
	MaxIdle     int32             `json:"maxIdle"`
	Replicas    int32             `json:"replicas"`
	Cluster     map[string]string `json:"cluster"`
}

type GrpcConfig struct {
	Enabled bool `json:"enabled"`
	Port    int  `json:"port"`
}

type MqConfig struct {
	Enabled  bool   `json:"enabled"`
	Queue    string `json:"queue"`
	Consumer string `json:"consumer"`
}

type GlobalConfig struct {
	Log          string              `json:"log"`
	Company      string              `json:"company"`
	Cache        *CacheConfig        `json:"cache"`
	Http         *HttpConfig         `json:"http"`
	Salt         string              `json:"salt"`
	CanRegister  bool                `json:"canRegister"`
	Ldap         *LdapConfig         `json:"ldap"`
	Uic          *UicConfig          `json:"uic"`
	GraphDB      *GraphDBConfig      `json:"graphdb"`
	FalconPortal *FalconPortalConfig `json:"falcon_portal"`
	Shortcut     *ShortcutConfig     `json:"shortcut"`
	Api          *ApiConfig          `json:"api"`
	Graph        *GraphConfig        `json:"graph"`
	Grpc         *GrpcConfig         `json:"grpc"`
	Mq           *MqConfig           `json:"mq"`
}

var (
	ConfigFile string
	config     *GlobalConfig
	configLock = new(sync.RWMutex)
)

func Config() *GlobalConfig {
	configLock.RLock()
	defer configLock.RUnlock()
	return config
}

func ParseConfig(cfg string) error {
	if cfg == "" {
		return fmt.Errorf("use -c to specify configuration file")
	}

	if !file.IsExist(cfg) {
		return fmt.Errorf("config file %s is nonexistent", cfg)
	}

	ConfigFile = cfg

	configContent, err := file.ToTrimString(cfg)
	if err != nil {
		return fmt.Errorf("read config file %s fail %s", cfg, err)
	}

	var c GlobalConfig
	err = json.Unmarshal([]byte(configContent), &c)
	if err != nil {
		return fmt.Errorf("parse config file %s fail %s", cfg, err)
	}

	configLock.Lock()
	defer configLock.Unlock()

	config = &c

	log.Println("read config file:", cfg, "successfully")
	return nil
}
<commit_msg>[fe] Fix typos<commit_after>package g

import (
	"encoding/json"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"sync"

	"github.com/toolkits/file"
)

type HttpConfig struct {
	Enabled bool   `json:"enabled"`
	Listen  string `json:"listen"`
	Cookie  string `json:"cookie"`
}

type TimeoutConfig struct {
	Conn  int64 `json:"conn"`
	Read  int64 `json:"read"`
	Write int64 `json:"write"`
}

type CacheConfig struct {
	Enabled bool           `json:"enabled"`
	Redis   string         `json:"redis"`
	Idle    int            `json:"idle"`
	Max     int            `json:"max"`
	Timeout *TimeoutConfig `json:"timeout"`
}

type UicConfig struct {
	Addr string `json:"addr"`
	Idle int    `json:"idle"`
	Max  int    `json:"max"`
}

type GraphDBConfig struct {
	Addr           string `json:"addr"`
	Idle           int    `json:"idle"`
	Max            int    `json:"max"`
	Limit          int    `json:"limit"`
	LimitHostGroup int    `json:"limitHostGroup"`
}
type FalconPortalConfig struct {
	Addr  string `json:"addr"`
	Idle  int    `json:"idle"`
	Max   int    `json:"max"`
	Limit int    `json:"limit"`
}

type ShortcutConfig struct {
	FalconPortal     string `json:"falconPortal"`
	FalconDashboard  string `json:"falconDashboard"`
	GrafanaDashboard string `json:"grafanaDashboard"`
	FalconAlarm      string `json:"falconAlarm"`
}

type LdapConfig struct {
	Enabled    bool     `json:"enabled"`
	Addr       string   `json:"addr"`
	BindDN     string   `json:"bindDN"`
	BaseDN     string   `json:"baseDN"`
	BindPasswd string   `json:"bindPasswd"`
	UserField  string   `json:"userField"`
	Attributes []string `json:"attributes"`
}

type ApiConfig struct {
	Key      string `json:"key"`
	Redirect string `json:"redirect"`
	Login    string `json:"login"`
	Access   string `json:"access"`
	Role     string `json:"role"`
	Logout   string `json:"logout"`
}

type GraphConfig struct {
	ConnTimeout int32             `json:"connTimeout"`
	CallTimeout int32             `json:"callTimeout"`
	MaxConns    int32             `json:"maxConns"`
	MaxIdle     int32             `json:"maxIdle"`
	Replicas    int32             `json:"replicas"`
	Cluster     map[string]string `json:"cluster"`
}

type GrpcConfig struct {
	Enabled bool `json:"enabled"`
	Port    int  `json:"port"`
}

type MqConfig struct {
	Enabled  bool   `json:"enabled"`
	Queue    string `json:"queue"`
	Consumer string `json:"consumer"`
}

type GlobalConfig struct {
	Log          string              `json:"log"`
	Company      string              `json:"company"`
	Cache        *CacheConfig        `json:"cache"`
	Http         *HttpConfig         `json:"http"`
	Salt         string              `json:"salt"`
	CanRegister  bool                `json:"canRegister"`
	Ldap         *LdapConfig         `json:"ldap"`
	Uic          *UicConfig          `json:"uic"`
	GraphDB      *GraphDBConfig      `json:"graphdb"`
	FalconPortal *FalconPortalConfig `json:"falcon_portal"`
	Shortcut     *ShortcutConfig     `json:"shortcut"`
	Api          *ApiConfig          `json:"api"`
	Graph        *GraphConfig        `json:"graph"`
	Grpc         *GrpcConfig         `json:"grpc"`
	Mq           *MqConfig           `json:"mq"`
}

var (
	ConfigFile string
	config     *GlobalConfig
	configLock = new(sync.RWMutex)
)

func Config() *GlobalConfig {
	configLock.RLock()
	defer configLock.RUnlock()
	return config
}

func ParseConfig(cfg string) error {
	if cfg == "" {
		return fmt.Errorf("use -c to specify configuration file")
	}

	if !file.IsExist(cfg) {
		return fmt.Errorf("config file %s is nonexistent", cfg)
	}

	ConfigFile = cfg

	configContent, err := file.ToTrimString(cfg)
	if err != nil {
		return fmt.Errorf("read config file %s fail %s", cfg, err)
	}

	var c GlobalConfig
	err = json.Unmarshal([]byte(configContent), &c)
	if err != nil {
		return fmt.Errorf("parse config file %s fail %s", cfg, err)
	}

	configLock.Lock()
	defer configLock.Unlock()

	config = &c

	log.Println("read config file:", cfg, "successfully")
	return nil
}
<|endoftext|>


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

package languageserver

import (
	"sort"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
	"github.com/sourcegraph/go-langserver/pkg/lsp"
)

// document encapsulates all information required to map file locations to Kythe tickets
type document struct {
	refs      []*RefResolution
	oldSrc    string
	newSrc    string
	staleRefs bool
	defLocs   map[string]*lsp.Location
}

func newDocument(refs []*RefResolution, oldSrc string, newSrc string, defLocs map[string]*lsp.Location) *document {
	d := &document{
		refs:      refs,
		oldSrc:    oldSrc,
		newSrc:    newSrc,
		staleRefs: true,
		defLocs:   defLocs,
	}

	sort.Slice(d.refs, func(i, j int) bool {
		return posLess(d.refs[i].oldRange.Start, d.refs[j].oldRange.Start)
	})

	return d
}

// xrefs produces a Kythe ticket corresponding to the entity at a given
// position in the file
func (doc *document) xrefs(pos lsp.Position) *RefResolution {
	if doc.staleRefs {
		doc.generateNewRefs()
	}

	var smallestValidRef *RefResolution
	for _, r := range doc.refs {
		if r.newRange != nil &&
			rangeContains(*r.newRange, pos) &&
			(smallestValidRef == nil || smaller(*r.newRange, *smallestValidRef.newRange)) {
			smallestValidRef = r
		}
	}
	return smallestValidRef
}

// updateSource accepts new file contents to be used for diffing when next
// required This invalidates the previous diff
func (doc *document) updateSource(newSrc string) {
	doc.newSrc = newSrc
	doc.staleRefs = true
}

// rangeInNewSource takes in a range representing a ref in the oldSrc
// and returns that refs range in the newSrc if it exists
func (doc *document) rangeInNewSource(r lsp.Range) *lsp.Range {
	if doc.staleRefs {
		doc.generateNewRefs()
	}

	for _, ref := range doc.refs {
		if ref.oldRange == r {
			return ref.newRange
		}
	}

	return nil
}

// generateNewRefs generates refs by diffing the current file contents against
// the old contents
func (doc *document) generateNewRefs() {
	// Invalidate all previously calculated ranges
	for _, r := range doc.refs {
		r.newRange = nil
	}

	dmp := diffmatchpatch.New()
	diffs := dmp.DiffCleanupSemantic(dmp.DiffMain(doc.oldSrc, doc.newSrc, true))

	// oldPos & newPos track progress through the oldSrc and newSrc respectively
	var oldPos, newPos lsp.Position
	// refIdx represents progress through the refs slice
	refIdx := 0

diffLoop:
	for _, d := range diffs {
		// We know that if our position in the old file is greater than
		// start of the ref then the current diff cannot be used to produce
		// a new range. Because refs is sorted by the start location of the
		// oldRange, we can loop forward until the current ref is past oldPos,
		// invalidating the refs along the way
		for posLess(doc.refs[refIdx].oldRange.Start, oldPos) {
			refIdx++
			// If all refs have been adjusted, nothing else needs to be done
			if len(doc.refs) <= refIdx {
				break diffLoop
			}
		}

		// Because refs are stored as lsp locations which are essentially
		// (line, character) tuples, knowing the lines contained within the
		// diff segment will be relevant
		dLines := strings.Split(d.Text, "\n")
		// If there's no newline we can't say the diff spans any lines so we
		// subtract 1
		dLineLen := len(dLines) - 1
		dNewLine := dLineLen != 0
		// dOffset determines the amount of characters the last line of the diff
		// contains
		dOffset := len(dLines[dLineLen])

		switch d.Type {
		// If text was deleted, we "move past" it in the oldSrc so we move the
		// oldPos forward
		case diffmatchpatch.DiffDelete:
			// If there was new line in the diff, then we moved forward that many lines
			// and are now at the character offset of the last line. Otherwise, we've moved
			// further through the same line
			if dNewLine {
				oldPos.Line += dLineLen
				oldPos.Character = dOffset
			} else {
				oldPos.Character += dOffset
			}

		// If text was inserted, we have "move past" it in the newSrc so we move the
		// newPos forward
		case diffmatchpatch.DiffInsert:
			if dNewLine {
				newPos.Line += dLineLen
				newPos.Character = dOffset
			} else {
				newPos.Character += dOffset
			}

		// DiffEqual is the only case where can actually map refs because we know all
		// refs contained within the equality are preserved
		case diffmatchpatch.DiffEqual:
			var oldEndChar int
			if dNewLine {
				oldEndChar = dOffset
			} else {
				oldEndChar = oldPos.Character + dOffset
			}

			// This range represents the span of the diff in the oldSrc
			diffRange := lsp.Range{
				Start: oldPos,
				End: lsp.Position{
					Line:      oldPos.Line + dLineLen,
					Character: oldEndChar,
				},
			}

			// Declare iteration variables outside because i will become the new refIdx
			// when we break or finish
			var (
				ref *RefResolution
				i   int
			)
			// Loop over the remaining unprocessed refs
			for i, ref = range doc.refs[refIdx:] {
				// When the start position is past the diffRange we know all
				// refs within the equality have been updated
				if !rangeContains(diffRange, ref.oldRange.Start) {
					break
				}

				// If the ref extends beyond the diffRange, we know the ref will
				// be invalidated
				if !rangeContains(diffRange, ref.oldRange.End) {
					continue
				}

				var (
					refStartLine  = newPos.Line + (ref.oldRange.Start.Line - oldPos.Line)
					refOnDiffLine = refStartLine != newPos.Line
					refLineLength = ref.oldRange.End.Line - ref.oldRange.Start.Line
					refCharLength = ref.oldRange.End.Character - ref.oldRange.Start.Character
					refStartChar  int
					refEndChar    int
				)

				// If the ref is on a different line than newPos, we know a newline occurs
				// between newPos and the start of the ref, meaning the start character will
				// be unchanged. Otherwise we add the offset of the ref from oldPos to newPos
				if refOnDiffLine {
					refStartChar = ref.oldRange.Start.Character
				} else {
					refStartChar = newPos.Character + ref.oldRange.Start.Character - oldPos.Character
				}

				if refLineLength > 0 {
					refEndChar = ref.oldRange.End.Character
				} else {
					refEndChar = refStartChar + refCharLength
				}

				ref.newRange = &lsp.Range{
					Start: lsp.Position{Line: refStartLine, Character: refStartChar},
					End: lsp.Position{
						Line:      refStartLine + refLineLength,
						Character: refEndChar,
					},
				}
			}

			// We know there's no reason to go back to any refs
			// within the diffRange
			refIdx += i

			// On an equality we have to move both oldPos and newPos forward
			if dNewLine {
				oldPos.Line += dLineLen
				oldPos.Character = dOffset
				newPos.Line += dLineLen
				newPos.Character = dOffset
			} else {
				oldPos.Character += dOffset
				newPos.Character += dOffset
			}
		}
	}

	doc.staleRefs = false
}

// RefResolution represents the mapping from a location in a document to a
// Kythe ticket
type RefResolution struct {
	ticket   string
	def      string
	oldRange lsp.Range
	newRange *lsp.Range
}

func posLess(a, b lsp.Position) bool {
	if a.Line == b.Line {
		return a.Character < b.Character
	}
	return a.Line < b.Line
}

func posLeq(a, b lsp.Position) bool {
	if a.Line == b.Line {
		return a.Character <= b.Character
	}
	return a.Line < b.Line
}

// rangeContains checks whether a Range contains a Position. This
// check is inclusive because the position represents a cursor location.
// Consider an identifier "hi" at offset 0. Cursor positions 0-2 inclusive
// should match it.
func rangeContains(r lsp.Range, pos lsp.Position) bool {
	return posLeq(r.Start, pos) && posLeq(pos, r.End)
}

func smaller(r1, r2 lsp.Range) bool {
	r1lines := r1.End.Line - r1.Start.Line
	r2lines := r2.End.Line - r2.Start.Line

	if r1lines == r2lines {
		r1chars := r1.End.Character - r1.Start.Character
		r2chars := r2.End.Character - r2.Start.Character
		return r1chars < r2chars
	}
	return r1lines < r2lines
}
<commit_msg>Use lossless diffing for word-based diffing<commit_after>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package languageserver

import (
	"sort"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
	"github.com/sourcegraph/go-langserver/pkg/lsp"
)

// document encapsulates all information required to map file locations to Kythe tickets
type document struct {
	refs      []*RefResolution
	oldSrc    string
	newSrc    string
	staleRefs bool
	defLocs   map[string]*lsp.Location
}

func newDocument(refs []*RefResolution, oldSrc string, newSrc string, defLocs map[string]*lsp.Location) *document {
	d := &document{
		refs:      refs,
		oldSrc:    oldSrc,
		newSrc:    newSrc,
		staleRefs: true,
		defLocs:   defLocs,
	}

	sort.Slice(d.refs, func(i, j int) bool {
		return posLess(d.refs[i].oldRange.Start, d.refs[j].oldRange.Start)
	})

	return d
}

// xrefs produces a Kythe ticket corresponding to the entity at a given
// position in the file
func (doc *document) xrefs(pos lsp.Position) *RefResolution {
	if doc.staleRefs {
		doc.generateNewRefs()
	}

	var smallestValidRef *RefResolution
	for _, r := range doc.refs {
		if r.newRange != nil &&
			rangeContains(*r.newRange, pos) &&
			(smallestValidRef == nil || smaller(*r.newRange, *smallestValidRef.newRange)) {
			smallestValidRef = r
		}
	}
	return smallestValidRef
}

// updateSource accepts new file contents to be used for diffing when next
// required This invalidates the previous diff
func (doc *document) updateSource(newSrc string) {
	doc.newSrc = newSrc
	doc.staleRefs = true
}

// rangeInNewSource takes in a range representing a ref in the oldSrc
// and returns that refs range in the newSrc if it exists
func (doc *document) rangeInNewSource(r lsp.Range) *lsp.Range {
	if doc.staleRefs {
		doc.generateNewRefs()
	}

	for _, ref := range doc.refs {
		if ref.oldRange == r {
			return ref.newRange
		}
	}

	return nil
}

// generateNewRefs generates refs by diffing the current file contents against
// the old contents
func (doc *document) generateNewRefs() {
	// Invalidate all previously calculated ranges
	for _, r := range doc.refs {
		r.newRange = nil
	}

	dmp := diffmatchpatch.New()
	diffs := dmp.DiffCleanupSemanticLossless(dmp.DiffMain(doc.oldSrc, doc.newSrc, true))

	// oldPos & newPos track progress through the oldSrc and newSrc respectively
	var oldPos, newPos lsp.Position
	// refIdx represents progress through the refs slice
	refIdx := 0

diffLoop:
	for _, d := range diffs {
		// We know that if our position in the old file is greater than
		// start of the ref then the current diff cannot be used to produce
		// a new range. Because refs is sorted by the start location of the
		// oldRange, we can loop forward until the current ref is past oldPos,
		// invalidating the refs along the way
		for posLess(doc.refs[refIdx].oldRange.Start, oldPos) {
			refIdx++
			// If all refs have been adjusted, nothing else needs to be done
			if len(doc.refs) <= refIdx {
				break diffLoop
			}
		}

		// Because refs are stored as lsp locations which are essentially
		// (line, character) tuples, knowing the lines contained within the
		// diff segment will be relevant
		dLines := strings.Split(d.Text, "\n")
		// If there's no newline we can't say the diff spans any lines so we
		// subtract 1
		dLineLen := len(dLines) - 1
		dNewLine := dLineLen != 0
		// dOffset determines the amount of characters the last line of the diff
		// contains
		dOffset := len(dLines[dLineLen])

		switch d.Type {
		// If text was deleted, we "move past" it in the oldSrc so we move the
		// oldPos forward
		case diffmatchpatch.DiffDelete:
			// If there was new line in the diff, then we moved forward that many lines
			// and are now at the character offset of the last line. Otherwise, we've moved
			// further through the same line
			if dNewLine {
				oldPos.Line += dLineLen
				oldPos.Character = dOffset
			} else {
				oldPos.Character += dOffset
			}

		// If text was inserted, we have "move past" it in the newSrc so we move the
		// newPos forward
		case diffmatchpatch.DiffInsert:
			if dNewLine {
				newPos.Line += dLineLen
				newPos.Character = dOffset
			} else {
				newPos.Character += dOffset
			}

		// DiffEqual is the only case where can actually map refs because we know all
		// refs contained within the equality are preserved
		case diffmatchpatch.DiffEqual:
			var oldEndChar int
			if dNewLine {
				oldEndChar = dOffset
			} else {
				oldEndChar = oldPos.Character + dOffset
			}

			// This range represents the span of the diff in the oldSrc
			diffRange := lsp.Range{
				Start: oldPos,
				End: lsp.Position{
					Line:      oldPos.Line + dLineLen,
					Character: oldEndChar,
				},
			}

			// Declare iteration variables outside because i will become the new refIdx
			// when we break or finish
			var (
				ref *RefResolution
				i   int
			)
			// Loop over the remaining unprocessed refs
			for i, ref = range doc.refs[refIdx:] {
				// When the start position is past the diffRange we know all
				// refs within the equality have been updated
				if !rangeContains(diffRange, ref.oldRange.Start) {
					break
				}

				// If the ref extends beyond the diffRange, we know the ref will
				// be invalidated
				if !rangeContains(diffRange, ref.oldRange.End) {
					continue
				}

				var (
					refStartLine  = newPos.Line + (ref.oldRange.Start.Line - oldPos.Line)
					refOnDiffLine = refStartLine != newPos.Line
					refLineLength = ref.oldRange.End.Line - ref.oldRange.Start.Line
					refCharLength = ref.oldRange.End.Character - ref.oldRange.Start.Character
					refStartChar  int
					refEndChar    int
				)

				// If the ref is on a different line than newPos, we know a newline occurs
				// between newPos and the start of the ref, meaning the start character will
				// be unchanged. Otherwise we add the offset of the ref from oldPos to newPos
				if refOnDiffLine {
					refStartChar = ref.oldRange.Start.Character
				} else {
					refStartChar = newPos.Character + ref.oldRange.Start.Character - oldPos.Character
				}

				if refLineLength > 0 {
					refEndChar = ref.oldRange.End.Character
				} else {
					refEndChar = refStartChar + refCharLength
				}

				ref.newRange = &lsp.Range{
					Start: lsp.Position{Line: refStartLine, Character: refStartChar},
					End: lsp.Position{
						Line:      refStartLine + refLineLength,
						Character: refEndChar,
					},
				}
			}

			// We know there's no reason to go back to any refs
			// within the diffRange
			refIdx += i

			// On an equality we have to move both oldPos and newPos forward
			if dNewLine {
				oldPos.Line += dLineLen
				oldPos.Character = dOffset
				newPos.Line += dLineLen
				newPos.Character = dOffset
			} else {
				oldPos.Character += dOffset
				newPos.Character += dOffset
			}
		}
	}

	doc.staleRefs = false
}

// RefResolution represents the mapping from a location in a document to a
// Kythe ticket
type RefResolution struct {
	ticket   string
	def      string
	oldRange lsp.Range
	newRange *lsp.Range
}

func posLess(a, b lsp.Position) bool {
	if a.Line == b.Line {
		return a.Character < b.Character
	}
	return a.Line < b.Line
}

func posLeq(a, b lsp.Position) bool {
	if a.Line == b.Line {
		return a.Character <= b.Character
	}
	return a.Line < b.Line
}

// rangeContains checks whether a Range contains a Position. This
// check is inclusive because the position represents a cursor location.
// Consider an identifier "hi" at offset 0. Cursor positions 0-2 inclusive
// should match it.
func rangeContains(r lsp.Range, pos lsp.Position) bool {
	return posLeq(r.Start, pos) && posLeq(pos, r.End)
}

func smaller(r1, r2 lsp.Range) bool {
	r1lines := r1.End.Line - r1.Start.Line
	r2lines := r2.End.Line - r2.Start.Line

	if r1lines == r2lines {
		r1chars := r1.End.Character - r1.Start.Character
		r2chars := r2.End.Character - r2.Start.Character
		return r1chars < r2chars
	}
	return r1lines < r2lines
}
<|endoftext|>


<commit_before>package goscaleio

import (
	"errors"
	"fmt"
	"reflect"

	types "github.com/emccode/goscaleio/types/v1"
)

type Sdc struct {
	Sdc    *types.Sdc
	client *Client
}

func NewSdc(client *Client, sdc *types.Sdc) *Sdc {
	return &Sdc{
		Sdc:    sdc,
		client: client,
	}
}

func (system *System) GetSdc() (sdcs []types.Sdc, err error) {
	endpoint := system.client.SIOEndpoint
	endpoint.Path = fmt.Sprintf("/api/instances/System::%v/relationships/Sdc", system.System.ID)

	req := system.client.NewRequest(map[string]string{}, "GET", endpoint, nil)
	req.SetBasicAuth("", system.client.Token)
	req.Header.Add("Accept", "application/json;version=1.0")

	resp, err := checkResp(system.client.Http.Do(req))
	if err != nil {
		return []types.Sdc{}, fmt.Errorf("problem getting response: %v", err)
	}
	defer resp.Body.Close()

	if err = decodeBody(resp, &sdcs); err != nil {
		return []types.Sdc{}, fmt.Errorf("error decoding instances response: %s", err)
	}

	// bs, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	// 	return []types.Sdc{}, errors.New("error reading body")
	// }
	//
	// fmt.Println(string(bs))
	// log.Fatalf("here")
	// return []types.Sdc{}, nil
	return sdcs, nil
}

func (system *System) FindSdc(field, value string) (sdc *Sdc, err error) {
	sdcs, err := system.GetSdc()
	if err != nil {
		return &Sdc{}, nil
	}

	for _, sdc := range sdcs {
		valueOf := reflect.ValueOf(sdc)
		switch {
		case reflect.Indirect(valueOf).FieldByName(field).String() == value:
			return NewSdc(system.client, &sdc), nil
		}
	}

	return &Sdc{}, errors.New("Couldn't find SDC")
}

func (sdc *Sdc) GetStatistics() (statistics types.Statistics, err error) {
	endpoint := sdc.client.SIOEndpoint
	endpoint.Path = fmt.Sprintf("/api/instances/Sdc::%v/relationships/Statistics", sdc.Sdc.ID)

	req := sdc.client.NewRequest(map[string]string{}, "GET", endpoint, nil)
	req.SetBasicAuth("", sdc.client.Token)
	req.Header.Add("Accept", "application/json;version=1.0")

	resp, err := checkResp(sdc.client.Http.Do(req))
	if err != nil {
		return types.Statistics{}, fmt.Errorf("problem getting response: %v", err)
	}
	defer resp.Body.Close()

	if err = decodeBody(resp, &statistics); err != nil {
		return types.Statistics{}, fmt.Errorf("error decoding instances response: %s", err)
	}

	// bs, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	// 	return errors.New("error reading body")
	// }
	//
	// fmt.Println(string(bs))
	return statistics, nil
}
<commit_msg>added sdc local<commit_after>package goscaleio

import (
	"errors"
	"fmt"
	"os/exec"
	"reflect"
	"strings"

	types "github.com/emccode/goscaleio/types/v1"
)

type Sdc struct {
	Sdc    *types.Sdc
	client *Client
}

func NewSdc(client *Client, sdc *types.Sdc) *Sdc {
	return &Sdc{
		Sdc:    sdc,
		client: client,
	}
}

func (system *System) GetSdc() (sdcs []types.Sdc, err error) {
	endpoint := system.client.SIOEndpoint
	endpoint.Path = fmt.Sprintf("/api/instances/System::%v/relationships/Sdc", system.System.ID)

	req := system.client.NewRequest(map[string]string{}, "GET", endpoint, nil)
	req.SetBasicAuth("", system.client.Token)
	req.Header.Add("Accept", "application/json;version=1.0")

	resp, err := checkResp(system.client.Http.Do(req))
	if err != nil {
		return []types.Sdc{}, fmt.Errorf("problem getting response: %v", err)
	}
	defer resp.Body.Close()

	if err = decodeBody(resp, &sdcs); err != nil {
		return []types.Sdc{}, fmt.Errorf("error decoding instances response: %s", err)
	}

	// bs, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	// 	return []types.Sdc{}, errors.New("error reading body")
	// }
	//
	// fmt.Println(string(bs))
	// log.Fatalf("here")
	// return []types.Sdc{}, nil
	return sdcs, nil
}

func (system *System) FindSdc(field, value string) (sdc *Sdc, err error) {
	sdcs, err := system.GetSdc()
	if err != nil {
		return &Sdc{}, nil
	}

	for _, sdc := range sdcs {
		valueOf := reflect.ValueOf(sdc)
		switch {
		case reflect.Indirect(valueOf).FieldByName(field).String() == value:
			return NewSdc(system.client, &sdc), nil
		}
	}

	return &Sdc{}, errors.New("Couldn't find SDC")
}

func (sdc *Sdc) GetStatistics() (statistics types.Statistics, err error) {
	endpoint := sdc.client.SIOEndpoint
	endpoint.Path = fmt.Sprintf("/api/instances/Sdc::%v/relationships/Statistics", sdc.Sdc.ID)

	req := sdc.client.NewRequest(map[string]string{}, "GET", endpoint, nil)
	req.SetBasicAuth("", sdc.client.Token)
	req.Header.Add("Accept", "application/json;version=1.0")

	resp, err := checkResp(sdc.client.Http.Do(req))
	if err != nil {
		return types.Statistics{}, fmt.Errorf("problem getting response: %v", err)
	}
	defer resp.Body.Close()

	if err = decodeBody(resp, &statistics); err != nil {
		return types.Statistics{}, fmt.Errorf("error decoding instances response: %s", err)
	}

	// bs, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	// 	return errors.New("error reading body")
	// }
	//
	// fmt.Println(string(bs))
	return statistics, nil
}

func GetSdcLocalGUID() (sdcGUID string, err error) {

	// get sdc kernel guid
	// /bin/emc/scaleio/drv_cfg --query_guid
	// sdcKernelGuid := "271bad82-08ee-44f2-a2b1-7e2787c27be1"

	out, err := exec.Command("/bin/emc/scaleio/drv_cfg", "--query_guid").Output()
	if err != nil {
		return "", fmt.Errorf("Error querying volumes: ", err)
	}

	sdcGUID = strings.Replace(string(out), "\n", "", -1)

	return sdcGUID, nil

}
<|endoftext|>


<commit_before>package storage

import (
	"bytes"
	"crypto/tls"
	"os"
	"strconv"
	"sync"

	"github.com/blevesearch/bleve"
	"github.com/boltdb/bolt"
)

type User struct {
	ID       uint64
	Username string

	id           []byte
	messageLog   *bolt.DB
	messageIndex bleve.Index
	certificate  *tls.Certificate
	lock         sync.Mutex
}

type Server struct {
	Name      string `json:"name"`
	Host      string `json:"host"`
	Port      string `json:"port,omitempty"`
	TLS       bool   `json:"tls,omitempty"`
	Password  string `json:"password,omitempty"`
	Nick      string `json:"nick"`
	Username  string `json:"username,omitempty"`
	Realname  string `json:"realname,omitempty"`
	Connected bool   `json:"connected"`
}

type Channel struct {
	Server string `json:"server"`
	Name   string `json:"name"`
	Topic  string `json:"topic,omitempty"`
}

func NewUser() (*User, error) {
	user := &User{}

	err := db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketUsers)

		user.ID, _ = b.NextSequence()
		user.Username = strconv.FormatUint(user.ID, 10)

		data, err := user.Marshal(nil)
		if err != nil {
			return err
		}

		user.id = idToBytes(user.ID)
		return b.Put(user.id, data)
	})

	if err != nil {
		return nil, err
	}

	err = user.openMessageLog()
	if err != nil {
		return nil, err
	}

	return user, nil
}

func LoadUsers() []*User {
	var users []*User

	db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketUsers)

		b.ForEach(func(k, _ []byte) error {
			id := idFromBytes(k)
			user := &User{
				ID:       id,
				Username: strconv.FormatUint(id, 10),
				id:       make([]byte, 8),
			}
			copy(user.id, k)

			users = append(users, user)

			return nil
		})

		return nil
	})

	for _, user := range users {
		user.openMessageLog()
		user.loadCertificate()
	}

	return users
}

func (u *User) GetServers() []Server {
	var servers []Server

	db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket(bucketServers).Cursor()

		for k, v := c.Seek(u.id); bytes.HasPrefix(k, u.id); k, v = c.Next() {
			server := Server{}
			server.Unmarshal(v)
			servers = append(servers, server)
		}

		return nil
	})

	return servers
}

func (u *User) GetChannels() []Channel {
	var channels []Channel

	db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket(bucketChannels).Cursor()

		for k, v := c.Seek(u.id); bytes.HasPrefix(k, u.id); k, v = c.Next() {
			channel := Channel{}
			channel.Unmarshal(v)
			channels = append(channels, channel)
		}

		return nil
	})

	return channels
}

func (u *User) AddServer(server Server) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketServers)
		data, _ := server.Marshal(nil)

		b.Put(u.serverID(server.Host), data)

		return nil
	})
}

func (u *User) AddChannel(channel Channel) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketChannels)
		data, _ := channel.Marshal(nil)

		b.Put(u.channelID(channel.Server, channel.Name), data)

		return nil
	})
}

func (u *User) SetNick(nick, address string) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketServers)
		id := u.serverID(address)

		server := Server{}
		server.Unmarshal(b.Get(id))
		server.Nick = nick

		data, _ := server.Marshal(nil)
		b.Put(id, data)

		return nil
	})
}

func (u *User) RemoveServer(address string) {
	db.Batch(func(tx *bolt.Tx) error {
		serverID := u.serverID(address)
		tx.Bucket(bucketServers).Delete(serverID)

		b := tx.Bucket(bucketChannels)
		c := b.Cursor()

		for k, _ := c.Seek(serverID); bytes.HasPrefix(k, serverID); k, _ = c.Next() {
			b.Delete(k)
		}

		return nil
	})
}

func (u *User) RemoveChannel(server, channel string) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketChannels)
		id := u.channelID(server, channel)

		b.Delete(id)

		return nil
	})
}

func (u *User) Remove() {
	db.Batch(func(tx *bolt.Tx) error {
		return tx.Bucket(bucketUsers).Delete(u.id)
	})
	u.closeMessageLog()
	os.RemoveAll(Path.User(u.Username))
}

func (u *User) serverID(address string) []byte {
	id := make([]byte, 8+len(address))
	copy(id, u.id)
	copy(id[8:], address)
	return id
}

func (u *User) channelID(server, channel string) []byte {
	id := make([]byte, 8+len(server)+1+len(channel))
	copy(id, u.id)
	copy(id[8:], server)
	copy(id[8+len(server)+1:], channel)
	return id
}
<commit_msg>Check if server exists in storage.User.SetNick()<commit_after>package storage

import (
	"bytes"
	"crypto/tls"
	"os"
	"strconv"
	"sync"

	"github.com/blevesearch/bleve"
	"github.com/boltdb/bolt"
)

type User struct {
	ID       uint64
	Username string

	id           []byte
	messageLog   *bolt.DB
	messageIndex bleve.Index
	certificate  *tls.Certificate
	lock         sync.Mutex
}

type Server struct {
	Name      string `json:"name"`
	Host      string `json:"host"`
	Port      string `json:"port,omitempty"`
	TLS       bool   `json:"tls,omitempty"`
	Password  string `json:"password,omitempty"`
	Nick      string `json:"nick"`
	Username  string `json:"username,omitempty"`
	Realname  string `json:"realname,omitempty"`
	Connected bool   `json:"connected"`
}

type Channel struct {
	Server string `json:"server"`
	Name   string `json:"name"`
	Topic  string `json:"topic,omitempty"`
}

func NewUser() (*User, error) {
	user := &User{}

	err := db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketUsers)

		user.ID, _ = b.NextSequence()
		user.Username = strconv.FormatUint(user.ID, 10)

		data, err := user.Marshal(nil)
		if err != nil {
			return err
		}

		user.id = idToBytes(user.ID)
		return b.Put(user.id, data)
	})

	if err != nil {
		return nil, err
	}

	err = user.openMessageLog()
	if err != nil {
		return nil, err
	}

	return user, nil
}

func LoadUsers() []*User {
	var users []*User

	db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketUsers)

		b.ForEach(func(k, _ []byte) error {
			id := idFromBytes(k)
			user := &User{
				ID:       id,
				Username: strconv.FormatUint(id, 10),
				id:       make([]byte, 8),
			}
			copy(user.id, k)

			users = append(users, user)

			return nil
		})

		return nil
	})

	for _, user := range users {
		user.openMessageLog()
		user.loadCertificate()
	}

	return users
}

func (u *User) GetServers() []Server {
	var servers []Server

	db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket(bucketServers).Cursor()

		for k, v := c.Seek(u.id); bytes.HasPrefix(k, u.id); k, v = c.Next() {
			server := Server{}
			server.Unmarshal(v)
			servers = append(servers, server)
		}

		return nil
	})

	return servers
}

func (u *User) GetChannels() []Channel {
	var channels []Channel

	db.View(func(tx *bolt.Tx) error {
		c := tx.Bucket(bucketChannels).Cursor()

		for k, v := c.Seek(u.id); bytes.HasPrefix(k, u.id); k, v = c.Next() {
			channel := Channel{}
			channel.Unmarshal(v)
			channels = append(channels, channel)
		}

		return nil
	})

	return channels
}

func (u *User) AddServer(server Server) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketServers)
		data, _ := server.Marshal(nil)

		b.Put(u.serverID(server.Host), data)

		return nil
	})
}

func (u *User) AddChannel(channel Channel) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketChannels)
		data, _ := channel.Marshal(nil)

		b.Put(u.channelID(channel.Server, channel.Name), data)

		return nil
	})
}

func (u *User) SetNick(nick, address string) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketServers)
		id := u.serverID(address)

		server := Server{}
		v := b.Get(id)
		if v != nil {
			server.Unmarshal(v)
			server.Nick = nick

			data, _ := server.Marshal(nil)
			b.Put(id, data)
		}

		return nil
	})
}

func (u *User) RemoveServer(address string) {
	db.Batch(func(tx *bolt.Tx) error {
		serverID := u.serverID(address)
		tx.Bucket(bucketServers).Delete(serverID)

		b := tx.Bucket(bucketChannels)
		c := b.Cursor()

		for k, _ := c.Seek(serverID); bytes.HasPrefix(k, serverID); k, _ = c.Next() {
			b.Delete(k)
		}

		return nil
	})
}

func (u *User) RemoveChannel(server, channel string) {
	db.Batch(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketChannels)
		id := u.channelID(server, channel)

		b.Delete(id)

		return nil
	})
}

func (u *User) Remove() {
	db.Batch(func(tx *bolt.Tx) error {
		return tx.Bucket(bucketUsers).Delete(u.id)
	})
	u.closeMessageLog()
	os.RemoveAll(Path.User(u.Username))
}

func (u *User) serverID(address string) []byte {
	id := make([]byte, 8+len(address))
	copy(id, u.id)
	copy(id[8:], address)
	return id
}

func (u *User) channelID(server, channel string) []byte {
	id := make([]byte, 8+len(server)+1+len(channel))
	copy(id, u.id)
	copy(id[8:], server)
	copy(id[8+len(server)+1:], channel)
	return id
}
<|endoftext|>