<commit_before>package stores

import (
	"testing"

	"github.com/davelondon/ktest/assert"
	"github.com/davelondon/ktest/require"

	"kego.io/system/node"
	"kego.io/tests/data"
)

func TestAddMutation(t *testing.T) {

	cb, n := data.Setup(t)

	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var a, p *node.Node

		a = node.NewNode()
		p = n.Map["ajs"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 5, len(n.Map["ajs"].Array))
		assert.Equal(t, 5, len(m.Ajs))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 4, len(n.Map["ajs"].Array))
		assert.Equal(t, 4, len(m.Ajs))

		a = node.NewNode()
		p = n.Map["ass"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 5, len(n.Map["ass"].Array))
		assert.Equal(t, 5, len(m.Ass))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 4, len(n.Map["ass"].Array))
		assert.Equal(t, 4, len(m.Ass))

		a = node.NewNode()
		p = n.Map["am"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 3, len(n.Map["am"].Array))
		assert.Equal(t, 3, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 3, len(m.Am))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 2, len(m.Am))
	}

	data.Run(t, n, n.Value.(*data.Multi), test)
}

func TestAddMutation2(t *testing.T) {
	cb, n := data.Setup(t)
	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var a, p *node.Node
		a = node.NewNode()
		p = n.Map["am"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 3, len(n.Map["am"].Array))
		assert.Equal(t, 3, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 3, len(m.Am))
		assert.Equal(t, "", m.Am[0].Js)
		assert.Equal(t, "amjs0", m.Am[1].Js)
		assert.Equal(t, "amjs1", m.Am[2].Js)
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 2, len(m.Am))
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
	}
	test(t, n.Map["m"], n.Value.(*data.Multi).M)
}

func TestDeleteMutation(t *testing.T) {

	cb, n := data.Setup(t)

	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var b, d, p *node.Node

		b = &node.Node{}
		d = n.Map["jb"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["jb"].ValueBool)
		assert.False(t, m.Jb)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["jb"].ValueBool)
		assert.True(t, m.Jb)

		b = &node.Node{}
		d = n.Map["ss"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["ss"].Missing)
		assert.Equal(t, "", n.Map["ss"].ValueString)
		assert.Nil(t, m.Ss)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["ss"].Missing)
		assert.Equal(t, "ss1", n.Map["ss"].ValueString)
		require.NotNil(t, m.Ss)
		assert.Equal(t, "ss1", m.Ss.Value())

		b = &node.Node{}
		d = n.Map["i"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["i"].Missing)
		assert.Nil(t, m.I)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["i"].Missing)
		assert.Equal(t, "ia", n.Map["i"].Value.(*data.Facea).A.Value())
		require.NotNil(t, m.I)
		assert.Equal(t, "ia", m.I.Face())

		b = &node.Node{}
		d = n.Map["ass"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["ass"].Missing)
		assert.Equal(t, 0, len(m.Ass))
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["ass"].Missing)
		assert.Equal(t, 4, len(m.Ass))

		b = &node.Node{}
		d = n.Map["mss"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["mss"].Missing)
		assert.Nil(t, m.Mss)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["mss"].Missing)
		require.NotNil(t, m.Mss)
		assert.Equal(t, 2, len(m.Mss))
		require.NotNil(t, m.Mss["a"])
		assert.Equal(t, "mssa", m.Mss["a"].Value())

		b = &node.Node{}
		d = n.Map["ass"].Array[0]
		p = n.Map["ass"]
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 3, len(n.Map["ass"].Array))
		assert.Equal(t, 3, len(m.Ass))
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 4, len(n.Map["ass"].Array))
		assert.Equal(t, 4, len(m.Ass))
		assert.Equal(t, "ass0", n.Map["ass"].Array[0].ValueString)
		require.NotNil(t, m.Ass[0])
		assert.Equal(t, "ass0", m.Ass[0].Value())

	}

	data.Run(t, n, n.Value.(*data.Multi), test)
}

func TestDeleteMutation1(t *testing.T) {
	cb, n := data.Setup(t)
	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var b, d, p *node.Node
		b = &node.Node{}
		d = n.Map["am"].Array[0]
		p = n.Map["am"]
		assert.Equal(t, "amjs0", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", n.Map["am"].Array[1].Map["js"].ValueString)
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 1, len(n.Map["am"].Array))
		assert.Equal(t, 1, len(m.Am))
		assert.Equal(t, "amjs1", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", m.Am[0].Js)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(m.Am))
		assert.Equal(t, "amjs0", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", n.Map["am"].Array[1].Map["js"].ValueString)
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
	}
	test(t, n.Map["m"], n.Value.(*data.Multi).M)
}
<commit_msg>Added redo test<commit_after>package stores

import (
	"testing"

	"github.com/davelondon/ktest/assert"
	"github.com/davelondon/ktest/require"

	"kego.io/system"
	"kego.io/system/node"
	"kego.io/tests/data"
)

func TestAddMutationRedo(t *testing.T) {
	cb, n := data.Setup(t)

	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var a, p *node.Node
		a = node.NewNode()
		p = n.Map["am"]
		ty, ok := system.GetTypeFromCache(cb.Ctx(), "kego.io/tests/data", "multi")
		require.True(t, ok)
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 2, ty))
		a1 := node.NewNode()
		p1 := n.Map["am"].Array[2]
		require.NoError(t, mutateAddNode(cb.Ctx(), a1, p1, "m", -1, ty))
		require.Equal(t, 3, len(n.Map["am"].Array))
		require.Equal(t, 3, len(m.Am))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p1, "m", -1))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 2))
		require.Equal(t, 2, len(n.Map["am"].Array))
		require.Equal(t, 2, len(m.Am))
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 2, ty))
		require.NoError(t, mutateAddNode(cb.Ctx(), a1, p1, "m", -1, ty))
		require.Equal(t, 3, len(n.Map["am"].Array))
		require.Equal(t, 3, len(m.Am))
		require.NotNil(t, n.Map["am"].Array[2])
		require.NotNil(t, m.Am[2])
	}

	test(t, n.Map["m"], n.Value.(*data.Multi).M)
}

func TestAddMutation(t *testing.T) {

	cb, n := data.Setup(t)

	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var a, p *node.Node

		a = node.NewNode()
		p = n.Map["ajs"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 5, len(n.Map["ajs"].Array))
		assert.Equal(t, 5, len(m.Ajs))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 4, len(n.Map["ajs"].Array))
		assert.Equal(t, 4, len(m.Ajs))

		a = node.NewNode()
		p = n.Map["ass"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 5, len(n.Map["ass"].Array))
		assert.Equal(t, 5, len(m.Ass))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 4, len(n.Map["ass"].Array))
		assert.Equal(t, 4, len(m.Ass))

		a = node.NewNode()
		p = n.Map["am"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 3, len(n.Map["am"].Array))
		assert.Equal(t, 3, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 3, len(m.Am))
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 2, len(m.Am))
	}

	data.Run(t, n, n.Value.(*data.Multi), test)
}

func TestAddMutation2(t *testing.T) {
	cb, n := data.Setup(t)
	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var a, p *node.Node
		a = node.NewNode()
		p = n.Map["am"]
		require.NoError(t, mutateAddNode(cb.Ctx(), a, p, "", 0, nil))
		assert.Equal(t, 3, len(n.Map["am"].Array))
		assert.Equal(t, 3, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 3, len(m.Am))
		assert.Equal(t, "", m.Am[0].Js)
		assert.Equal(t, "amjs0", m.Am[1].Js)
		assert.Equal(t, "amjs1", m.Am[2].Js)
		require.NoError(t, mutateUndoAddNode(cb.Ctx(), p, "", 0))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(n.Map["am"].Value.([]*data.Multi)))
		assert.Equal(t, 2, len(m.Am))
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
	}
	test(t, n.Map["m"], n.Value.(*data.Multi).M)
}

func TestDeleteMutation(t *testing.T) {

	cb, n := data.Setup(t)

	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var b, d, p *node.Node

		b = &node.Node{}
		d = n.Map["jb"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["jb"].ValueBool)
		assert.False(t, m.Jb)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["jb"].ValueBool)
		assert.True(t, m.Jb)

		b = &node.Node{}
		d = n.Map["ss"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["ss"].Missing)
		assert.Equal(t, "", n.Map["ss"].ValueString)
		assert.Nil(t, m.Ss)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["ss"].Missing)
		assert.Equal(t, "ss1", n.Map["ss"].ValueString)
		require.NotNil(t, m.Ss)
		assert.Equal(t, "ss1", m.Ss.Value())

		b = &node.Node{}
		d = n.Map["i"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["i"].Missing)
		assert.Nil(t, m.I)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["i"].Missing)
		assert.Equal(t, "ia", n.Map["i"].Value.(*data.Facea).A.Value())
		require.NotNil(t, m.I)
		assert.Equal(t, "ia", m.I.Face())

		b = &node.Node{}
		d = n.Map["ass"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["ass"].Missing)
		assert.Equal(t, 0, len(m.Ass))
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["ass"].Missing)
		assert.Equal(t, 4, len(m.Ass))

		b = &node.Node{}
		d = n.Map["mss"]
		p = n
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.True(t, n.Map["mss"].Missing)
		assert.Nil(t, m.Mss)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.False(t, n.Map["mss"].Missing)
		require.NotNil(t, m.Mss)
		assert.Equal(t, 2, len(m.Mss))
		require.NotNil(t, m.Mss["a"])
		assert.Equal(t, "mssa", m.Mss["a"].Value())

		b = &node.Node{}
		d = n.Map["ass"].Array[0]
		p = n.Map["ass"]
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 3, len(n.Map["ass"].Array))
		assert.Equal(t, 3, len(m.Ass))
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 4, len(n.Map["ass"].Array))
		assert.Equal(t, 4, len(m.Ass))
		assert.Equal(t, "ass0", n.Map["ass"].Array[0].ValueString)
		require.NotNil(t, m.Ass[0])
		assert.Equal(t, "ass0", m.Ass[0].Value())

	}

	data.Run(t, n, n.Value.(*data.Multi), test)
}

func TestDeleteMutation1(t *testing.T) {
	cb, n := data.Setup(t)
	test := func(t *testing.T, n *node.Node, m *data.Multi) {
		var b, d, p *node.Node
		b = &node.Node{}
		d = n.Map["am"].Array[0]
		p = n.Map["am"]
		assert.Equal(t, "amjs0", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", n.Map["am"].Array[1].Map["js"].ValueString)
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
		require.NoError(t, mutateDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 1, len(n.Map["am"].Array))
		assert.Equal(t, 1, len(m.Am))
		assert.Equal(t, "amjs1", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", m.Am[0].Js)
		require.NoError(t, mutateUndoDeleteNode(cb.Ctx(), d, p, b))
		assert.Equal(t, 2, len(n.Map["am"].Array))
		assert.Equal(t, 2, len(m.Am))
		assert.Equal(t, "amjs0", n.Map["am"].Array[0].Map["js"].ValueString)
		assert.Equal(t, "amjs1", n.Map["am"].Array[1].Map["js"].ValueString)
		assert.Equal(t, "amjs0", m.Am[0].Js)
		assert.Equal(t, "amjs1", m.Am[1].Js)
	}
	test(t, n.Map["m"], n.Value.(*data.Multi).M)
}
<|endoftext|>


<commit_before>package sitemap

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

// Index is a structure of <sitemapindex>
type Index struct {
	XMLName xml.Name `xml:"sitemapindex"`
	Sitemap []parts  `xml:"sitemap"`
}

// parts is a structure of <sitemap> in <sitemapindex>
type parts struct {
	Loc     string `xml:"loc"`
	LastMod string `xml:"lastmod"`
}

// Sitemap is a structure of <sitemap>
type Sitemap struct {
	XMLName xml.Name `xml:"urlset"`
	URL     []URL    `xml:"url"`
}

// URL is a structure of <url> in <sitemap>
type URL struct {
	Loc        string  `xml:"loc"`
	LastMod    string  `xml:"lastmod"`
	ChangeFreq string  `xml:"changefreq"`
	Priority   float32 `xml:"priority"`
}

// fetch is page acquisition function
var fetch = func(URL string, options interface{}) ([]byte, error) {
	var body []byte

	res, err := http.Get(URL)
	if err != nil {
		return body, err
	}
	defer res.Body.Close()

	return ioutil.ReadAll(res.Body)
}

// Time interval to be used in Index.get
var interval = time.Second

// Get sitemap data from URL
func Get(URL string, options interface{}) (Sitemap, error) {
	data, err := fetch(URL, options)
	if err != nil {
		return Sitemap{}, err
	}

	idx, idxErr := ParseIndex(data)
	smap, smapErr := Parse(data)

	if idxErr != nil && smapErr != nil {
		if idxErr != nil {
			err = idxErr
		} else {
			err = smapErr
		}
		return Sitemap{}, fmt.Errorf("URL is not a sitemap or sitemapindex: %v", err)
	} else if idxErr != nil {
		return smap, nil
	}

	smap, err = idx.get(data, options)
	if err != nil {
		return Sitemap{}, err
	}

	return smap, nil
}

// Get Sitemap data from sitemapindex file
func (s *Index) get(data []byte, options interface{}) (Sitemap, error) {
	idx, err := ParseIndex(data)
	if err != nil {
		return Sitemap{}, err
	}

	var smap Sitemap
	for _, s := range idx.Sitemap {
		time.Sleep(interval)
		data, err := fetch(s.Loc, options)
		if err != nil {
			return smap, err
		}

		err = xml.Unmarshal(data, &smap)
		if err != nil {
			return smap, err
		}
	}

	return smap, err
}

// Parse create Sitemap data from text
func Parse(data []byte) (Sitemap, error) {
	var smap Sitemap
	if len(data) == 0 {
		return smap, fmt.Errorf("sitemap.xml is empty.")
	}

	err := xml.Unmarshal(data, &smap)
	return smap, err
}

// ParseIndex create Index data from text
func ParseIndex(data []byte) (Index, error) {
	var idx Index
	if len(data) == 0 {
		return idx, fmt.Errorf("sitemapindex.xml is empty.")
	}

	err := xml.Unmarshal(data, &idx)
	return idx, err
}

// SetInterval change Time interval to be used in Index.get
func SetInterval(time time.Duration) {
	interval = time
}

// SetFetch change fetch closure
func SetFetch(f func(URL string, options interface{}) ([]byte, error)) {
	fetch = f
}
<commit_msg>update variable declaration<commit_after>package sitemap

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

// Index is a structure of <sitemapindex>
type Index struct {
	XMLName xml.Name `xml:"sitemapindex"`
	Sitemap []parts  `xml:"sitemap"`
}

// parts is a structure of <sitemap> in <sitemapindex>
type parts struct {
	Loc     string `xml:"loc"`
	LastMod string `xml:"lastmod"`
}

// Sitemap is a structure of <sitemap>
type Sitemap struct {
	XMLName xml.Name `xml:"urlset"`
	URL     []URL    `xml:"url"`
}

// URL is a structure of <url> in <sitemap>
type URL struct {
	Loc        string  `xml:"loc"`
	LastMod    string  `xml:"lastmod"`
	ChangeFreq string  `xml:"changefreq"`
	Priority   float32 `xml:"priority"`
}

var (
	// fetch is page acquisition function
	fetch = func(URL string, options interface{}) ([]byte, error) {
		var body []byte

		res, err := http.Get(URL)
		if err != nil {
			return body, err
		}
		defer res.Body.Close()

		return ioutil.ReadAll(res.Body)
	}

	// Time interval to be used in Index.get
	interval = time.Second
)

// Get sitemap data from URL
func Get(URL string, options interface{}) (Sitemap, error) {
	data, err := fetch(URL, options)
	if err != nil {
		return Sitemap{}, err
	}

	idx, idxErr := ParseIndex(data)
	smap, smapErr := Parse(data)

	if idxErr != nil && smapErr != nil {
		if idxErr != nil {
			err = idxErr
		} else {
			err = smapErr
		}
		return Sitemap{}, fmt.Errorf("URL is not a sitemap or sitemapindex: %v", err)
	} else if idxErr != nil {
		return smap, nil
	}

	smap, err = idx.get(data, options)
	if err != nil {
		return Sitemap{}, err
	}

	return smap, nil
}

// Get Sitemap data from sitemapindex file
func (s *Index) get(data []byte, options interface{}) (Sitemap, error) {
	idx, err := ParseIndex(data)
	if err != nil {
		return Sitemap{}, err
	}

	var smap Sitemap
	for _, s := range idx.Sitemap {
		time.Sleep(interval)
		data, err := fetch(s.Loc, options)
		if err != nil {
			return smap, err
		}

		err = xml.Unmarshal(data, &smap)
		if err != nil {
			return smap, err
		}
	}

	return smap, err
}

// Parse create Sitemap data from text
func Parse(data []byte) (Sitemap, error) {
	var smap Sitemap
	if len(data) == 0 {
		return smap, fmt.Errorf("sitemap.xml is empty.")
	}

	err := xml.Unmarshal(data, &smap)
	return smap, err
}

// ParseIndex create Index data from text
func ParseIndex(data []byte) (Index, error) {
	var idx Index
	if len(data) == 0 {
		return idx, fmt.Errorf("sitemapindex.xml is empty.")
	}

	err := xml.Unmarshal(data, &idx)
	return idx, err
}

// SetInterval change Time interval to be used in Index.get
func SetInterval(time time.Duration) {
	interval = time
}

// SetFetch change fetch closure
func SetFetch(f func(URL string, options interface{}) ([]byte, error)) {
	fetch = f
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/jingweno/jqplay/jq"
	"gopkg.in/unrolled/render.v1"
)

const (
	JSONPayloadLimit   = JSONPayloadLimitMB * OneMB
	JSONPayloadLimitMB = 5
	OneMB              = 1024000
)

type JQHandlerContext struct {
	*Config
	JQ string
}

func (c *JQHandlerContext) Asset(path string) string {
	return fmt.Sprintf("%s/%s", c.Config.AssetHost, path)
}

func (c *JQHandlerContext) ShouldInitJQ() bool {
	return c.JQ != ""
}

type JQHandler struct {
	r *render.Render
	c *Config
}

func (h *JQHandler) handleIndex(rw http.ResponseWriter, r *http.Request) {
	h.r.HTML(rw, 200, "index", &JQHandlerContext{Config: h.c})
}

func (h *JQHandler) handleJqPost(rw http.ResponseWriter, r *http.Request) {
	if r.ContentLength == -1 {
		log.Printf("Error: Content length is unknown")
	}

	if r.ContentLength > JSONPayloadLimit {
		msg := fmt.Sprintf("JSON payload size is %.1fMB, larger than limit %dMB.", float64(r.ContentLength)/OneMB, JSONPayloadLimitMB)
		log.Printf("Error: %s", msg)
		h.r.JSON(rw, 403, map[string]string{
			"message": msg,
		})

		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		rw.WriteHeader(422)
		fmt.Fprint(rw, err.Error())
		return
	}
	defer r.Body.Close()

	var jq *jq.JQ
	err = json.Unmarshal(b, &jq)
	if err != nil {
		rw.WriteHeader(422)
		fmt.Fprint(rw, err.Error())
		return
	}

	err = jq.Eval(rw)
	if err != nil {
		rw.WriteHeader(422)
		fmt.Fprint(rw, err.Error())
		return
	}
}

func (h *JQHandler) handleJqGet(rw http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	jq := &jq.JQ{
		J: q.Get("j"),
		Q: q.Get("q"),
	}

	var jqData string
	if err := jq.Validate(); err == nil {
		d, err := json.Marshal(jq)
		if err == nil {
			jqData = string(d)
		}
	}

	h.r.HTML(rw, 200, "index", &JQHandlerContext{Config: h.c, JQ: jqData})
}

func (h *JQHandler) handleJq(rw http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		h.handleJqPost(rw, r)
		return
	}

	if r.Method == "GET" {
		h.handleJqGet(rw, r)
		return
	}

	rw.WriteHeader(500)
}
<commit_msg>More WriteHeader fixes<commit_after>package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/jingweno/jqplay/jq"
	"gopkg.in/unrolled/render.v1"
)

const (
	JSONPayloadLimit   = JSONPayloadLimitMB * OneMB
	JSONPayloadLimitMB = 5
	OneMB              = 1024000
)

type JQHandlerContext struct {
	*Config
	JQ string
}

func (c *JQHandlerContext) Asset(path string) string {
	return fmt.Sprintf("%s/%s", c.Config.AssetHost, path)
}

func (c *JQHandlerContext) ShouldInitJQ() bool {
	return c.JQ != ""
}

type JQHandler struct {
	r *render.Render
	c *Config
}

func (h *JQHandler) handleIndex(rw http.ResponseWriter, r *http.Request) {
	h.r.HTML(rw, 200, "index", &JQHandlerContext{Config: h.c})
}

func (h *JQHandler) handleJqPost(rw http.ResponseWriter, r *http.Request) {
	if r.ContentLength == -1 {
		log.Printf("Error: Content length is unknown")
	}

	if r.ContentLength > JSONPayloadLimit {
		msg := fmt.Sprintf("JSON payload size is %.1fMB, larger than limit %dMB.", float64(r.ContentLength)/OneMB, JSONPayloadLimitMB)
		log.Printf("Error: %s", msg)
		rw.WriteHeader(403)
		fmt.Fprint(rw, msg)
		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		rw.WriteHeader(422)
		fmt.Fprint(rw, err.Error())
		return
	}
	defer r.Body.Close()

	var jq *jq.JQ
	err = json.Unmarshal(b, &jq)
	if err != nil {
		rw.WriteHeader(422)
		fmt.Fprint(rw, err.Error())
		return
	}

	// Evaling into ResponseWriter sets the status code to 200
	// appending error message in the end if there's any
	err = jq.Eval(rw)
	if err != nil {
		fmt.Fprint(rw, err.Error())
	}
}

func (h *JQHandler) handleJqGet(rw http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	jq := &jq.JQ{
		J: q.Get("j"),
		Q: q.Get("q"),
	}

	var jqData string
	if err := jq.Validate(); err == nil {
		d, err := json.Marshal(jq)
		if err == nil {
			jqData = string(d)
		}
	}

	h.r.HTML(rw, 200, "index", &JQHandlerContext{Config: h.c, JQ: jqData})
}

func (h *JQHandler) handleJq(rw http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		h.handleJqPost(rw, r)
		return
	}

	if r.Method == "GET" {
		h.handleJqGet(rw, r)
		return
	}

	rw.WriteHeader(500)
}
<|endoftext|>


<commit_before>// Copyright 2017 fatedier, fatedier@gmail.com
//
// 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 server

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/fatedier/frp/assets"
	"github.com/fatedier/frp/g"
	"github.com/fatedier/frp/models/msg"
	"github.com/fatedier/frp/utils/log"
	frpNet "github.com/fatedier/frp/utils/net"
	"github.com/fatedier/frp/utils/util"
	"github.com/fatedier/frp/utils/version"
	"github.com/fatedier/frp/utils/vhost"

	"github.com/fatedier/golib/net/mux"
	fmux "github.com/hashicorp/yamux"
)

const (
	connReadTimeout time.Duration = 10 * time.Second
)

var ServerService *Service

// Server service.
type Service struct {
	// Dispatch connections to different handlers listen on same port.
	muxer *mux.Mux

	// Accept connections from client.
	listener frpNet.Listener

	// Accept connections using kcp.
	kcpListener frpNet.Listener

	// For https proxies, route requests to different clients by hostname and other infomation.
	VhostHttpsMuxer *vhost.HttpsMuxer

	httpReverseProxy *vhost.HttpReverseProxy

	// Manage all controllers.
	ctlManager *ControlManager

	// Manage all proxies.
	pxyManager *ProxyManager

	// Manage all visitor listeners.
	visitorManager *VisitorManager

	// Manage all tcp ports.
	tcpPortManager *PortManager

	// Manage all udp ports.
	udpPortManager *PortManager

	// Controller for nat hole connections.
	natHoleController *NatHoleController
}

func NewService() (svr *Service, err error) {
	cfg := &g.GlbServerCfg.ServerCommonConf
	svr = &Service{
		ctlManager:     NewControlManager(),
		pxyManager:     NewProxyManager(),
		visitorManager: NewVisitorManager(),
		tcpPortManager: NewPortManager("tcp", cfg.ProxyBindAddr, cfg.AllowPorts),
		udpPortManager: NewPortManager("udp", cfg.ProxyBindAddr, cfg.AllowPorts),
	}

	// Init assets.
	err = assets.Load(cfg.AssetsDir)
	if err != nil {
		err = fmt.Errorf("Load assets error: %v", err)
		return
	}

	var (
		httpMuxOn  bool
		httpsMuxOn bool
	)
	if cfg.BindAddr == cfg.ProxyBindAddr {
		if cfg.BindPort == cfg.VhostHttpPort {
			httpMuxOn = true
		}
		if cfg.BindPort == cfg.VhostHttpsPort {
			httpsMuxOn = true
		}
		if httpMuxOn || httpsMuxOn {
			svr.muxer = mux.NewMux()
		}
	}

	// Listen for accepting connections from client.
	ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.BindPort))
	if err != nil {
		err = fmt.Errorf("Create server listener error, %v", err)
		return
	}
	if svr.muxer != nil {
		go svr.muxer.Serve(ln)
		ln = svr.muxer.DefaultListener()
	}
	svr.listener = frpNet.WrapLogListener(ln)
	log.Info("frps tcp listen on %s:%d", cfg.BindAddr, cfg.BindPort)

	// Listen for accepting connections from client using kcp protocol.
	if cfg.KcpBindPort > 0 {
		svr.kcpListener, err = frpNet.ListenKcp(cfg.BindAddr, cfg.KcpBindPort)
		if err != nil {
			err = fmt.Errorf("Listen on kcp address udp [%s:%d] error: %v", cfg.BindAddr, cfg.KcpBindPort, err)
			return
		}
		log.Info("frps kcp listen on udp %s:%d", cfg.BindAddr, cfg.KcpBindPort)
	}

	// Create http vhost muxer.
	if cfg.VhostHttpPort > 0 {
		rp := vhost.NewHttpReverseProxy()
		svr.httpReverseProxy = rp

		address := fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
		server := &http.Server{
			Addr:    address,
			Handler: rp,
		}
		var l net.Listener
		if httpMuxOn {
			l = svr.muxer.ListenHttp(0)
		} else {
			l, err = net.Listen("tcp", address)
			if err != nil {
				err = fmt.Errorf("Create vhost http listener error, %v", err)
				return
			}
		}
		go server.Serve(l)
		log.Info("http service listen on %s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
	}

	// Create https vhost muxer.
	if cfg.VhostHttpsPort > 0 {
		var l net.Listener
		if httpsMuxOn {
			l = svr.muxer.ListenHttps(0)
		} else {
			l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpsPort))
			if err != nil {
				err = fmt.Errorf("Create server listener error, %v", err)
				return
			}
		}

		svr.VhostHttpsMuxer, err = vhost.NewHttpsMuxer(frpNet.WrapLogListener(l), 30*time.Second)
		if err != nil {
			err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
			return
		}
		log.Info("https service listen on %s:%d", cfg.ProxyBindAddr, cfg.VhostHttpsPort)
	}

	// Create nat hole controller.
	if cfg.BindUdpPort > 0 {
		var nc *NatHoleController
		addr := fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.BindUdpPort)
		nc, err = NewNatHoleController(addr)
		if err != nil {
			err = fmt.Errorf("Create nat hole controller error, %v", err)
			return
		}
		svr.natHoleController = nc
		log.Info("nat hole udp service listen on %s:%d", cfg.BindAddr, cfg.BindUdpPort)
	}

	// Create dashboard web server.
	if cfg.DashboardPort > 0 {
		err = RunDashboardServer(cfg.DashboardAddr, cfg.DashboardPort)
		if err != nil {
			err = fmt.Errorf("Create dashboard web server error, %v", err)
			return
		}
		log.Info("Dashboard listen on %s:%d", cfg.DashboardAddr, cfg.DashboardPort)
	}
	return
}

func (svr *Service) Run() {
	if svr.natHoleController != nil {
		go svr.natHoleController.Run()
	}
	if g.GlbServerCfg.KcpBindPort > 0 {
		go svr.HandleListener(svr.kcpListener)
	}
	svr.HandleListener(svr.listener)

}

func (svr *Service) HandleListener(l frpNet.Listener) {
	// Listen for incoming connections from client.
	for {
		c, err := l.Accept()
		if err != nil {
			log.Warn("Listener for incoming connections from client closed")
			return
		}

		// Start a new goroutine for dealing connections.
		go func(frpConn frpNet.Conn) {
			dealFn := func(conn frpNet.Conn) {
				var rawMsg msg.Message
				conn.SetReadDeadline(time.Now().Add(connReadTimeout))
				if rawMsg, err = msg.ReadMsg(conn); err != nil {
					log.Trace("Failed to read message: %v", err)
					conn.Close()
					return
				}
				conn.SetReadDeadline(time.Time{})

				switch m := rawMsg.(type) {
				case *msg.Login:
					err = svr.RegisterControl(conn, m)
					// If login failed, send error message there.
					// Otherwise send success message in control's work goroutine.
					if err != nil {
						conn.Warn("%v", err)
						msg.WriteMsg(conn, &msg.LoginResp{
							Version: version.Full(),
							Error:   err.Error(),
						})
						conn.Close()
					}
				case *msg.NewWorkConn:
					svr.RegisterWorkConn(conn, m)
				case *msg.NewVisitorConn:
					if err = svr.RegisterVisitorConn(conn, m); err != nil {
						conn.Warn("%v", err)
						msg.WriteMsg(conn, &msg.NewVisitorConnResp{
							ProxyName: m.ProxyName,
							Error:     err.Error(),
						})
						conn.Close()
					} else {
						msg.WriteMsg(conn, &msg.NewVisitorConnResp{
							ProxyName: m.ProxyName,
							Error:     "",
						})
					}
				default:
					log.Warn("Error message type for the new connection [%s]", conn.RemoteAddr().String())
					conn.Close()
				}
			}

			if g.GlbServerCfg.TcpMux {
				fmuxCfg := fmux.DefaultConfig()
				fmuxCfg.LogOutput = ioutil.Discard
				session, err := fmux.Server(frpConn, fmuxCfg)
				if err != nil {
					log.Warn("Failed to create mux connection: %v", err)
					frpConn.Close()
					return
				}

				for {
					stream, err := session.AcceptStream()
					if err != nil {
						log.Warn("Accept new mux stream error: %v", err)
						session.Close()
						return
					}
					wrapConn := frpNet.WrapConn(stream)
					go dealFn(wrapConn)
				}
			} else {
				dealFn(frpConn)
			}
		}(c)
	}
}

func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (err error) {
	ctlConn.Info("client login info: ip [%s] version [%s] hostname [%s] os [%s] arch [%s]",
		ctlConn.RemoteAddr().String(), loginMsg.Version, loginMsg.Hostname, loginMsg.Os, loginMsg.Arch)

	// Check client version.
	if ok, msg := version.Compat(loginMsg.Version); !ok {
		err = fmt.Errorf("%s", msg)
		return
	}

	// Check auth.
	nowTime := time.Now().Unix()
	if g.GlbServerCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > g.GlbServerCfg.AuthTimeout {
		err = fmt.Errorf("authorization timeout")
		return
	}
	if util.GetAuthKey(g.GlbServerCfg.Token, loginMsg.Timestamp) != loginMsg.PrivilegeKey {
		err = fmt.Errorf("authorization failed")
		return
	}

	// If client's RunId is empty, it's a new client, we just create a new controller.
	// Otherwise, we check if there is one controller has the same run id. If so, we release previous controller and start new one.
	if loginMsg.RunId == "" {
		loginMsg.RunId, err = util.RandId()
		if err != nil {
			return
		}
	}

	ctl := NewControl(svr, ctlConn, loginMsg)

	if oldCtl := svr.ctlManager.Add(loginMsg.RunId, ctl); oldCtl != nil {
		oldCtl.allShutdown.WaitDone()
	}

	ctlConn.AddLogPrefix(loginMsg.RunId)
	ctl.Start()

	// for statistics
	StatsNewClient()
	return
}

// RegisterWorkConn register a new work connection to control and proxies need it.
func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkConn) {
	ctl, exist := svr.ctlManager.GetById(newMsg.RunId)
	if !exist {
		workConn.Warn("No client control found for run id [%s]", newMsg.RunId)
		return
	}
	ctl.RegisterWorkConn(workConn)
	return
}

func (svr *Service) RegisterVisitorConn(visitorConn frpNet.Conn, newMsg *msg.NewVisitorConn) error {
	return svr.visitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
		newMsg.UseEncryption, newMsg.UseCompression)
}

func (svr *Service) RegisterProxy(name string, pxy Proxy) error {
	return svr.pxyManager.Add(name, pxy)
}

func (svr *Service) DelProxy(name string) {
	svr.pxyManager.Del(name)
}
<commit_msg>change accept connection error loglevel to debug<commit_after>// Copyright 2017 fatedier, fatedier@gmail.com
//
// 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 server

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/fatedier/frp/assets"
	"github.com/fatedier/frp/g"
	"github.com/fatedier/frp/models/msg"
	"github.com/fatedier/frp/utils/log"
	frpNet "github.com/fatedier/frp/utils/net"
	"github.com/fatedier/frp/utils/util"
	"github.com/fatedier/frp/utils/version"
	"github.com/fatedier/frp/utils/vhost"

	"github.com/fatedier/golib/net/mux"
	fmux "github.com/hashicorp/yamux"
)

const (
	connReadTimeout time.Duration = 10 * time.Second
)

var ServerService *Service

// Server service.
type Service struct {
	// Dispatch connections to different handlers listen on same port.
	muxer *mux.Mux

	// Accept connections from client.
	listener frpNet.Listener

	// Accept connections using kcp.
	kcpListener frpNet.Listener

	// For https proxies, route requests to different clients by hostname and other infomation.
	VhostHttpsMuxer *vhost.HttpsMuxer

	httpReverseProxy *vhost.HttpReverseProxy

	// Manage all controllers.
	ctlManager *ControlManager

	// Manage all proxies.
	pxyManager *ProxyManager

	// Manage all visitor listeners.
	visitorManager *VisitorManager

	// Manage all tcp ports.
	tcpPortManager *PortManager

	// Manage all udp ports.
	udpPortManager *PortManager

	// Controller for nat hole connections.
	natHoleController *NatHoleController
}

func NewService() (svr *Service, err error) {
	cfg := &g.GlbServerCfg.ServerCommonConf
	svr = &Service{
		ctlManager:     NewControlManager(),
		pxyManager:     NewProxyManager(),
		visitorManager: NewVisitorManager(),
		tcpPortManager: NewPortManager("tcp", cfg.ProxyBindAddr, cfg.AllowPorts),
		udpPortManager: NewPortManager("udp", cfg.ProxyBindAddr, cfg.AllowPorts),
	}

	// Init assets.
	err = assets.Load(cfg.AssetsDir)
	if err != nil {
		err = fmt.Errorf("Load assets error: %v", err)
		return
	}

	var (
		httpMuxOn  bool
		httpsMuxOn bool
	)
	if cfg.BindAddr == cfg.ProxyBindAddr {
		if cfg.BindPort == cfg.VhostHttpPort {
			httpMuxOn = true
		}
		if cfg.BindPort == cfg.VhostHttpsPort {
			httpsMuxOn = true
		}
		if httpMuxOn || httpsMuxOn {
			svr.muxer = mux.NewMux()
		}
	}

	// Listen for accepting connections from client.
	ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.BindPort))
	if err != nil {
		err = fmt.Errorf("Create server listener error, %v", err)
		return
	}
	if svr.muxer != nil {
		go svr.muxer.Serve(ln)
		ln = svr.muxer.DefaultListener()
	}
	svr.listener = frpNet.WrapLogListener(ln)
	log.Info("frps tcp listen on %s:%d", cfg.BindAddr, cfg.BindPort)

	// Listen for accepting connections from client using kcp protocol.
	if cfg.KcpBindPort > 0 {
		svr.kcpListener, err = frpNet.ListenKcp(cfg.BindAddr, cfg.KcpBindPort)
		if err != nil {
			err = fmt.Errorf("Listen on kcp address udp [%s:%d] error: %v", cfg.BindAddr, cfg.KcpBindPort, err)
			return
		}
		log.Info("frps kcp listen on udp %s:%d", cfg.BindAddr, cfg.KcpBindPort)
	}

	// Create http vhost muxer.
	if cfg.VhostHttpPort > 0 {
		rp := vhost.NewHttpReverseProxy()
		svr.httpReverseProxy = rp

		address := fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
		server := &http.Server{
			Addr:    address,
			Handler: rp,
		}
		var l net.Listener
		if httpMuxOn {
			l = svr.muxer.ListenHttp(0)
		} else {
			l, err = net.Listen("tcp", address)
			if err != nil {
				err = fmt.Errorf("Create vhost http listener error, %v", err)
				return
			}
		}
		go server.Serve(l)
		log.Info("http service listen on %s:%d", cfg.ProxyBindAddr, cfg.VhostHttpPort)
	}

	// Create https vhost muxer.
	if cfg.VhostHttpsPort > 0 {
		var l net.Listener
		if httpsMuxOn {
			l = svr.muxer.ListenHttps(0)
		} else {
			l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.ProxyBindAddr, cfg.VhostHttpsPort))
			if err != nil {
				err = fmt.Errorf("Create server listener error, %v", err)
				return
			}
		}

		svr.VhostHttpsMuxer, err = vhost.NewHttpsMuxer(frpNet.WrapLogListener(l), 30*time.Second)
		if err != nil {
			err = fmt.Errorf("Create vhost httpsMuxer error, %v", err)
			return
		}
		log.Info("https service listen on %s:%d", cfg.ProxyBindAddr, cfg.VhostHttpsPort)
	}

	// Create nat hole controller.
	if cfg.BindUdpPort > 0 {
		var nc *NatHoleController
		addr := fmt.Sprintf("%s:%d", cfg.BindAddr, cfg.BindUdpPort)
		nc, err = NewNatHoleController(addr)
		if err != nil {
			err = fmt.Errorf("Create nat hole controller error, %v", err)
			return
		}
		svr.natHoleController = nc
		log.Info("nat hole udp service listen on %s:%d", cfg.BindAddr, cfg.BindUdpPort)
	}

	// Create dashboard web server.
	if cfg.DashboardPort > 0 {
		err = RunDashboardServer(cfg.DashboardAddr, cfg.DashboardPort)
		if err != nil {
			err = fmt.Errorf("Create dashboard web server error, %v", err)
			return
		}
		log.Info("Dashboard listen on %s:%d", cfg.DashboardAddr, cfg.DashboardPort)
	}
	return
}

func (svr *Service) Run() {
	if svr.natHoleController != nil {
		go svr.natHoleController.Run()
	}
	if g.GlbServerCfg.KcpBindPort > 0 {
		go svr.HandleListener(svr.kcpListener)
	}
	svr.HandleListener(svr.listener)

}

func (svr *Service) HandleListener(l frpNet.Listener) {
	// Listen for incoming connections from client.
	for {
		c, err := l.Accept()
		if err != nil {
			log.Warn("Listener for incoming connections from client closed")
			return
		}

		// Start a new goroutine for dealing connections.
		go func(frpConn frpNet.Conn) {
			dealFn := func(conn frpNet.Conn) {
				var rawMsg msg.Message
				conn.SetReadDeadline(time.Now().Add(connReadTimeout))
				if rawMsg, err = msg.ReadMsg(conn); err != nil {
					log.Trace("Failed to read message: %v", err)
					conn.Close()
					return
				}
				conn.SetReadDeadline(time.Time{})

				switch m := rawMsg.(type) {
				case *msg.Login:
					err = svr.RegisterControl(conn, m)
					// If login failed, send error message there.
					// Otherwise send success message in control's work goroutine.
					if err != nil {
						conn.Warn("%v", err)
						msg.WriteMsg(conn, &msg.LoginResp{
							Version: version.Full(),
							Error:   err.Error(),
						})
						conn.Close()
					}
				case *msg.NewWorkConn:
					svr.RegisterWorkConn(conn, m)
				case *msg.NewVisitorConn:
					if err = svr.RegisterVisitorConn(conn, m); err != nil {
						conn.Warn("%v", err)
						msg.WriteMsg(conn, &msg.NewVisitorConnResp{
							ProxyName: m.ProxyName,
							Error:     err.Error(),
						})
						conn.Close()
					} else {
						msg.WriteMsg(conn, &msg.NewVisitorConnResp{
							ProxyName: m.ProxyName,
							Error:     "",
						})
					}
				default:
					log.Warn("Error message type for the new connection [%s]", conn.RemoteAddr().String())
					conn.Close()
				}
			}

			if g.GlbServerCfg.TcpMux {
				fmuxCfg := fmux.DefaultConfig()
				fmuxCfg.LogOutput = ioutil.Discard
				session, err := fmux.Server(frpConn, fmuxCfg)
				if err != nil {
					log.Warn("Failed to create mux connection: %v", err)
					frpConn.Close()
					return
				}

				for {
					stream, err := session.AcceptStream()
					if err != nil {
						log.Debug("Accept new mux stream error: %v", err)
						session.Close()
						return
					}
					wrapConn := frpNet.WrapConn(stream)
					go dealFn(wrapConn)
				}
			} else {
				dealFn(frpConn)
			}
		}(c)
	}
}

func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (err error) {
	ctlConn.Info("client login info: ip [%s] version [%s] hostname [%s] os [%s] arch [%s]",
		ctlConn.RemoteAddr().String(), loginMsg.Version, loginMsg.Hostname, loginMsg.Os, loginMsg.Arch)

	// Check client version.
	if ok, msg := version.Compat(loginMsg.Version); !ok {
		err = fmt.Errorf("%s", msg)
		return
	}

	// Check auth.
	nowTime := time.Now().Unix()
	if g.GlbServerCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > g.GlbServerCfg.AuthTimeout {
		err = fmt.Errorf("authorization timeout")
		return
	}
	if util.GetAuthKey(g.GlbServerCfg.Token, loginMsg.Timestamp) != loginMsg.PrivilegeKey {
		err = fmt.Errorf("authorization failed")
		return
	}

	// If client's RunId is empty, it's a new client, we just create a new controller.
	// Otherwise, we check if there is one controller has the same run id. If so, we release previous controller and start new one.
	if loginMsg.RunId == "" {
		loginMsg.RunId, err = util.RandId()
		if err != nil {
			return
		}
	}

	ctl := NewControl(svr, ctlConn, loginMsg)

	if oldCtl := svr.ctlManager.Add(loginMsg.RunId, ctl); oldCtl != nil {
		oldCtl.allShutdown.WaitDone()
	}

	ctlConn.AddLogPrefix(loginMsg.RunId)
	ctl.Start()

	// for statistics
	StatsNewClient()
	return
}

// RegisterWorkConn register a new work connection to control and proxies need it.
func (svr *Service) RegisterWorkConn(workConn frpNet.Conn, newMsg *msg.NewWorkConn) {
	ctl, exist := svr.ctlManager.GetById(newMsg.RunId)
	if !exist {
		workConn.Warn("No client control found for run id [%s]", newMsg.RunId)
		return
	}
	ctl.RegisterWorkConn(workConn)
	return
}

func (svr *Service) RegisterVisitorConn(visitorConn frpNet.Conn, newMsg *msg.NewVisitorConn) error {
	return svr.visitorManager.NewConn(newMsg.ProxyName, visitorConn, newMsg.Timestamp, newMsg.SignKey,
		newMsg.UseEncryption, newMsg.UseCompression)
}

func (svr *Service) RegisterProxy(name string, pxy Proxy) error {
	return svr.pxyManager.Add(name, pxy)
}

func (svr *Service) DelProxy(name string) {
	svr.pxyManager.Del(name)
}
<|endoftext|>


<commit_before>package server

import (
	"time"
)

const (
	// The amount of time to elapse without a heartbeat before becoming a candidate
	defaultElectionTimeout = 200 * time.Millisecond

	// The frequency by which heartbeats are sent to followers.
	defaultHeartbeatTimeout = 50 * time.Millisecond
)
<commit_msg>chore(server): cleanup some whitespace<commit_after>package server

import (
	"time"
)

const (
	// The amount of time to elapse without a heartbeat before becoming a candidate
	defaultElectionTimeout = 200 * time.Millisecond

	// The frequency by which heartbeats are sent to followers.
	defaultHeartbeatTimeout = 50 * time.Millisecond
)
<|endoftext|>


<commit_before>package gonfs

type Configuration map[string]string

type ConfigurationServer interface {
    GetConfiguration() Configuration
    GetSetting(path string) string
    SetSetting(path string, value string)
}

type ConfigurationTree struct {
    Prefix string
    SubtreeHandlers map[string]ConfigurationServer
}
<commit_msg>added implementation of ConfigurationServer for structure ConfigurationTree; added error support and error-handling types for method signatures inside ConfigurationServer<commit_after>package gonfs

import (
    "fmt"
    "strings"
)

type Configuration map[string]string

type ConfigurationServer interface {
    GetConfiguration() Configuration
    GetSetting(path string) (string, error)
    SetSetting(path string, value string) error
}

type ConfigurationTree struct {
    Prefix string
    SubtreeHandlers map[string]ConfigurationServer
}

type InvalidPathError struct {
    Path string
}

type TreeAssignmentError struct {
    Path string
}

type NodeDoesNotExistError struct {
    Path string
}

func (ipe *InvalidPathError) Error() string {
    return fmt.Sprintf("the configuration tree path %s does not refer to an existing tree or setting", ipe.Path)
}

func (tae *TreeAssignmentError) Error() string {
    return fmt.Sprintf("the configuration tree path %s refers to a tree and so it cannot be assigned a value", tae.Path)
}

func (ndnee *NodeDoesNotExistError) Error() string {
    return fmt.Sprintf("the configuration tree path %s does not refer to a valid tree or setting", ndnee.Path)
}

func (ct *ConfigurationTree) GetConfiguration() Configuration {
    mergedConfiguraton := new(Configuration)

    for prefix, handler := range ct.SubtreeHandlers {
        for path, value := range handler.GetConfiguration() {
            mergedConfiguraton[fmt.Sprintf("%s/%s", prefix, path)] = value
        }
    }

    return mergedConfiguraton
}

func (ct *ConfigurationTree) GetSetting(path string) (string, error) {
    for prefix, handler := range ct.SubtreeHandlers {
        if !strings.HasPrefix(path, prefix) {
            continue
        }

        value, err := handler.GetSetting(strings.TrimPrefix(path, prefix))

        if err == nil {
            return value, err
        }
    }

    return nil, &NodeDoesNotExistError{path}
}

func (ct *ConfigurationTree) SetSetting(path string, value string) error {
    for prefix, handler := range ct.SubtreeHandlers {
        if !strings.HasPrefix(path, prefix) {
            continue
        }

        err := handler.SetSetting(strings.TrimPrefix(path, prefix), value)

        if err == nil {
            return err
        }
    }

    return &NodeDoesNotExistError{path}
}
<|endoftext|>


<commit_before>package gosnmpquerier

import (
	"testing"
	"time"

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

type FakeSnmpClient struct{}

func (snmpClient *FakeSnmpClient) get(destination, community string, oids []string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 1, Value: 1}}, nil
}

func (snmpClient *FakeSnmpClient) walk(destination, community, oid string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 1, Value: 1}}, nil
}

func (snmpClient *FakeSnmpClient) getnext(destination, community string, oids []string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 1, Value: 1}}, nil

}

func syncQuerier() *SyncQuerier {
	querier := NewSyncQuerier(1)
	querier.asyncQuerier.snmpClient = &FakeSnmpClient{}
	return querier
}

func TestGetReturnsSnmpGetResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.Get("192.168.5.15", "alea2", []string{"1.3.6.1.2.1.1.1.0"}, 1*time.Second, 1)
	assert.Equal(t, result, []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 0x1, Value: 1}})
}

func TestGetNextReturnsSnmpGetNextResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.GetNext("192.168.5.15", "alea2", []string{"1.3.6.1.2.1.1.1.0"}, 1*time.Second, 1)
	assert.Equal(t, result, []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 0x1, Value: 1}})
}

func TestWalkReturnsSnmpWalkResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.Walk("192.168.5.15", "alea2", "1.3.6.1.2.1.1", 1*time.Second, 1)
	assert.Equal(t, result, []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 0x1, Value: 1}})
}
<commit_msg>Refactor tests<commit_after>package gosnmpquerier

import (
	"testing"
	"time"

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

type FakeSnmpClient struct{}

func (snmpClient *FakeSnmpClient) get(destination, community string, oids []string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return makeSnmpPDu()
}

func (snmpClient *FakeSnmpClient) walk(destination, community, oid string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return makeSnmpPDu()
}

func (snmpClient *FakeSnmpClient) getnext(destination, community string, oids []string, timeout time.Duration, retries int) ([]gosnmp.SnmpPDU, error) {
	return makeSnmpPDu()
}

func makeSnmpPDu() ([]gosnmp.SnmpPDU, error) {
	return []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 1, Value: 1}}, nil
}

func syncQuerier() *SyncQuerier {
	querier := NewSyncQuerier(1)
	querier.asyncQuerier.snmpClient = &FakeSnmpClient{}
	return querier
}

func expectedSnmpResult() []gosnmp.SnmpPDU {
	return []gosnmp.SnmpPDU{gosnmp.SnmpPDU{Name: "foo", Type: 0x1, Value: 1}}
}
func TestGetReturnsSnmpGetResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.Get("192.168.5.15", "alea2", []string{"1.3.6.1.2.1.1.1.0"}, 1*time.Second, 1)
	assert.Equal(t, result, expectedSnmpResult())
}

func TestGetNextReturnsSnmpGetNextResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.GetNext("192.168.5.15", "alea2", []string{"1.3.6.1.2.1.1.1.0"}, 1*time.Second, 1)
	assert.Equal(t, result, expectedSnmpResult())
}

func TestWalkReturnsSnmpWalkResult(t *testing.T) {
	querier := syncQuerier()
	result, _ := querier.Walk("192.168.5.15", "alea2", "1.3.6.1.2.1.1", 1*time.Second, 1)
	assert.Equal(t, result, expectedSnmpResult())
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 The SurgeMQ Authors. 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 service

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"sync"
	"sync/atomic"
	"time"
)

var (
	bufcnt            int64
	DefaultBufferSize int64

	DeviceInBufferSize  int64
	DeviceOutBufferSize int64

	MasterInBufferSize  int64
	MasterOutBufferSize int64
)

type sequence struct {
	// The current position of the producer or consumer
	cursor,

	// The previous known position of the consumer (if producer) or producer (if consumer)
	gate,

	// These are fillers to pad the cache line, which is generally 64 bytes
	p2, p3, p4, p5, p6, p7 int64
}

func newSequence() *sequence {
	return &sequence{}
}

func (this *sequence) get() int64 {
	return atomic.LoadInt64(&this.cursor)
}

func (this *sequence) set(seq int64) {
	atomic.StoreInt64(&this.cursor, seq)
}

type buffer struct {
	id int64

	readIndex  int64 //读序号
	writeIndex int64 //写序号
	buf        []*[]byte

	size int64
	mask int64

	done int64

	pcond *sync.Cond
	ccond *sync.Cond

	b []byte //readfrom中的临时数组，为反复使用不必创建新数组
}

func newBuffer(size int64) (*buffer, error) {
	if size < 0 {
		return nil, bufio.ErrNegativeCount
	}

	if size == 0 {
		size = DefaultBufferSize
	}

	if !powerOfTwo64(size) {
		fmt.Printf("Size must be power of two. Try %d.", roundUpPowerOfTwo64(size))
		return nil, fmt.Errorf("Size must be power of two. Try %d.", roundUpPowerOfTwo64(size))
	}

	return &buffer{
		id:         atomic.AddInt64(&bufcnt, 1),
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		size:       size,
		mask:       size - 1,
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
		b:          make([]byte, 5),
	}, nil
}

/**
获取当前读序号
*/
func (this *buffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *buffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

func (this *buffer) ID() int64 {
	return this.id
}

func (this *buffer) Close() error {
	atomic.StoreInt64(&this.done, 1)

	this.pcond.L.Lock()
	this.ccond.Signal()
	//this.ccond.Broadcast()
	this.pcond.L.Unlock()

	this.ccond.L.Lock()
	this.pcond.Signal()
	//this.pcond.Broadcast()
	this.ccond.L.Unlock()

	return nil
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *buffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Signal()
		//this.pcond.Broadcast()
		this.ccond.L.Unlock()
		time.Sleep(3 * time.Millisecond)
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return nil, false
		}
		writeIndex = this.GetCurrentWriteIndex()
		if readIndex >= writeIndex {
			this.pcond.Signal()
			//this.pcond.Broadcast()
			this.ccond.Wait()
		} else {
			break
		}
		//time.Sleep(500 * time.Microsecond)
		//time.Sleep(1 * time.Millisecond)
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *buffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Signal()
		//this.ccond.Broadcast()
		this.pcond.L.Unlock()
		time.Sleep(3 * time.Millisecond)
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return false
		}
		readIndex = this.GetCurrentReadIndex()
		if writeIndex >= readIndex && writeIndex-readIndex >= this.size {
			this.ccond.Signal()
			//this.ccond.Broadcast()
			this.pcond.Wait()
			//time.Sleep(1 * time.Millisecond)
		} else {
			break
		}
		//time.Sleep(500 * time.Microsecond)
		//time.Sleep(1 * time.Millisecond)
	}
	index := writeIndex & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}

/**
修改 尽量减少数据的创建
*/
func (this *buffer) ReadFrom(r io.Reader) (int64, error) {
	defer this.Close()

	total := int64(0)

	for {
		time.Sleep(2 * time.Millisecond)
		if this.isDone() {
			return total, io.EOF
		}

		var write_bytes []byte

		//b := make([]byte, 5)
		n, err := r.Read(this.b[0:1])
		if err != nil {
			return total, io.EOF
		}
		total += int64(n)
		max_cnt := 1
		for {
			if this.isDone() {
				return total, io.EOF
			}
			// If we have read 5 bytes and still not done, then there's a problem.
			if max_cnt > 4 {
				return 0, fmt.Errorf("sendrecv/peekMessageSize: 4th byte of remaining length has continuation bit set")
			}
			_, err := r.Read(this.b[max_cnt:(max_cnt + 1)])

			//fmt.Println(b)
			if err != nil {
				return total, err
			}
			if this.b[max_cnt] >= 0x80 {
				max_cnt++
			} else {
				break
			}
		}
		remlen, m := binary.Uvarint(this.b[1 : max_cnt+1])
		remlen_tmp := int64(remlen)
		start_ := int64(1) + int64(m)
		total_tmp := remlen_tmp + start_

		write_bytes = make([]byte, total_tmp)
		copy(write_bytes[0:m+1], this.b[0:m+1])
		nlen := int64(0)
		times := 0
		cnt_ := int64(32)
		for nlen < remlen_tmp {
			if this.isDone() {
				return total, io.EOF
			}
			if times > 100 {
				return total, io.EOF
			} else {
				times = 0
			}
			times++
			tmpm := remlen_tmp - nlen

			b_ := write_bytes[(start_ + nlen):]
			if tmpm > cnt_ {
				b_ = write_bytes[(start_ + nlen):(start_ + nlen + cnt_)]
			}

			//b_ := make([]byte, remlen)
			n, err = r.Read(b_[0:])

			if err != nil {
				/*Log.Errorc(func() string {
					return fmt.Sprintf("从conn读取数据失败(%s)(0)", err)
				})
				time.Sleep(5 * time.Millisecond)
				continue*/
				return total, err
			}
			//write_bytes = append(write_bytes, b_[0:]...)
			nlen += int64(n)
			total += int64(n)
		}

		ok := this.WriteBuffer(&write_bytes)

		if !ok {
			return total, errors.New("write ringbuffer failed")
		}
	}
}

func (this *buffer) WriteTo(w io.Writer) (int64, error) {
	defer this.Close()

	total := int64(0)

	for {
		if this.isDone() {
			return total, io.EOF
		}

		p, ok := this.ReadBuffer()
		if !ok {
			return total, errors.New("read buffer failed")
		}
		// There's some data, let's process it first
		if len(*p) > 0 {
			n, err := w.Write(*p)
			total += int64(n)
			//Log.Debugc(func() string{ return fmt.Sprintf("Wrote %d bytes, totaling %d bytes", n, total)})

			if err != nil {
				return total, err
			}
		}

	}
}

func (this *buffer) isDone() bool {
	if atomic.LoadInt64(&this.done) == 1 {
		return true
	}

	return false
}

func ringCopy(dst, src []byte, start int64) int {
	n := len(src)

	i, l := 0, 0

	for n > 0 {
		l = copy(dst[start:], src[i:])
		i += l
		n -= l

		if n > 0 {
			start = 0
		}
	}

	return i
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

func roundUpPowerOfTwo64(n int64) int64 {
	n--
	n |= n >> 1
	n |= n >> 2
	n |= n >> 4
	n |= n >> 8
	n |= n >> 16
	n |= n >> 32
	n++

	return n
}
<commit_msg>修改 buffer.go process.go sendrecv.go xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 修改readfrom休眠时间（10毫秒）;取消读写休眠<commit_after>// Copyright (c) 2014 The SurgeMQ Authors. 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 service

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"sync"
	"sync/atomic"
	"time"
)

var (
	bufcnt            int64
	DefaultBufferSize int64

	DeviceInBufferSize  int64
	DeviceOutBufferSize int64

	MasterInBufferSize  int64
	MasterOutBufferSize int64
)

type sequence struct {
	// The current position of the producer or consumer
	cursor,

	// The previous known position of the consumer (if producer) or producer (if consumer)
	gate,

	// These are fillers to pad the cache line, which is generally 64 bytes
	p2, p3, p4, p5, p6, p7 int64
}

func newSequence() *sequence {
	return &sequence{}
}

func (this *sequence) get() int64 {
	return atomic.LoadInt64(&this.cursor)
}

func (this *sequence) set(seq int64) {
	atomic.StoreInt64(&this.cursor, seq)
}

type buffer struct {
	id int64

	readIndex  int64 //读序号
	writeIndex int64 //写序号
	buf        []*[]byte

	size int64
	mask int64

	done int64

	pcond *sync.Cond
	ccond *sync.Cond

	b []byte //readfrom中的临时数组，为反复使用不必创建新数组
}

func newBuffer(size int64) (*buffer, error) {
	if size < 0 {
		return nil, bufio.ErrNegativeCount
	}

	if size == 0 {
		size = DefaultBufferSize
	}

	if !powerOfTwo64(size) {
		fmt.Printf("Size must be power of two. Try %d.", roundUpPowerOfTwo64(size))
		return nil, fmt.Errorf("Size must be power of two. Try %d.", roundUpPowerOfTwo64(size))
	}

	return &buffer{
		id:         atomic.AddInt64(&bufcnt, 1),
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		size:       size,
		mask:       size - 1,
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
		b:          make([]byte, 5),
	}, nil
}

/**
获取当前读序号
*/
func (this *buffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *buffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

func (this *buffer) ID() int64 {
	return this.id
}

func (this *buffer) Close() error {
	atomic.StoreInt64(&this.done, 1)

	this.pcond.L.Lock()
	this.ccond.Signal()
	//this.ccond.Broadcast()
	this.pcond.L.Unlock()

	this.ccond.L.Lock()
	this.pcond.Signal()
	//this.pcond.Broadcast()
	this.ccond.L.Unlock()

	return nil
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *buffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Signal()
		//this.pcond.Broadcast()
		this.ccond.L.Unlock()
		//time.Sleep(3 * time.Millisecond)
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return nil, false
		}
		writeIndex = this.GetCurrentWriteIndex()
		if readIndex >= writeIndex {
			this.pcond.Signal()
			//this.pcond.Broadcast()
			this.ccond.Wait()
		} else {
			break
		}
		//time.Sleep(500 * time.Microsecond)
		//time.Sleep(1 * time.Millisecond)
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *buffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Signal()
		//this.ccond.Broadcast()
		this.pcond.L.Unlock()
		//time.Sleep(3 * time.Millisecond)
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return false
		}
		readIndex = this.GetCurrentReadIndex()
		if writeIndex >= readIndex && writeIndex-readIndex >= this.size {
			this.ccond.Signal()
			//this.ccond.Broadcast()
			this.pcond.Wait()
			//time.Sleep(1 * time.Millisecond)
		} else {
			break
		}
		//time.Sleep(500 * time.Microsecond)
		//time.Sleep(1 * time.Millisecond)
	}
	index := writeIndex & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}

/**
修改 尽量减少数据的创建
*/
func (this *buffer) ReadFrom(r io.Reader) (int64, error) {
	defer this.Close()

	total := int64(0)

	for {
		time.Sleep(10 * time.Millisecond)
		if this.isDone() {
			return total, io.EOF
		}

		var write_bytes []byte

		//b := make([]byte, 5)
		n, err := r.Read(this.b[0:1])
		if err != nil {
			return total, io.EOF
		}
		total += int64(n)
		max_cnt := 1
		for {
			if this.isDone() {
				return total, io.EOF
			}
			// If we have read 5 bytes and still not done, then there's a problem.
			if max_cnt > 4 {
				return 0, fmt.Errorf("sendrecv/peekMessageSize: 4th byte of remaining length has continuation bit set")
			}
			_, err := r.Read(this.b[max_cnt:(max_cnt + 1)])

			//fmt.Println(b)
			if err != nil {
				return total, err
			}
			if this.b[max_cnt] >= 0x80 {
				max_cnt++
			} else {
				break
			}
		}
		remlen, m := binary.Uvarint(this.b[1 : max_cnt+1])
		remlen_tmp := int64(remlen)
		start_ := int64(1) + int64(m)
		total_tmp := remlen_tmp + start_

		write_bytes = make([]byte, total_tmp)
		copy(write_bytes[0:m+1], this.b[0:m+1])
		nlen := int64(0)
		times := 0
		cnt_ := int64(32)
		for nlen < remlen_tmp {
			if this.isDone() {
				return total, io.EOF
			}
			if times > 100 {
				return total, io.EOF
			} else {
				times = 0
			}
			times++
			tmpm := remlen_tmp - nlen

			b_ := write_bytes[(start_ + nlen):]
			if tmpm > cnt_ {
				b_ = write_bytes[(start_ + nlen):(start_ + nlen + cnt_)]
			}

			//b_ := make([]byte, remlen)
			n, err = r.Read(b_[0:])

			if err != nil {
				/*Log.Errorc(func() string {
					return fmt.Sprintf("从conn读取数据失败(%s)(0)", err)
				})
				time.Sleep(5 * time.Millisecond)
				continue*/
				return total, err
			}
			//write_bytes = append(write_bytes, b_[0:]...)
			nlen += int64(n)
			total += int64(n)
		}

		ok := this.WriteBuffer(&write_bytes)

		if !ok {
			return total, errors.New("write ringbuffer failed")
		}
	}
}

func (this *buffer) WriteTo(w io.Writer) (int64, error) {
	defer this.Close()

	total := int64(0)

	for {
		if this.isDone() {
			return total, io.EOF
		}

		p, ok := this.ReadBuffer()
		if !ok {
			return total, errors.New("read buffer failed")
		}
		// There's some data, let's process it first
		if len(*p) > 0 {
			n, err := w.Write(*p)
			total += int64(n)
			//Log.Debugc(func() string{ return fmt.Sprintf("Wrote %d bytes, totaling %d bytes", n, total)})

			if err != nil {
				return total, err
			}
		}

	}
}

func (this *buffer) isDone() bool {
	if atomic.LoadInt64(&this.done) == 1 {
		return true
	}

	return false
}

func ringCopy(dst, src []byte, start int64) int {
	n := len(src)

	i, l := 0, 0

	for n > 0 {
		l = copy(dst[start:], src[i:])
		i += l
		n -= l

		if n > 0 {
			start = 0
		}
	}

	return i
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

func roundUpPowerOfTwo64(n int64) int64 {
	n--
	n |= n >> 1
	n |= n >> 2
	n |= n >> 4
	n |= n >> 8
	n |= n >> 16
	n |= n >> 32
	n++

	return n
}
<|endoftext|>


<commit_before>// +build windows

package box

import (
	"syscall"
	"unsafe"
)

var kernel32 = syscall.NewLazyDLL("kernel32")

var hConout, _ = syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)

type coord_t struct {
	X int16
	Y int16
}

type small_rect_t struct {
	Left   int16
	Top    int16
	Right  int16
	Bottom int16
}

type console_screen_buffer_info_t struct {
	Size              coord_t
	CursorPosition    coord_t
	Attributes        uint16
	Window            small_rect_t
	MaximumWindowSize coord_t
}

var getConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")

func GetScreenBufferInfo() *console_screen_buffer_info_t {
	var csbi console_screen_buffer_info_t
	getConsoleScreenBufferInfo.Call(
		uintptr(hConout),
		uintptr(unsafe.Pointer(&csbi)))
	return &csbi
}

func (this *console_screen_buffer_info_t) ViewSize() (int, int) {
	return int(this.Window.Right-this.Window.Left) + 1,
		int(this.Window.Bottom-this.Window.Top) + 1
}

func (this *console_screen_buffer_info_t) CursorPos() (int, int) {
	return int(this.CursorPosition.X), int(this.CursorPosition.Y)
}

func GetLocate() (int, int) {
	return GetScreenBufferInfo().CursorPos()
}
<commit_msg>(inner) make console_handle class<commit_after>// +build windows

package box

import (
	"syscall"
	"unsafe"
)

var kernel32 = syscall.NewLazyDLL("kernel32")

var hConout, _ = syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)

type coord_t struct {
	X int16
	Y int16
}

type small_rect_t struct {
	Left   int16
	Top    int16
	Right  int16
	Bottom int16
}

type console_screen_buffer_info_t struct {
	Size              coord_t
	CursorPosition    coord_t
	Attributes        uint16
	Window            small_rect_t
	MaximumWindowSize coord_t
}

var getConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")

type console_handle_t syscall.Handle

func newHandle(handle syscall.Handle) console_handle_t {
	return console_handle_t(handle)
}

func (h console_handle_t) GetScreenBufferInfo() *console_screen_buffer_info_t {
	var csbi console_screen_buffer_info_t
	getConsoleScreenBufferInfo.Call(
		uintptr(h),
		uintptr(unsafe.Pointer(&csbi)))
	return &csbi
}

func GetScreenBufferInfo() *console_screen_buffer_info_t {
	return console_handle_t(hConout).GetScreenBufferInfo()
}

func (this *console_screen_buffer_info_t) ViewSize() (int, int) {
	return int(this.Window.Right-this.Window.Left) + 1,
		int(this.Window.Bottom-this.Window.Top) + 1
}

func (this *console_screen_buffer_info_t) CursorPos() (int, int) {
	return int(this.CursorPosition.X), int(this.CursorPosition.Y)
}

func GetLocate() (int, int) {
	return GetScreenBufferInfo().CursorPos()
}
<|endoftext|>


<commit_before>// Copyright 2015 The Serulian 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 srg

import (
	"fmt"
	"strings"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/compilerutil"
	"github.com/serulian/compiler/parser"
)

// SRGTypeRef represents a type reference defined in the SRG.
type SRGTypeRef struct {
	compilergraph.GraphNode
	srg *SRG // The parent SRG.
}

type TypeRefKind int

const (
	typeRefUnknown  TypeRefKind = iota // An unknown type.
	TypeRefNullable                    // A nullable type.
	TypeRefStream                      // A stream type.
	TypeRefSlice                       // A slice type.
	TypeRefPath                        // A normal path type. May have generics.
	TypeRefVoid                        // A void type reference.
	TypeRefAny                         // An any type reference.
)

// GetTypeRef returns an SRGTypeRef wrapper for the given type reference now.
func (g *SRG) GetTypeRef(node compilergraph.GraphNode) SRGTypeRef {
	return SRGTypeRef{node, g}
}

// GetTypeReferences returns all the type references in the SRG.
func (g *SRG) GetTypeReferences() []SRGTypeRef {
	it := g.findAllNodes(parser.NodeTypeTypeReference).
		BuildNodeIterator()

	var refs []SRGTypeRef
	for it.Next() {
		refs = append(refs, SRGTypeRef{it.Node(), g})
	}

	return refs
}

// Location returns the source location for this type ref.
func (t SRGTypeRef) Location() compilercommon.SourceAndLocation {
	return salForNode(t.GraphNode)
}

// ResolutionPath returns the full resolution path for this type reference.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolutionPath() string {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")

	var resolvePathPieces = make([]string, 0)
	var currentPath compilergraph.GraphNode = t.GraphNode.
		GetNode(parser.NodeTypeReferencePath).
		GetNode(parser.NodeIdentifierPathRoot)

	for {
		// Add the path piece to the array.
		name := currentPath.Get(parser.NodeIdentifierAccessName)
		resolvePathPieces = append([]string{name}, resolvePathPieces...)

		// If there is a source, continue searching.
		source, found := currentPath.TryGetNode(parser.NodeIdentifierAccessSource)
		if !found {
			break
		}

		currentPath = source
	}

	return strings.Join(resolvePathPieces, ".")
}

// ResolveType attempts to resolve the type path referenced by this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolveType() (TypeResolutionResult, bool) {
	// Find the parent module.
	source := compilercommon.InputSource(t.GraphNode.Get(parser.NodePredicateSource))
	srgModule, found := t.srg.FindModuleBySource(source)
	if !found {
		panic(fmt.Sprintf("Unknown parent module: %s", source))
	}

	// Resolve the type path under the module.
	resolutionPath := t.ResolutionPath()
	resolvedType, typeFound := srgModule.ResolveType(resolutionPath)
	if typeFound {
		return resolvedType, true
	}

	// If not found and the path is a single name, try to resolve as a generic
	// under a parent function or type.
	if strings.ContainsRune(resolutionPath, '.') {
		// Not a single name.
		return TypeResolutionResult{}, false
	}

	containingFilter := func(q compilergraph.GraphQuery) compilergraph.Query {
		// For this filter, we check if the defining type (or type member) if the
		// generic is the same type (or type member) containing the typeref. To do so,
		// we perform a check that the start rune and end rune of the definition
		// contains the range of the start and end rune, respectively, of the typeref. Since
		// we know both nodes are in the same module, and the SRG is a tree, this validates
		// that we are in the correct scope without having to walk the tree upward.
		startRune := t.GraphNode.Get(parser.NodePredicateStartRune)
		endRune := t.GraphNode.Get(parser.NodePredicateEndRune)

		return q.
			In(parser.NodeTypeDefinitionGeneric, parser.NodePredicateTypeMemberGeneric).
			HasWhere(parser.NodePredicateStartRune, compilergraph.WhereLTE, startRune).
			HasWhere(parser.NodePredicateEndRune, compilergraph.WhereGTE, endRune)
	}

	resolvedGenericNode, genericFound := t.srg.layer.
		StartQuery().                                         // Find a node...
		Has(parser.NodeGenericPredicateName, resolutionPath). // With the generic name..
		Has(parser.NodePredicateSource, string(source)).      // That is in this module...
		IsKind(parser.NodeTypeGeneric).                       // That is a generic...
		FilterBy(containingFilter).                           // Filter by whether its defining type or member contains this typeref.
		TryGetNode()

	return resultForTypeOrGeneric(SRGTypeOrGeneric{resolvedGenericNode, t.srg}), genericFound
}

// InnerReference returns the inner type reference, if this is a nullable or stream.
func (t SRGTypeRef) InnerReference() SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() != TypeRefPath }, "Expected non-path")
	return SRGTypeRef{t.GraphNode.GetNode(parser.NodeTypeReferenceInnerType), t.srg}
}

// Generics returns the generics defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Generics() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceGeneric)
}

// HasGenerics returns whether this type reference has generics.
func (t SRGTypeRef) HasGenerics() bool {
	_, found := t.GraphNode.TryGet(parser.NodeTypeReferenceGeneric)
	return found
}

// Parameters returns the parameters defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Parameters() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceParameter)
}

// HasParameters returns whether this type reference has parameters.
func (t SRGTypeRef) HasParameters() bool {
	_, found := t.GraphNode.TryGet(parser.NodeTypeReferenceParameter)
	return found
}

// subReferences returns the subreferences found off of the given predicate, if any.
func (t SRGTypeRef) subReferences(predicate string) []SRGTypeRef {
	subRefs := make([]SRGTypeRef, 0)
	it := t.GraphNode.StartQuery().Out(predicate).BuildNodeIterator()
	for it.Next() {
		subRefs = append(subRefs, SRGTypeRef{it.Node(), t.srg})
	}
	return subRefs
}

// RefKind returns the kind of this type reference.
func (t SRGTypeRef) RefKind() TypeRefKind {
	nodeKind := t.GraphNode.Kind.(parser.NodeType)
	switch nodeKind {
	case parser.NodeTypeVoid:
		return TypeRefVoid

	case parser.NodeTypeAny:
		return TypeRefAny

	case parser.NodeTypeStream:
		return TypeRefStream

	case parser.NodeTypeSlice:
		return TypeRefSlice

	case parser.NodeTypeNullable:
		return TypeRefNullable

	case parser.NodeTypeTypeReference:
		return TypeRefPath

	default:
		panic(fmt.Sprintf("Unknown kind of type reference node %v", nodeKind))
	}
}
<commit_msg>Typo fix<commit_after>// Copyright 2015 The Serulian 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 srg

import (
	"fmt"
	"strings"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/compilerutil"
	"github.com/serulian/compiler/parser"
)

// SRGTypeRef represents a type reference defined in the SRG.
type SRGTypeRef struct {
	compilergraph.GraphNode
	srg *SRG // The parent SRG.
}

type TypeRefKind int

const (
	typeRefUnknown  TypeRefKind = iota // An unknown type.
	TypeRefNullable                    // A nullable type.
	TypeRefStream                      // A stream type.
	TypeRefSlice                       // A slice type.
	TypeRefPath                        // A normal path type. May have generics.
	TypeRefVoid                        // A void type reference.
	TypeRefAny                         // An any type reference.
)

// GetTypeRef returns an SRGTypeRef wrapper for the given type reference node.
func (g *SRG) GetTypeRef(node compilergraph.GraphNode) SRGTypeRef {
	return SRGTypeRef{node, g}
}

// GetTypeReferences returns all the type references in the SRG.
func (g *SRG) GetTypeReferences() []SRGTypeRef {
	it := g.findAllNodes(parser.NodeTypeTypeReference).
		BuildNodeIterator()

	var refs []SRGTypeRef
	for it.Next() {
		refs = append(refs, SRGTypeRef{it.Node(), g})
	}

	return refs
}

// Location returns the source location for this type ref.
func (t SRGTypeRef) Location() compilercommon.SourceAndLocation {
	return salForNode(t.GraphNode)
}

// ResolutionPath returns the full resolution path for this type reference.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolutionPath() string {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")

	var resolvePathPieces = make([]string, 0)
	var currentPath compilergraph.GraphNode = t.GraphNode.
		GetNode(parser.NodeTypeReferencePath).
		GetNode(parser.NodeIdentifierPathRoot)

	for {
		// Add the path piece to the array.
		name := currentPath.Get(parser.NodeIdentifierAccessName)
		resolvePathPieces = append([]string{name}, resolvePathPieces...)

		// If there is a source, continue searching.
		source, found := currentPath.TryGetNode(parser.NodeIdentifierAccessSource)
		if !found {
			break
		}

		currentPath = source
	}

	return strings.Join(resolvePathPieces, ".")
}

// ResolveType attempts to resolve the type path referenced by this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolveType() (TypeResolutionResult, bool) {
	// Find the parent module.
	source := compilercommon.InputSource(t.GraphNode.Get(parser.NodePredicateSource))
	srgModule, found := t.srg.FindModuleBySource(source)
	if !found {
		panic(fmt.Sprintf("Unknown parent module: %s", source))
	}

	// Resolve the type path under the module.
	resolutionPath := t.ResolutionPath()
	resolvedType, typeFound := srgModule.ResolveType(resolutionPath)
	if typeFound {
		return resolvedType, true
	}

	// If not found and the path is a single name, try to resolve as a generic
	// under a parent function or type.
	if strings.ContainsRune(resolutionPath, '.') {
		// Not a single name.
		return TypeResolutionResult{}, false
	}

	containingFilter := func(q compilergraph.GraphQuery) compilergraph.Query {
		// For this filter, we check if the defining type (or type member) if the
		// generic is the same type (or type member) containing the typeref. To do so,
		// we perform a check that the start rune and end rune of the definition
		// contains the range of the start and end rune, respectively, of the typeref. Since
		// we know both nodes are in the same module, and the SRG is a tree, this validates
		// that we are in the correct scope without having to walk the tree upward.
		startRune := t.GraphNode.Get(parser.NodePredicateStartRune)
		endRune := t.GraphNode.Get(parser.NodePredicateEndRune)

		return q.
			In(parser.NodeTypeDefinitionGeneric, parser.NodePredicateTypeMemberGeneric).
			HasWhere(parser.NodePredicateStartRune, compilergraph.WhereLTE, startRune).
			HasWhere(parser.NodePredicateEndRune, compilergraph.WhereGTE, endRune)
	}

	resolvedGenericNode, genericFound := t.srg.layer.
		StartQuery().                                         // Find a node...
		Has(parser.NodeGenericPredicateName, resolutionPath). // With the generic name..
		Has(parser.NodePredicateSource, string(source)).      // That is in this module...
		IsKind(parser.NodeTypeGeneric).                       // That is a generic...
		FilterBy(containingFilter).                           // Filter by whether its defining type or member contains this typeref.
		TryGetNode()

	return resultForTypeOrGeneric(SRGTypeOrGeneric{resolvedGenericNode, t.srg}), genericFound
}

// InnerReference returns the inner type reference, if this is a nullable or stream.
func (t SRGTypeRef) InnerReference() SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() != TypeRefPath }, "Expected non-path")
	return SRGTypeRef{t.GraphNode.GetNode(parser.NodeTypeReferenceInnerType), t.srg}
}

// Generics returns the generics defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Generics() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceGeneric)
}

// HasGenerics returns whether this type reference has generics.
func (t SRGTypeRef) HasGenerics() bool {
	_, found := t.GraphNode.TryGet(parser.NodeTypeReferenceGeneric)
	return found
}

// Parameters returns the parameters defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Parameters() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceParameter)
}

// HasParameters returns whether this type reference has parameters.
func (t SRGTypeRef) HasParameters() bool {
	_, found := t.GraphNode.TryGet(parser.NodeTypeReferenceParameter)
	return found
}

// subReferences returns the subreferences found off of the given predicate, if any.
func (t SRGTypeRef) subReferences(predicate string) []SRGTypeRef {
	subRefs := make([]SRGTypeRef, 0)
	it := t.GraphNode.StartQuery().Out(predicate).BuildNodeIterator()
	for it.Next() {
		subRefs = append(subRefs, SRGTypeRef{it.Node(), t.srg})
	}
	return subRefs
}

// RefKind returns the kind of this type reference.
func (t SRGTypeRef) RefKind() TypeRefKind {
	nodeKind := t.GraphNode.Kind.(parser.NodeType)
	switch nodeKind {
	case parser.NodeTypeVoid:
		return TypeRefVoid

	case parser.NodeTypeAny:
		return TypeRefAny

	case parser.NodeTypeStream:
		return TypeRefStream

	case parser.NodeTypeSlice:
		return TypeRefSlice

	case parser.NodeTypeNullable:
		return TypeRefNullable

	case parser.NodeTypeTypeReference:
		return TypeRefPath

	default:
		panic(fmt.Sprintf("Unknown kind of type reference node %v", nodeKind))
	}
}
<|endoftext|>


<commit_before>package proj

import (
	"goposm/element"
	"math"
)

const pole = 6378137 * math.Pi // 20037508.342789244

func wgsToMerc(long, lat float64) (x, y float64) {
	x = long * pole / 180.0
	y = math.Log(math.Tan((90.0+lat)*math.Pi/360.0)) / math.Pi * pole
	return x, y
}

func mercToWgs(x, y float64) (long, lat float64) {
	long = 180.0 * x / pole
	lat = 180.0 / math.Pi * (2*math.Atan(math.Exp((y/pole)*math.Pi)) - math.Pi/2)
	return long, lat
}

func NodesToMerc(nodes []element.Node) {
	for _, nd := range nodes {
		nd.Long, nd.Lat = wgsToMerc(nd.Long, nd.Lat)
	}
}
<commit_msg>fixed transformation of node slice<commit_after>package proj

import (
	"goposm/element"
	"math"
)

const pole = 6378137 * math.Pi // 20037508.342789244

func wgsToMerc(long, lat float64) (x, y float64) {
	x = long * pole / 180.0
	y = math.Log(math.Tan((90.0+lat)*math.Pi/360.0)) / math.Pi * pole
	return x, y
}

func mercToWgs(x, y float64) (long, lat float64) {
	long = 180.0 * x / pole
	lat = 180.0 / math.Pi * (2*math.Atan(math.Exp((y/pole)*math.Pi)) - math.Pi/2)
	return long, lat
}

func NodesToMerc(nodes []element.Node) {
	for i, nd := range nodes {
		nodes[i].Long, nodes[i].Lat = wgsToMerc(nd.Long, nd.Lat)
	}
}
<|endoftext|>


<commit_before>package sms

import (
	"bufio"
	"bytes"
	"errors"
	"net"
	"strings"
)

type Sender struct {
	Id     string // Sender identifier. See Source field in smsd.cfg
	Server string // IP address:port or unix domain socket path
	Delete bool   // Will message need to be deleted after sent/reported?
	Report bool   // Is report required?
}

// Sends txt as SMS to recipients. Recipient need to be specified as
// PhoneNumber[=DstId] You can use DstId to link recipient with some other
// data in your database. Send is thread-safe.
func (s *Sender) Send(txt string, recipients ...string) error {
	if len(recipients) == 0 {
		return nil
	}
	proto := "tcp"
	if strings.IndexRune(s.Server, ':') == -1 {
		proto = "unix"
	}
	c, err := net.Dial(proto, s.Server)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(c)

	if err = writeln(w, s.Id); err != nil {
		return err
	}

	if _, err = w.WriteString(recipients[0]); err != nil {
		return err
	}
	for _, num := range recipients[1:] {
		if err = w.WriteByte(' '); err != nil {
			return err
		}
		if _, err = w.WriteString(num); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if s.Delete {
		if err = writeln(w, "delete"); err != nil {
			return err
		}
	}
	if s.Report {
		if err = writeln(w, "report"); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if _, err = w.WriteString(strings.TrimSpace(txt)); err != nil {
		return err
	}
	if err = writeln(w, "\n."); err != nil {
		return err
	}
	if err = w.Flush(); err != nil {
		return err
	}
	// Read OK response
	buf, _, err := bufio.NewReader(c).ReadLine()
	if err != nil {
		return err
	}
	buf = bytes.TrimSpace(buf)
	if !bytes.Equal(buf, []byte{'O', 'K'}) {
		c.Close()
		return errors.New(string(buf))
	}
	return c.Close()
}

func newLine(w *bufio.Writer) error {
	return w.WriteByte('\n')
}

func writeln(w *bufio.Writer, s string) error {
	_, err := w.WriteString(s)
	if err != nil {
		return err
	}
	return newLine(w)
}

// Returns number of characters that will be used to send txt via SMS
func Len(txt string) int {
	m, n := 1, 0
	for _, r := range txt {
		if r > 0x7F {
			m = 4
		}
		n++
	}
	return m * n
}
<commit_msg>ParseNumbers function added<commit_after>package sms

import (
	"bufio"
	"bytes"
	"errors"
	"net"
	"strings"
)

type Sender struct {
	Id     string // Sender identifier. See Source field in smsd.cfg
	Server string // IP address:port or unix domain socket path
	Delete bool   // Will message need to be deleted after sent/reported?
	Report bool   // Is report required?
}

// Sends txt as SMS to recipients. Recipient need to be specified as
// PhoneNumber[=DstId] You can use DstId to link recipient with some other
// data in your database. Send is thread-safe.
func (s *Sender) Send(txt string, recipients ...string) error {
	if len(recipients) == 0 {
		return nil
	}
	proto := "tcp"
	if strings.IndexRune(s.Server, ':') == -1 {
		proto = "unix"
	}
	c, err := net.Dial(proto, s.Server)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(c)

	if err = writeln(w, s.Id); err != nil {
		return err
	}

	if _, err = w.WriteString(recipients[0]); err != nil {
		return err
	}
	for _, num := range recipients[1:] {
		if err = w.WriteByte(' '); err != nil {
			return err
		}
		if _, err = w.WriteString(num); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if s.Delete {
		if err = writeln(w, "delete"); err != nil {
			return err
		}
	}
	if s.Report {
		if err = writeln(w, "report"); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if _, err = w.WriteString(strings.TrimSpace(txt)); err != nil {
		return err
	}
	if err = writeln(w, "\n."); err != nil {
		return err
	}
	if err = w.Flush(); err != nil {
		return err
	}
	// Read OK response
	buf, _, err := bufio.NewReader(c).ReadLine()
	if err != nil {
		return err
	}
	buf = bytes.TrimSpace(buf)
	if !bytes.Equal(buf, []byte{'O', 'K'}) {
		c.Close()
		return errors.New(string(buf))
	}
	return c.Close()
}

func newLine(w *bufio.Writer) error {
	return w.WriteByte('\n')
}

func writeln(w *bufio.Writer, s string) error {
	_, err := w.WriteString(s)
	if err != nil {
		return err
	}
	return newLine(w)
}

// Returns number of characters that will be used to send txt via SMS
func Len(txt string) int {
	m, n := 1, 0
	for _, r := range txt {
		if r > 0x7F {
			m = 4
		}
		n++
	}
	return m * n
}

func normalize(num string) string {
	return strings.Map(
		func(r rune) rune {
			if r == '-' || r == ' ' {
				return -1
			}
			return r
		},
		num,
	)
}

// Parses list of numbers in form: 12341, 22-33-44; +48 52 211 222-33-11
// If id != "" appends "=id" to any number.
// If filter != nil it is used to filter normalized numbers.
func ParseNumbers(phones, id string, filter func(string) bool) []string {
	spl := strings.FieldsFunc(
		phones,
		func(r rune) bool {
			return r == ',' || r == ';'
		},
	)
	if id != "" {
		id = "=" + id
	}
	ret := make([]string, 0, len(spl))
	for _, num := range spl {
		num := normalize(num)
		if num != "" && (filter == nil || filter(num)) {
			if id != "" {
				num += id
			}
			ret = append(ret, num)
		}
	}
	return ret
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"time"

	"github.com/cheggaaa/pb"
)

const defaultPort = "5000"

func main() {
	if len(os.Args) < 3 {
		fmt.Printf("Usage: %s <ip> <file>\n", os.Args[0])
		return
	}
	if isCiaFile(os.Args[2]) == false {
		fmt.Println("Error, not cia file")
		return
	}
	file, err := os.Open(os.Args[2])
	checkError(err)
	defer file.Close()
	fileInfo, err := file.Stat()
	checkError(err)
	fileSize := fileInfo.Size()
	ipPort := setDefaultPort(os.Args[1])
	raddr, err := net.ResolveTCPAddr("tcp", ipPort)
	checkError(err)
	out, err := net.DialTCP("tcp", nil, raddr)
	checkError(err)
	defer out.Close()
	buffer := make([]byte, 128*1024)

	//write filesize
	err = binary.Write(out, binary.BigEndian, &fileSize)
	checkError(err)

	//progress bar
	bar := pb.New64(fileSize)
	bar.SetRefreshRate(time.Second)
	bar.ShowCounters = false
	bar.ShowTimeLeft = true
	bar.ShowSpeed = true
	bar.SetUnits(pb.U_BYTES)
	pbStartFlag := false
	ciaInstallSuccess := false

	for {
		n, err := file.Read(buffer)
		if err != nil {
			if err == io.EOF {
				bar.Set64(fileSize)
				ciaInstallSuccess = true
			} else {
				fmt.Println(err)
			}
			break
		}
		if n <= 0 {
			break
		}
		nWrite, err := out.Write(buffer[:n])
		if err != nil {
			fmt.Println(err)
			break
		}
		if pbStartFlag == false {
			pbStartFlag = true
			bar.Set64(0)
			bar.Start()
		}
		bar.Add(nWrite)
		if n != nWrite {
			fmt.Println("partial write...")
			break
		}
	}

	if ciaInstallSuccess {
		bar.FinishPrint("Install cia file success")
	} else {
		bar.FinishPrint("Install cia file failed")
	}
}

func setDefaultPort(ip string) string {
	_, _, err := net.SplitHostPort(ip)
	if err != nil {
		return ip + ":" + defaultPort
	}
	return ip
}

func isCiaFile(path string) bool {
	if len(path) < 4 {
		return false
	}
	ext := path[len(path)-4:]
	if (ext[0] == '.') &&
		(ext[1] == 'c' || ext[1] == 'C') &&
		(ext[2] == 'i' || ext[2] == 'i') &&
		(ext[3] == 'a' || ext[3] == 'A') {
		return true
	}
	return false
}

func checkError(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}
<commit_msg>check file size<commit_after>package main

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"time"

	"github.com/cheggaaa/pb"
)

const defaultPort = "5000"

func main() {
	if len(os.Args) < 3 {
		fmt.Printf("Usage: %s <ip> <file>\n", os.Args[0])
		return
	}
	if isCiaFile(os.Args[2]) == false {
		fmt.Println("Error, not cia file")
		return
	}
	file, err := os.Open(os.Args[2])
	checkError(err)
	defer file.Close()
	fileInfo, err := file.Stat()
	checkError(err)
	fileSize := fileInfo.Size()
	if fileSize <= 0 {
		fmt.Println("Empty file")
		return
	}
	ipPort := setDefaultPort(os.Args[1])
	raddr, err := net.ResolveTCPAddr("tcp", ipPort)
	checkError(err)
	out, err := net.DialTCP("tcp", nil, raddr)
	checkError(err)
	defer out.Close()
	buffer := make([]byte, 128*1024)

	//write filesize
	err = binary.Write(out, binary.BigEndian, &fileSize)
	checkError(err)

	//progress bar
	bar := pb.New64(fileSize)
	bar.SetRefreshRate(time.Second)
	bar.ShowCounters = false
	bar.ShowTimeLeft = true
	bar.ShowSpeed = true
	bar.SetUnits(pb.U_BYTES)
	pbStartFlag := false
	ciaInstallSuccess := false

	for {
		n, err := file.Read(buffer)
		if err != nil {
			if err == io.EOF {
				bar.Set64(fileSize)
				ciaInstallSuccess = true
			} else {
				fmt.Println(err)
			}
			break
		}
		if n <= 0 {
			break
		}
		nWrite, err := out.Write(buffer[:n])
		if err != nil {
			fmt.Println(err)
			break
		}
		if pbStartFlag == false {
			pbStartFlag = true
			bar.Set64(0)
			bar.Start()
		}
		bar.Add(nWrite)
		if n != nWrite {
			fmt.Println("partial write...")
			break
		}
	}

	if ciaInstallSuccess {
		bar.FinishPrint("Install cia file success")
	} else {
		bar.FinishPrint("Install cia file failed")
	}
}

func setDefaultPort(ip string) string {
	_, _, err := net.SplitHostPort(ip)
	if err != nil {
		return ip + ":" + defaultPort
	}
	return ip
}

func isCiaFile(path string) bool {
	if len(path) < 4 {
		return false
	}
	ext := path[len(path)-4:]
	if (ext[0] == '.') &&
		(ext[1] == 'c' || ext[1] == 'C') &&
		(ext[2] == 'i' || ext[2] == 'i') &&
		(ext[3] == 'a' || ext[3] == 'A') {
		return true
	}
	return false
}

func checkError(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}
<|endoftext|>