<commit_before>package models

import (
	"errors"
	"fmt"
	"strings"
	"testing"

	"github.com/taironas/gonawin/helpers"
	"github.com/taironas/gonawin/test"

	"appengine/aetest"
)

type testTeam struct {
	name        string
	description string
	adminId     int64
	private     bool
}

// TestCreateTeam tests that you can create a team.
//
func TestCreateTeam(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		team  testTeam
	}{
		{
			title: "can create public team",
			team:  testTeam{"my team", "description", 10, false},
		},
		{
			title: "can create private team",
			team:  testTeam{"my other team", "description", 0, true},
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *Team
		if got, err = CreateTeam(c, test.team.name, test.team.description, test.team.adminId, test.team.private); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeam(got, test.team); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeamInvertedIndex(t, c, got, test.team); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyTeam test that you can destroy a team.
//
func TestDestroyTeam(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title      string
		team       testTeam
		overrideId bool
		newId      int64
		err        string
	}{
		{
			title: "can destroy team",
			team:  testTeam{"my team", "description", 10, false},
		},
		{
			title:      "cannot destroy team",
			team:       testTeam{"my team other team", "description", 10, false},
			overrideId: true,
			newId:      11,
			err:        "Cannot find team with Id",
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *Team
		if got, err = CreateTeam(c, test.team.name, test.team.description, test.team.adminId, test.team.private); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}

		if test.overrideId {
			got.Id = test.newId
		}

		if err = got.Destroy(c); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
		}

		var team *Team
		if team, err = TeamById(c, got.Id); team != nil {
			t.Errorf("test %v - Error: team found, not properly destroyed - %v", i, err)
		}

		if err = checkTeamInvertedIndex(t, c, got, test.team); err == nil {
			t.Errorf("test %v - Error: team found in database", i)
		}
	}
}

// TestFindTeams tests that you can find teams.
//
func TestFindTeams(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		teams []testTeam
		query string
		want  int
	}{
		{
			title: "can find team",
			teams: []testTeam{
				testTeam{"my team", "description", 10, false},
				testTeam{"my other team", "description", 10, false},
			},
			query: "my team",
			want:  1,
		},
		{
			title: "cannot find teams",
			teams: []testTeam{
				testTeam{"real", "description", 10, false},
				testTeam{"barça", "description", 10, false},
			},
			query: "something else",
			want:  0,
		},
		{
			title: "can find multiple teams",
			teams: []testTeam{
				testTeam{"lakers", "description", 10, false},
				testTeam{"lakers", "description", 10, false},
				testTeam{"lakers", "description", 10, false},
			},
			query: "lakers",
			want:  3,
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		for _, team := range test.teams {
			if _, err = CreateTeam(c, team.name, team.description, team.adminId, team.private); err != nil {
				t.Errorf("test %v - Error: %v", i, err)
			}
		}

		var got []*Team
		if got = FindTeams(c, "Name", test.query); len(got) != test.want {
			t.Errorf("test %v - found %v teams expected %v with query %v by Name", i, test.want, len(got), test.query)
		}
	}
}

// TestTeamById tests TeamById function.
//
func TestTeamById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tTeam := testTeam{"my team", "description", 10, false}

	var team *Team
	if team, err = CreateTeam(c, tTeam.name, tTeam.description, tTeam.adminId, tTeam.private); err != nil {
		t.Errorf("Error: %v", err)
	}

	tests := []struct {
		title  string
		Id     int64
		wanted testTeam
		err    string
	}{
		{
			title:  "can get team by Id",
			Id:     team.Id,
			wanted: testTeam{team.Name, team.Description, team.AdminIds[0], team.Private},
		},
		{
			title: "cannot get team by Id",
			Id:    -1,
			err:   "no such entity",
		},
	}

	for i, test := range tests {
		t.Log(test.title)

		var got *Team
		if got, err = TeamById(c, test.Id); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
		} else if err = checkTeam(got, test.wanted); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamKeyById tests TeamKeyById function.
//
func TestTeamKeyById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		id    int64
	}{
		{
			title: "can get team Key by Id",
			id:    0,
		},
	}

	for i, test := range tests {
		t.Log(test.title)

		if got := TeamKeyById(c, test.id); got == nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamUpdate tests team.Update function.
//
func TestTeamUpdate(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tTeam := testTeam{"my team", "description", 10, false}

	var newTeam *Team
	if newTeam, err = CreateTeam(c, tTeam.name, tTeam.description, tTeam.adminId, tTeam.private); err != nil {
		t.Errorf("Error: %v", err)
	}

	tests := []struct {
		title      string
		id         int64
		updateTeam testTeam
		overrideId bool
		newId      int64
		err        string
	}{
		{
			title:      "can update team",
			id:         newTeam.Id,
			updateTeam: testTeam{name: "updated team 1", description: "updated description 1"},
		},
		{
			title:      "cannot update, team not found",
			id:         newTeam.Id,
			updateTeam: testTeam{name: "updated team 2", description: "updated description 2"},
			overrideId: true,
			newId:      -1,
			err:        "no such entity",
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var team *Team
		if team, err = TeamById(c, test.id); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}

		team.Name = test.updateTeam.name
		team.Description = test.updateTeam.description
		team.AdminIds[0] = test.updateTeam.adminId
		team.Private = test.updateTeam.private

		if test.overrideId {
			team.Id = test.newId
		}

		if err = team.Update(c); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
			continue
		}

		var got *Team
		if got, err = TeamById(c, team.Id); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeam(got, test.updateTeam); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeamInvertedIndex(t, c, got, test.updateTeam); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamsKeysByIds tests team.TeamsKeysByIds function.
//
func TestTeamsKeysByIds(t *testing.T) {
	var c aetest.Context

	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	ids := []int64{1, 2, 3, 4}
	keys := TeamsKeysByIds(c, ids)
	if len(keys) != len(ids) {
		t.Errorf("test keys lenght does not match, expected: %v, got: %v", len(ids), len(keys))
	}
}

// checkTeam checks that the team passed has the same fields as the testTeam object.
//
func checkTeam(got *Team, want testTeam) error {
	var s string
	if got.Name != want.name {
		s = fmt.Sprintf("want name == %s, got %s", want.name, got.Name)
	} else if got.Description != want.description {
		s = fmt.Sprintf("want Description == %s, got %s", want.description, got.Description)
	} else if got.AdminIds[0] != want.adminId {
		s = fmt.Sprintf("want AdminId == %s, got %s", want.adminId, got.AdminIds[0])
	} else if got.Private != want.private {
		s = fmt.Sprintf("want Private == %s, got %s", want.private, got.Private)
	} else {
		return nil
	}
	return errors.New(s)
}

// checkTeamInvertedIndex checks that the team is present in the datastore when
// performing a search.
//
func checkTeamInvertedIndex(t *testing.T, c aetest.Context, got *Team, want testTeam) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings(want.name)
	if ids, err = GetTeamInvertedIndexes(c, words); err != nil {
		return fmt.Errorf("failed calling GetTeamInvertedIndexes %v", err)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("team not found")
}
<commit_msg>multiple tests<commit_after>package models

import (
	"errors"
	"fmt"
	"strings"
	"testing"

	"github.com/taironas/gonawin/helpers"
	"github.com/taironas/gonawin/test"

	"appengine/aetest"
)

type testTeam struct {
	name        string
	description string
	adminId     int64
	private     bool
}

// TestCreateTeam tests that you can create a team.
//
func TestCreateTeam(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		team  testTeam
	}{
		{
			title: "can create public team",
			team:  testTeam{"my team", "description", 10, false},
		},
		{
			title: "can create private team",
			team:  testTeam{"my other team", "description", 0, true},
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *Team
		if got, err = CreateTeam(c, test.team.name, test.team.description, test.team.adminId, test.team.private); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeam(got, test.team); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeamInvertedIndex(t, c, got, test.team); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyTeam test that you can destroy a team.
//
func TestDestroyTeam(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title      string
		team       testTeam
		overrideId bool
		newId      int64
		err        string
	}{
		{
			title: "can destroy team",
			team:  testTeam{"my team", "description", 10, false},
		},
		{
			title:      "cannot destroy team",
			team:       testTeam{"my team other team", "description", 10, false},
			overrideId: true,
			newId:      11,
			err:        "Cannot find team with Id",
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *Team
		if got, err = CreateTeam(c, test.team.name, test.team.description, test.team.adminId, test.team.private); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}

		if test.overrideId {
			got.Id = test.newId
		}

		if err = got.Destroy(c); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
		}

		var team *Team
		if team, err = TeamById(c, got.Id); team != nil {
			t.Errorf("test %v - Error: team found, not properly destroyed - %v", i, err)
		}

		if err = checkTeamInvertedIndex(t, c, got, test.team); err == nil {
			t.Errorf("test %v - Error: team found in database", i)
		}
	}
}

// TestFindTeams tests that you can find teams.
//
func TestFindTeams(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		teams []testTeam
		query string
		want  int
	}{
		{
			title: "can find team",
			teams: []testTeam{
				testTeam{"my team", "description", 10, false},
				testTeam{"my other team", "description", 10, false},
			},
			query: "my team",
			want:  1,
		},
		{
			title: "cannot find teams",
			teams: []testTeam{
				testTeam{"real", "description", 10, false},
				testTeam{"barça", "description", 10, false},
			},
			query: "something else",
			want:  0,
		},
		{
			title: "can find multiple teams",
			teams: []testTeam{
				testTeam{"lakers", "description", 10, false},
				testTeam{"lakers", "description", 10, false},
				testTeam{"lakers", "description", 10, false},
			},
			query: "lakers",
			want:  3,
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		for _, team := range test.teams {
			if _, err = CreateTeam(c, team.name, team.description, team.adminId, team.private); err != nil {
				t.Errorf("test %v - Error: %v", i, err)
			}
		}

		var got []*Team
		if got = FindTeams(c, "Name", test.query); len(got) != test.want {
			t.Errorf("test %v - found %v teams expected %v with query %v by Name", i, test.want, len(got), test.query)
		}
	}
}

// TestTeamById tests TeamById function.
//
func TestTeamById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tTeam := testTeam{"my team", "description", 10, false}

	var team *Team
	if team, err = CreateTeam(c, tTeam.name, tTeam.description, tTeam.adminId, tTeam.private); err != nil {
		t.Errorf("Error: %v", err)
	}

	tests := []struct {
		title  string
		Id     int64
		wanted testTeam
		err    string
	}{
		{
			title:  "can get team by Id",
			Id:     team.Id,
			wanted: testTeam{team.Name, team.Description, team.AdminIds[0], team.Private},
		},
		{
			title: "cannot get team by Id",
			Id:    -1,
			err:   "no such entity",
		},
	}

	for i, test := range tests {
		t.Log(test.title)

		var got *Team
		if got, err = TeamById(c, test.Id); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
		} else if err = checkTeam(got, test.wanted); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamKeyById tests TeamKeyById function.
//
func TestTeamKeyById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		id    int64
	}{
		{
			title: "can get team Key by Id",
			id:    0,
		},
	}

	for i, test := range tests {
		t.Log(test.title)

		if got := TeamKeyById(c, test.id); got == nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamUpdate tests team.Update function.
//
func TestTeamUpdate(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tTeam := testTeam{"my team", "description", 10, false}

	var newTeam *Team
	if newTeam, err = CreateTeam(c, tTeam.name, tTeam.description, tTeam.adminId, tTeam.private); err != nil {
		t.Errorf("Error: %v", err)
	}

	tests := []struct {
		title      string
		id         int64
		updateTeam testTeam
		overrideId bool
		newId      int64
		err        string
	}{
		{
			title:      "can update team",
			id:         newTeam.Id,
			updateTeam: testTeam{name: "updated team 1", description: "updated description 1"},
		},
		{
			title:      "cannot update, team not found",
			id:         newTeam.Id,
			updateTeam: testTeam{name: "updated team 2", description: "updated description 2"},
			overrideId: true,
			newId:      -1,
			err:        "no such entity",
		},
	}

	for i, test := range tests {
		t.Log(test.title)
		var team *Team
		if team, err = TeamById(c, test.id); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}

		team.Name = test.updateTeam.name
		team.Description = test.updateTeam.description
		team.AdminIds[0] = test.updateTeam.adminId
		team.Private = test.updateTeam.private

		if test.overrideId {
			team.Id = test.newId
		}

		if err = team.Update(c); err != nil {
			if len(test.err) == 0 {
				t.Errorf("test %v - Error: %v", i, err)
			} else if !strings.Contains(gonawintest.ErrorString(err), test.err) {
				t.Errorf("test %v - Error: %v expected %v", i, err, test.err)
			}
			continue
		}

		var got *Team
		if got, err = TeamById(c, team.Id); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeam(got, test.updateTeam); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkTeamInvertedIndex(t, c, got, test.updateTeam); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestTeamsKeysByIds tests team.TeamsKeysByIds function.
//
func TestTeamsKeysByIds(t *testing.T) {
	var c aetest.Context

	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		ids []int64
	}{
		{[]int64{}},
		{[]int64{1, 2, 3, 4}},
	}

	for i, test := range tests {
		keys := TeamsKeysByIds(c, test.ids)
		if len(keys) != len(test.ids) {
			t.Errorf("test %v: keys lenght does not match, expected: %v, got: %v", i, len(test.ids), len(keys))
		}
	}
}

// checkTeam checks that the team passed has the same fields as the testTeam object.
//
func checkTeam(got *Team, want testTeam) error {
	var s string
	if got.Name != want.name {
		s = fmt.Sprintf("want name == %s, got %s", want.name, got.Name)
	} else if got.Description != want.description {
		s = fmt.Sprintf("want Description == %s, got %s", want.description, got.Description)
	} else if got.AdminIds[0] != want.adminId {
		s = fmt.Sprintf("want AdminId == %s, got %s", want.adminId, got.AdminIds[0])
	} else if got.Private != want.private {
		s = fmt.Sprintf("want Private == %s, got %s", want.private, got.Private)
	} else {
		return nil
	}
	return errors.New(s)
}

// checkTeamInvertedIndex checks that the team is present in the datastore when
// performing a search.
//
func checkTeamInvertedIndex(t *testing.T, c aetest.Context, got *Team, want testTeam) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings(want.name)
	if ids, err = GetTeamInvertedIndexes(c, words); err != nil {
		return fmt.Errorf("failed calling GetTeamInvertedIndexes %v", err)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("team not found")
}
<|endoftext|>


<commit_before>package file

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/mithrandie/go-file/v2"
)

type OpenType int

const (
	ForRead OpenType = iota
	ForCreate
	ForUpdate
)

type mngFileType int

const (
	fileTypeRLock mngFileType = iota
	fileTypeLock
	fileTypeTemp
)

var mngFileTypeLit = map[mngFileType]string{
	fileTypeRLock: "read lock",
	fileTypeLock:  "lock",
	fileTypeTemp:  "temporary",
}

func (t mngFileType) String() string {
	return mngFileTypeLit[t]
}

type mngFile struct {
	path string
	fp   *os.File
}

func newMngFile(path string, fp *os.File) *mngFile {
	return &mngFile{
		path: path,
		fp:   fp,
	}
}

func (m *mngFile) close() error {
	if m != nil {
		if m.fp != nil {
			if err := file.Close(m.fp); err != nil {
				return err
			}
		}

		if Exists(m.path) {
			if err := os.Remove(m.path); err != nil {
				return err
			}
		}
	}
	return nil
}

func (m *mngFile) closeWithErrors() []error {
	var errs []error
	if m != nil {
		if m.fp != nil {
			if err := file.Close(m.fp); err != nil {
				errs = append(errs, err)
			}
		}

		if Exists(m.path) {
			if err := os.Remove(m.path); err != nil {
				errs = append(errs, err)
			}
		}
	}
	return errs
}

type Handler struct {
	path string
	fp   *os.File

	openType OpenType

	rlockFile *mngFile
	lockFile  *mngFile
	tempFile  *mngFile

	closed bool
}

func NewHandlerForRead(ctx context.Context, container *Container, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) {
	tctx, cancel := GetTimeoutContext(ctx, defaultWaitTimeout)
	defer cancel()

	h := &Handler{
		path:     path,
		openType: ForRead,
	}

	if !Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s does not exist", h.path))
	}

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeRLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.OpenToReadContext(tctx, retryDelay, h.path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func NewHandlerForCreate(container *Container, path string) (*Handler, error) {
	h := &Handler{
		path:     path,
		openType: ForCreate,
	}

	if Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s already exists", h.path))
	}

	if err := h.tryCreateManagementFile(fileTypeLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.Create(h.path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func NewHandlerForUpdate(ctx context.Context, container *Container, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) {
	tctx, cancel := GetTimeoutContext(ctx, defaultWaitTimeout)
	defer cancel()

	h := &Handler{
		path:     path,
		openType: ForUpdate,
	}

	if !Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s does not exist", h.path))
	}

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.OpenToUpdateContext(tctx, retryDelay, path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeTemp); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func closeIsolatedHandler(h *Handler, err error) error {
	return NewCompositeError(ParseError(err), h.closeWithErrors())
}

func (h *Handler) Path() string {
	return h.path
}

func (h *Handler) File() *os.File {
	return h.fp
}

func (h *Handler) FileForUpdate() (*os.File, error) {
	switch h.openType {
	case ForUpdate:
		return h.tempFile.fp, nil
	case ForCreate:
		return h.fp, nil
	}
	return nil, fmt.Errorf("file %s cannot be updated", h.path)
}

func (h *Handler) close() error {
	if h.closed {
		return nil
	}

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			return err
		}
		h.fp = nil
	}

	if h.openType == ForCreate && Exists(h.path) {
		if err := os.Remove(h.path); err != nil {
			return err
		}
	}

	if err := h.tempFile.close(); err != nil {
		return err
	}
	h.tempFile = nil

	if err := h.lockFile.close(); err != nil {
		return err
	}
	h.lockFile = nil

	if err := h.rlockFile.close(); err != nil {
		return err
	}
	h.rlockFile = nil

	h.closed = true
	return nil
}

func (h *Handler) commit() error {
	if h.closed {
		return nil
	}

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			return err
		}
		h.fp = nil
	}

	if h.openType == ForUpdate {
		if h.tempFile.fp != nil {
			if err := file.Close(h.tempFile.fp); err != nil {
				return err
			}
			h.tempFile.fp = nil
		}

		if Exists(h.path) {
			if err := os.Remove(h.path); err != nil {
				return err
			}
		}

		if err := os.Rename(h.tempFile.path, h.path); err != nil {
			return err
		}
	} else {
		if err := h.tempFile.close(); err != nil {
			return err
		}
		h.tempFile = nil
	}

	if err := h.lockFile.close(); err != nil {
		return err
	}
	h.lockFile = nil

	if err := h.rlockFile.close(); err != nil {
		return err
	}
	h.rlockFile = nil

	h.closed = true
	return nil
}

func (h *Handler) closeWithErrors() error {
	if h.closed {
		return nil
	}

	var errs []error

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			errs = append(errs, err)
		} else {
			h.fp = nil
		}
	}

	if h.openType == ForCreate && Exists(h.path) {
		if err := os.Remove(h.path); err != nil {
			errs = append(errs, err)
		}
	}

	if cerrs := h.tempFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.tempFile = nil
	}

	if cerrs := h.lockFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.lockFile = nil
	}

	if cerrs := h.rlockFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.rlockFile = nil
	}

	return NewForcedUnlockError(errs)
}

func (h *Handler) CreateManagementFileContext(ctx context.Context, retryDelay time.Duration, fileType mngFileType) error {
	if ctx.Err() != nil {
		return NewContextIsDone(ctx.Err().Error())
	}

	for {
		if err := h.tryCreateManagementFile(fileType); err != nil {
			if _, ok := err.(*LockError); !ok {
				return err
			}
		} else {
			return nil
		}

		select {
		case <-ctx.Done():
			return NewTimeoutError(h.path)
		case <-time.After(retryDelay):
			// try again
		}
	}
}

func (h *Handler) tryCreateManagementFile(fileType mngFileType) error {
	if len(h.path) < 1 {
		return NewLockError("filename not specified")
	}

	switch fileType {
	case fileTypeLock:
		return h.tryCreateLockFile()
	case fileTypeTemp:
		return h.tryCreateTempFile()
	default: //fileTypeRLock
		return h.tryCreateRLockFile()
	}
}

func (h *Handler) tryCreateRLockFile() (err error) {
	if h.rlockFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeRLock, h.path))
	}

	lockFilePath := LockFilePath(h.path)
	if LockExists(h.path) {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
	}

	lfp, err := file.Create(lockFilePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
	}
	lockFile := newMngFile(lockFilePath, lfp)
	defer func() {
		err = NewCompositeError(err, lockFile.close())
	}()

	filePath := RLockFilePath(h.path)
	fp, e := file.Create(filePath)
	if e != nil {
		err = NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
		return
	}

	h.rlockFile = newMngFile(filePath, fp)
	return
}

func (h *Handler) tryCreateLockFile() error {
	if h.lockFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeLock, h.path))
	}

	filePath := LockFilePath(h.path)
	if RLockExists(h.path) || LockExists(h.path) {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeLock, h.path))
	}

	fp, err := file.Create(filePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeLock, h.path))
	}

	h.lockFile = newMngFile(filePath, fp)
	return nil
}

func (h *Handler) tryCreateTempFile() error {
	if h.tempFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeTemp, h.path))
	}

	filePath := TempFilePath(h.path)
	fp, err := file.Create(filePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeTemp, h.path))
	}

	h.tempFile = newMngFile(filePath, fp)
	return nil
}
<commit_msg>Improve file handling.<commit_after>package file

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/mithrandie/go-file/v2"
)

type OpenType int

const (
	ForRead OpenType = iota
	ForCreate
	ForUpdate
)

type mngFileType int

const (
	fileTypeRLock mngFileType = iota
	fileTypeLock
	fileTypeTemp
)

var mngFileTypeLit = map[mngFileType]string{
	fileTypeRLock: "read lock",
	fileTypeLock:  "lock",
	fileTypeTemp:  "temporary",
}

func (t mngFileType) String() string {
	return mngFileTypeLit[t]
}

type mngFile struct {
	path string
	fp   *os.File
}

func newMngFile(path string, fp *os.File) *mngFile {
	return &mngFile{
		path: path,
		fp:   fp,
	}
}

func (m *mngFile) close() error {
	if m != nil {
		if m.fp != nil {
			if err := file.Close(m.fp); err != nil {
				return err
			}
		}

		if Exists(m.path) {
			if err := os.Remove(m.path); err != nil {
				return err
			}
		}
	}
	return nil
}

func (m *mngFile) closeWithErrors() []error {
	var errs []error
	if m != nil {
		if m.fp != nil {
			if err := file.Close(m.fp); err != nil {
				errs = append(errs, err)
			}
		}

		if Exists(m.path) {
			if err := os.Remove(m.path); err != nil {
				errs = append(errs, err)
			}
		}
	}
	return errs
}

type Handler struct {
	path string
	fp   *os.File

	openType OpenType

	rlockFile *mngFile
	lockFile  *mngFile
	tempFile  *mngFile

	closed bool
}

func NewHandlerForRead(ctx context.Context, container *Container, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) {
	tctx, cancel := GetTimeoutContext(ctx, defaultWaitTimeout)
	defer cancel()

	h := &Handler{
		path:     path,
		openType: ForRead,
	}

	if !Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s does not exist", h.path))
	}

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeRLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.OpenToReadContext(tctx, retryDelay, h.path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func NewHandlerForCreate(container *Container, path string) (*Handler, error) {
	h := &Handler{
		path:     path,
		openType: ForCreate,
	}

	if Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s already exists", h.path))
	}

	if err := h.tryCreateManagementFile(fileTypeLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.Create(h.path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func NewHandlerForUpdate(ctx context.Context, container *Container, path string, defaultWaitTimeout time.Duration, retryDelay time.Duration) (*Handler, error) {
	tctx, cancel := GetTimeoutContext(ctx, defaultWaitTimeout)
	defer cancel()

	h := &Handler{
		path:     path,
		openType: ForUpdate,
	}

	if !Exists(h.path) {
		return h, NewIOError(fmt.Sprintf("file %s does not exist", h.path))
	}

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeLock); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	fp, err := file.OpenToUpdateContext(tctx, retryDelay, path)
	if err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	h.fp = fp

	if err := h.CreateManagementFileContext(tctx, retryDelay, fileTypeTemp); err != nil {
		return h, closeIsolatedHandler(h, err)
	}

	if err := container.Add(h.path, h); err != nil {
		return h, closeIsolatedHandler(h, err)
	}
	return h, nil
}

func closeIsolatedHandler(h *Handler, err error) error {
	return NewCompositeError(ParseError(err), h.closeWithErrors())
}

func (h *Handler) Path() string {
	return h.path
}

func (h *Handler) File() *os.File {
	return h.fp
}

func (h *Handler) FileForUpdate() (*os.File, error) {
	switch h.openType {
	case ForUpdate:
		return h.tempFile.fp, nil
	case ForCreate:
		return h.fp, nil
	}
	return nil, fmt.Errorf("file %s cannot be updated", h.path)
}

func (h *Handler) close() error {
	if h.closed {
		return nil
	}

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			return err
		}
		h.fp = nil
	}

	if h.openType == ForCreate && Exists(h.path) {
		if err := os.Remove(h.path); err != nil {
			return err
		}
	}

	if err := h.tempFile.close(); err != nil {
		return err
	}
	h.tempFile = nil

	if err := h.lockFile.close(); err != nil {
		return err
	}
	h.lockFile = nil

	if err := h.rlockFile.close(); err != nil {
		return err
	}
	h.rlockFile = nil

	h.closed = true
	return nil
}

func (h *Handler) commit() error {
	if h.closed {
		return nil
	}

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			return err
		}
		h.fp = nil
	}

	if h.openType == ForUpdate {
		if h.tempFile.fp != nil {
			if err := file.Close(h.tempFile.fp); err != nil {
				return err
			}
			h.tempFile.fp = nil
		}

		if Exists(h.path) {
			if err := os.Remove(h.path); err != nil {
				return err
			}
		}

		if err := os.Rename(h.tempFile.path, h.path); err != nil {
			return err
		}
	} else {
		if err := h.tempFile.close(); err != nil {
			return err
		}
		h.tempFile = nil
	}

	if err := h.lockFile.close(); err != nil {
		return err
	}
	h.lockFile = nil

	if err := h.rlockFile.close(); err != nil {
		return err
	}
	h.rlockFile = nil

	h.closed = true
	return nil
}

func (h *Handler) closeWithErrors() error {
	if h.closed {
		return nil
	}

	var errs []error

	if h.fp != nil {
		if err := file.Close(h.fp); err != nil {
			errs = append(errs, err)
		} else {
			h.fp = nil
		}
	}

	if h.openType == ForCreate && Exists(h.path) {
		if err := os.Remove(h.path); err != nil {
			errs = append(errs, err)
		}
	}

	if cerrs := h.tempFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.tempFile = nil
	}

	if cerrs := h.lockFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.lockFile = nil
	}

	if cerrs := h.rlockFile.closeWithErrors(); cerrs != nil {
		errs = append(errs, cerrs...)
	} else {
		h.rlockFile = nil
	}

	return NewForcedUnlockError(errs)
}

func (h *Handler) CreateManagementFileContext(ctx context.Context, retryDelay time.Duration, fileType mngFileType) error {
	if ctx.Err() != nil {
		return NewContextIsDone(ctx.Err().Error())
	}

	for {
		if err := h.tryCreateManagementFile(fileType); err != nil {
			if _, ok := err.(*LockError); !ok {
				return err
			}
		} else {
			return nil
		}

		select {
		case <-ctx.Done():
			return NewTimeoutError(h.path)
		case <-time.After(retryDelay):
			// try again
		}
	}
}

func (h *Handler) tryCreateManagementFile(fileType mngFileType) error {
	if len(h.path) < 1 {
		return NewLockError("filename not specified")
	}

	switch fileType {
	case fileTypeLock:
		return h.tryCreateLockFile()
	case fileTypeTemp:
		return h.tryCreateTempFile()
	default: //fileTypeRLock
		return h.tryCreateRLockFile()
	}
}

func (h *Handler) tryCreateRLockFile() (err error) {
	if h.rlockFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeRLock, h.path))
	}

	lockFilePath := LockFilePath(h.path)
	if LockExists(h.path) {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
	}

	lfp, err := file.Create(lockFilePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
	}
	lockFile := newMngFile(lockFilePath, lfp)
	defer func() {
		err = NewCompositeError(err, lockFile.close())
	}()

	filePath := RLockFilePath(h.path)
	fp, e := file.Create(filePath)
	if e != nil {
		err = NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeRLock, h.path))
		return
	}

	h.rlockFile = newMngFile(filePath, fp)
	return
}

func (h *Handler) tryCreateLockFile() error {
	if h.lockFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeLock, h.path))
	}

	filePath := LockFilePath(h.path)
	if LockExists(h.path) || RLockExists(h.path) {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeLock, h.path))
	}

	fp, err := file.Create(filePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeLock, h.path))
	}
	h.lockFile = newMngFile(filePath, fp)

	if RLockExists(h.path) {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeLock, h.path))
	}

	return nil
}

func (h *Handler) tryCreateTempFile() error {
	if h.tempFile != nil {
		return NewLockError(fmt.Sprintf("%s file for %s is already created", fileTypeTemp, h.path))
	}

	filePath := TempFilePath(h.path)
	fp, err := file.Create(filePath)
	if err != nil {
		return NewLockError(fmt.Sprintf("failed to create %s file for %q", fileTypeTemp, h.path))
	}

	h.tempFile = newMngFile(filePath, fp)
	return nil
}
<|endoftext|>


<commit_before>package rpc

import (
	viper "github.com/spf13/viper"

	log "github.com/Cepave/open-falcon-backend/common/logruslog"
	nqmService "github.com/Cepave/open-falcon-backend/common/service/nqm"
)

var logger = log.NewDefaultLogger("INFO")

func InitPackage(config *viper.Viper) {
	config.SetDefault("nqm.queue_size.refresh_agent_ping_list", 8)
	config.SetDefault("nqm.cache_minutes.agent_ping_list", 20)

	nqmConfig := nqmService.AgentHbsServiceConfig {
		QueueSizeOfRefreshCacheOfPingList: config.GetInt("nqm.queue_size.refresh_agent_ping_list"),
		CacheTimeoutMinutes: config.GetInt("nqm.cache_minutes.agent_ping_list"),
	}
	nqmAgentHbsService = nqmService.NewAgentHbsService(nqmConfig)

	logger.Infof("[NQM] Ping list of agent. Timeout: %d minutes. Queue Size: %d",
		nqmConfig.CacheTimeoutMinutes, nqmConfig.QueueSizeOfRefreshCacheOfPingList,
	)
}
<commit_msg>[OWL-1594] Add checking of least value on cache timeout(non-debug mode)<commit_after>package rpc

import (
	viper "github.com/spf13/viper"

	log "github.com/Cepave/open-falcon-backend/common/logruslog"
	nqmService "github.com/Cepave/open-falcon-backend/common/service/nqm"
)

var logger = log.NewDefaultLogger("INFO")

func InitPackage(config *viper.Viper) {
	initNqmConfig(config)
}

func initNqmConfig(config *viper.Viper) {
	config.SetDefault("nqm.queue_size.refresh_agent_ping_list", 8)
	config.SetDefault("nqm.cache_minutes.agent_ping_list", 20)

	nqmConfig := nqmService.AgentHbsServiceConfig {
		QueueSizeOfRefreshCacheOfPingList: config.GetInt("nqm.queue_size.refresh_agent_ping_list"),
		CacheTimeoutMinutes: config.GetInt("nqm.cache_minutes.agent_ping_list"),
	}

	/**
	 * If the mode is not in debug, the least timeout is 10 minutes
	 */
	if !config.GetBool("debug") && config.GetInt("nqm.cache_minutes.agent_ping_list") < 5 {
		nqmConfig.CacheTimeoutMinutes = 5
	}
	// :~)

	nqmAgentHbsService = nqmService.NewAgentHbsService(nqmConfig)

	logger.Infof("[NQM] Ping list of agent. Timeout: %d minutes. Queue Size: %d",
		nqmConfig.CacheTimeoutMinutes, nqmConfig.QueueSizeOfRefreshCacheOfPingList,
	)
}
<|endoftext|>


<commit_before>package luaconf

import (
	"github.com/carbonsrv/carbon/modules/glue"
	"github.com/gin-gonic/gin"
	//"github.com/vifino/golua/lua"
	"github.com/carbonsrv/carbon/modules/middleware"
	"github.com/carbonsrv/carbon/modules/repl"
	"github.com/carbonsrv/carbon/modules/scheduler"
	"github.com/pmylund/go-cache"
	"github.com/vifino/luar"
)

var checker_code = `
srv.Finish_VHOSTS()

if srv.used == false then
	os.exit(0)
end
`

// Configure the server based on a lua script.
func Configure(script string, args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, runrepl bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if !runrepl && didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	err := L.DoFile(script)
	if err != nil {
		return err
	} else {
		if runrepl {
			repl.Run(L)
		}
		L.DoString(checker_code)
		c := make(chan bool)
		<-c
	}
	return nil
}

// Configure the server based on a lua string.
func Eval(script string, args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, runrepl bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if !runrepl && didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	err := L.DoString(script)
	if err != nil {
		return err
	} else {
		if runrepl {
			repl.Run(L)
		}
		L.DoString(checker_code)
		c := make(chan bool)
		<-c
	}
	return nil
}

// Run REPL
func REPL(args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if !runrepl && didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	repl.Run(L)
	L.DoString(checker_code)
	return nil
}
<commit_msg>Woops, some prototype code is left oer.<commit_after>package luaconf

import (
	"github.com/carbonsrv/carbon/modules/glue"
	"github.com/gin-gonic/gin"
	//"github.com/vifino/golua/lua"
	"github.com/carbonsrv/carbon/modules/middleware"
	"github.com/carbonsrv/carbon/modules/repl"
	"github.com/carbonsrv/carbon/modules/scheduler"
	"github.com/pmylund/go-cache"
	"github.com/vifino/luar"
)

var checker_code = `
srv.Finish_VHOSTS()

if srv.used == false then
	os.exit(0)
end
`

// Configure the server based on a lua script.
func Configure(script string, args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, runrepl bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	err := L.DoFile(script)
	if err != nil {
		return err
	} else {
		if runrepl {
			repl.Run(L)
		}
		L.DoString(checker_code)
		c := make(chan bool)
		<-c
	}
	return nil
}

// Configure the server based on a lua string.
func Eval(script string, args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, runrepl bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	err := L.DoString(script)
	if err != nil {
		return err
	} else {
		if runrepl {
			repl.Run(L)
		}
		L.DoString(checker_code)
		c := make(chan bool)
		<-c
	}
	return nil
}

// Run REPL
func REPL(args []string, cfe *cache.Cache, webroot string, useRecovery bool, useLogger bool, finalizer func(srv *gin.Engine)) error {
	srv := gin.New()
	if useLogger {
		srv.Use(gin.Logger())
	}
	if useRecovery {
		srv.Use(gin.Recovery())
	}
	L := luar.Init()

	var didnt_run_yet = true
	luar.Register(L, "carbon", luar.Map{ // srv and the state
		"srv": srv,
		"L":   L,
		"launch_server": func() {
			if didnt_run_yet {
				scheduler.Add(func() {
					finalizer(srv)
				})
				didnt_run_yet = false
			}
		},
	})
	luar.Register(L, "var", luar.Map{ // Vars
		"root": webroot,
	})
	luar.Register(L, "", luar.Map{
		"args": args,
	})
	middleware.Bind(L)
	middleware.BindStatic(L, cfe)
	L.DoString(glue.MainGlue())
	L.DoString(glue.ConfGlue())

	repl.Run(L)
	L.DoString(checker_code)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/xlvector/caspercloud"
	_ "github.com/xlvector/caspercloud/ci"
	"golang.org/x/net/websocket"

	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"runtime"
)

var health bool

func init() {
	health = true
}

func HandleHealth(w http.ResponseWriter, req *http.Request) {
	if health {
		fmt.Fprint(w, "yes")
	} else {
		http.Error(w, "no", http.StatusNotFound)
	}
}

func HandleStart(w http.ResponseWriter, req *http.Request) {
	health = true
	fmt.Fprint(w, "ok")
}

func HandleShutdown(w http.ResponseWriter, req *http.Request) {
	health = false
	fmt.Fprint(w, "ok")
}

func main() {
	runtime.GOMAXPROCS(6)
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	port := flag.String("port", "8000", "port number")
	host := flag.String("host", "127.0.0.1", "host")
	flag.Parse()

	service := caspercloud.NewCasperServer(*host)
	http.Handle("/submit", service)
	http.HandleFunc("/start", HandleStart)
	http.HandleFunc("/shutdown", HandleShutdown)
	http.HandleFunc("/health", HandleHealth)
	http.Handle("/ws/submit", websocket.Handler(service.ServeWebSocket))
	http.Handle("/images/",
		http.StripPrefix("/images/",
			http.FileServer(http.Dir("./images"))))
	http.Handle("/site/",
		http.StripPrefix("/site/", http.FileServer(http.Dir("./site"))))
	l, e := net.Listen("tcp", ":"+*port)
	if e != nil {
		log.Fatal("listen error:", e)
	}
	http.Serve(l, nil)
}
<commit_msg>fix conflict<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/xlvector/caspercloud"
	_ "github.com/xlvector/caspercloud/ci"
	"golang.org/x/net/websocket"
	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"runtime"
)

var health bool

func init() {
	health = true
}

func HandleHealth(w http.ResponseWriter, req *http.Request) {
	if health {
		fmt.Fprint(w, "yes")
	} else {
		http.Error(w, "no", http.StatusNotFound)
	}
}

func HandleStart(w http.ResponseWriter, req *http.Request) {
	health = true
	fmt.Fprint(w, "ok")
}

func HandleShutdown(w http.ResponseWriter, req *http.Request) {
	health = false
	fmt.Fprint(w, "ok")
}

func main() {
	runtime.GOMAXPROCS(6)
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	port := flag.String("port", "8000", "port number")
	host := flag.String("host", "127.0.0.1", "host")
	flag.Parse()

	service := caspercloud.NewCasperServer(*host)
	http.Handle("/submit", service)
	http.HandleFunc("/start", HandleStart)
	http.HandleFunc("/shutdown", HandleShutdown)
	http.HandleFunc("/health", HandleHealth)
	http.Handle("/ws/submit", websocket.Handler(service.ServeWebSocket))
	http.Handle("/images/",
		http.StripPrefix("/images/",
			http.FileServer(http.Dir("./images"))))
	http.Handle("/site/",
		http.StripPrefix("/site/",
			http.FileServer(http.Dir("./site"))))
	l, e := net.Listen("tcp", ":"+*port)
	if e != nil {
		log.Fatal("listen error:", e)
	}
	http.Serve(l, nil)
}
<|endoftext|>


<commit_before>package cell_test

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

	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/pivotal-golang/archiver/compressor"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
	"github.com/tedsuo/ifrit/grouper"
	"golang.org/x/crypto/ssh"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("SSH", func() {
	verifySSH := func(address, processGuid string, index int) {
		Eventually(
			helpers.LRPInstanceStatePoller(receptorClient, processGuid, index, nil),
		).Should(Equal(receptor.ActualLRPStateRunning))

		clientConfig := &ssh.ClientConfig{
			User: fmt.Sprintf("diego:%s/%d", processGuid, index),
			Auth: []ssh.AuthMethod{ssh.Password("")},
		}

		client, err := ssh.Dial("tcp", address, clientConfig)
		Ω(err).ShouldNot(HaveOccurred())

		session, err := client.NewSession()
		Ω(err).ShouldNot(HaveOccurred())

		output, err := session.Output("/usr/bin/env")
		Ω(err).ShouldNot(HaveOccurred())

		Ω(string(output)).Should(ContainSubstring("USER=vcap"))
	}

	var (
		processGuid         string
		fileServerStaticDir string

		runtime      ifrit.Process
		sshdFileName string
		lrp          receptor.DesiredLRPCreateRequest
		sshdArgs     []string
		address      string
	)

	BeforeEach(func() {
		sshdFileName = "sshd.tgz"
		processGuid = helpers.GenerateGuid()
		address = componentMaker.Addresses.SSHProxy
		sshdArgs = []string{
			"-hostKey=" + componentMaker.SshConfig.HostKey,
			"-authorizedKey=" + componentMaker.SshConfig.AuthorizedKey,
		}

		var fileServer ifrit.Runner
		fileServer, fileServerStaticDir = componentMaker.FileServer()
		runtime = ginkgomon.Invoke(grouper.NewParallel(os.Kill, grouper.Members{
			{"router", componentMaker.Router()},
			{"file-server", fileServer},
			{"exec", componentMaker.Executor()},
			{"rep", componentMaker.Rep()},
			{"converger", componentMaker.Converger()},
			{"auctioneer", componentMaker.Auctioneer()},
			{"route-emitter", componentMaker.RouteEmitter()},
			{"ssh-proxy", componentMaker.SSHProxy()},
		}))

		tgCompressor := compressor.NewTgz()
		err := tgCompressor.Compress(componentMaker.Artifacts.Executables["sshd"], filepath.Join(fileServerStaticDir, sshdFileName))
		Ω(err).ShouldNot(HaveOccurred())
	})

	AfterEach(func() {
		helpers.StopProcesses(runtime)
	})

	JustBeforeEach(func() {
		lrp = receptor.DesiredLRPCreateRequest{
			ProcessGuid: processGuid,
			Domain:      "inigo",
			Instances:   2,
			Setup: &models.SerialAction{
				Actions: []models.Action{
					&models.DownloadAction{
						Artifact: "sshd",
						From:     fmt.Sprintf("http://%s/v1/static/%s", componentMaker.Addresses.FileServer, sshdFileName),
						To:       "/tmp",
						CacheKey: "sshd",
					},
				},
			},
			Action: &models.RunAction{
				Path: "/tmp/sshd",
				Args: append([]string{
					"-address=0.0.0.0:2222",
				}, sshdArgs...),
			},
			Monitor: &models.RunAction{
				Path: "nc",
				Args: []string{"-z", "127.0.0.1", "2222"},
			},
			StartTimeout: 60,
			RootFS:       "preloaded:" + helpers.PreloadedStacks[0],
			MemoryMB:     128,
			DiskMB:       128,
			Ports:        []uint16{2222},
		}

		err := receptorClient.CreateDesiredLRP(lrp)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(func() []receptor.ActualLRPResponse {
			lrps, err := receptorClient.ActualLRPsByProcessGuid(processGuid)
			Ω(err).ShouldNot(HaveOccurred())

			return lrps
		}).Should(HaveLen(2))
	})

	Context("when valid processguid and index are used as part of username", func() {

		It("can ssh to appropriate app instance container", func() {
			verifySSH(address, processGuid, 0)
			verifySSH(address, processGuid, 1)
		})

		Context("when invalid password is used", func() {
			var clientConfig *ssh.ClientConfig

			BeforeEach(func() {
				clientConfig = &ssh.ClientConfig{
					User: "diego:" + processGuid + "/0",
					Auth: []ssh.AuthMethod{ssh.Password("invalid:password")},
				}
			})

			It("returns an error", func() {
				Eventually(
					helpers.LRPInstanceStatePoller(receptorClient, processGuid, 0, nil),
				).Should(Equal(receptor.ActualLRPStateRunning))

				_, err := ssh.Dial("tcp", address, clientConfig)
				Ω(err).Should(HaveOccurred())
			})

		})

	})

	Context("when non-existent index is used as part of username", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "diego:" + processGuid + "/3",
				Auth: []ssh.AuthMethod{ssh.Password("")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})

	Context("when non-existent process guid is used as part of username", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "diego:not-existing-process-guid/0",
				Auth: []ssh.AuthMethod{ssh.Password("")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})

	Context("when invalid username format is used", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "vcap",
				Auth: []ssh.AuthMethod{ssh.Password("some-password")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})
})
<commit_msg>Test ssh local port forwarding<commit_after>package cell_test

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

	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/pivotal-golang/archiver/compressor"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
	"github.com/tedsuo/ifrit/grouper"
	"golang.org/x/crypto/ssh"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("SSH", func() {
	verifySSH := func(address, processGuid string, index int) {
		clientConfig := &ssh.ClientConfig{
			User: fmt.Sprintf("diego:%s/%d", processGuid, index),
			Auth: []ssh.AuthMethod{ssh.Password("")},
		}

		client, err := ssh.Dial("tcp", address, clientConfig)
		Ω(err).ShouldNot(HaveOccurred())

		session, err := client.NewSession()
		Ω(err).ShouldNot(HaveOccurred())

		output, err := session.Output("/usr/bin/env")
		Ω(err).ShouldNot(HaveOccurred())

		Ω(string(output)).Should(ContainSubstring("USER=vcap"))
	}

	var (
		processGuid         string
		fileServerStaticDir string

		runtime      ifrit.Process
		sshdFileName string
		lrp          receptor.DesiredLRPCreateRequest
		sshdArgs     []string
		address      string
	)

	BeforeEach(func() {
		sshdFileName = "sshd.tgz"
		processGuid = helpers.GenerateGuid()
		address = componentMaker.Addresses.SSHProxy
		sshdArgs = []string{
			"-hostKey=" + componentMaker.SshConfig.HostKey,
			"-authorizedKey=" + componentMaker.SshConfig.AuthorizedKey,
		}

		var fileServer ifrit.Runner
		fileServer, fileServerStaticDir = componentMaker.FileServer()
		runtime = ginkgomon.Invoke(grouper.NewParallel(os.Kill, grouper.Members{
			{"router", componentMaker.Router()},
			{"file-server", fileServer},
			{"exec", componentMaker.Executor()},
			{"rep", componentMaker.Rep()},
			{"converger", componentMaker.Converger()},
			{"auctioneer", componentMaker.Auctioneer()},
			{"route-emitter", componentMaker.RouteEmitter()},
			{"ssh-proxy", componentMaker.SSHProxy()},
		}))

		tgCompressor := compressor.NewTgz()
		err := tgCompressor.Compress(componentMaker.Artifacts.Executables["sshd"], filepath.Join(fileServerStaticDir, sshdFileName))
		Ω(err).ShouldNot(HaveOccurred())
	})

	AfterEach(func() {
		helpers.StopProcesses(runtime)
	})

	JustBeforeEach(func() {
		lrp = receptor.DesiredLRPCreateRequest{
			ProcessGuid: processGuid,
			Domain:      "inigo",
			Instances:   2,
			Setup: &models.SerialAction{
				Actions: []models.Action{
					&models.DownloadAction{
						Artifact: "sshd",
						From:     fmt.Sprintf("http://%s/v1/static/%s", componentMaker.Addresses.FileServer, sshdFileName),
						To:       "/tmp",
						CacheKey: "sshd",
					},
				},
			},
			Action: &models.ParallelAction{
				Actions: []models.Action{
					&models.RunAction{
						Path: "/tmp/sshd",
						Args: append([]string{
							"-address=0.0.0.0:2222",
						}, sshdArgs...),
					},
					&models.RunAction{
						Path: "bash",
						Args: []string{"-c", `while true; do echo "sup dawg" | nc -l localhost 9999; done`},
					},
				},
			},
			Monitor: &models.RunAction{
				Path: "nc",
				Args: []string{"-z", "127.0.0.1", "2222"},
			},
			StartTimeout: 60,
			RootFS:       "preloaded:" + helpers.PreloadedStacks[0],
			MemoryMB:     128,
			DiskMB:       128,
			Ports:        []uint16{2222},
		}

		err := receptorClient.CreateDesiredLRP(lrp)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(func() []receptor.ActualLRPResponse {
			lrps, err := receptorClient.ActualLRPsByProcessGuid(processGuid)
			Ω(err).ShouldNot(HaveOccurred())

			return lrps
		}).Should(HaveLen(2))

		Eventually(
			helpers.LRPInstanceStatePoller(receptorClient, processGuid, 0, nil),
		).Should(Equal(receptor.ActualLRPStateRunning))

		Eventually(
			helpers.LRPInstanceStatePoller(receptorClient, processGuid, 1, nil),
		).Should(Equal(receptor.ActualLRPStateRunning))
	})

	Context("when valid processguid and index are used as part of username", func() {
		It("can ssh to appropriate app instance container", func() {
			verifySSH(address, processGuid, 0)
			verifySSH(address, processGuid, 1)
		})

		It("supports local port fowarding", func() {
			clientConfig := &ssh.ClientConfig{
				User: fmt.Sprintf("diego:%s/%d", processGuid, 0),
				Auth: []ssh.AuthMethod{ssh.Password("")},
			}

			client, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).ShouldNot(HaveOccurred())

			lconn, err := client.Dial("tcp", "localhost:9999")
			Ω(err).ShouldNot(HaveOccurred())

			reader := bufio.NewReader(lconn)
			line, err := reader.ReadString('\n')
			Ω(err).ShouldNot(HaveOccurred())
			Ω(line).Should(ContainSubstring("sup dawg"))
		})

		Context("when invalid password is used", func() {
			var clientConfig *ssh.ClientConfig

			BeforeEach(func() {
				clientConfig = &ssh.ClientConfig{
					User: "diego:" + processGuid + "/0",
					Auth: []ssh.AuthMethod{ssh.Password("invalid:password")},
				}
			})

			It("returns an error", func() {
				Eventually(
					helpers.LRPInstanceStatePoller(receptorClient, processGuid, 0, nil),
				).Should(Equal(receptor.ActualLRPStateRunning))

				_, err := ssh.Dial("tcp", address, clientConfig)
				Ω(err).Should(HaveOccurred())
			})
		})
	})

	Context("when non-existent index is used as part of username", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "diego:" + processGuid + "/3",
				Auth: []ssh.AuthMethod{ssh.Password("")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})

	Context("when non-existent process guid is used as part of username", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "diego:not-existing-process-guid/0",
				Auth: []ssh.AuthMethod{ssh.Password("")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})

	Context("when invalid username format is used", func() {
		var clientConfig *ssh.ClientConfig

		BeforeEach(func() {
			clientConfig = &ssh.ClientConfig{
				User: "vcap",
				Auth: []ssh.AuthMethod{ssh.Password("some-password")},
			}
		})

		It("returns an error", func() {
			_, err := ssh.Dial("tcp", address, clientConfig)
			Ω(err).Should(HaveOccurred())
		})
	})
})
<|endoftext|>


<commit_before>package influx

import (
	"encoding/json"
	"sync"
	"time"

	"github.com/funkygao/gafka/cmd/kguard/monitor"
	"github.com/funkygao/gafka/zk"
	log "github.com/funkygao/log4go"
	"github.com/influxdata/influxdb/client/v2"
	"github.com/rcrowley/go-metrics"
)

func init() {
	monitor.RegisterWatcher("influx.query", func() monitor.Watcher {
		return &WatchInfluxDB{
			Tick: time.Minute,
		}
	})
}

// WatchInfluxDB continuously query InfluxDB for major metrics.
//
// kateway itself will report metrics to influxdb, but there are
// several kateway instances in a cluster, we need kguard to aggregate them.
type WatchInfluxDB struct {
	Zkzone *zk.ZkZone
	Stop   <-chan struct{}
	Tick   time.Duration
	Wg     *sync.WaitGroup

	addr string
	db   string
	cli  client.Client
}

func (this *WatchInfluxDB) Init(ctx monitor.Context) {
	this.Zkzone = ctx.ZkZone()
	this.Stop = ctx.StopChan()
	this.Wg = ctx.WaitGroup()
	this.addr = ctx.InfluxAddr()
	this.db = ctx.InfluxDB()
}

func (this *WatchInfluxDB) Run() {
	defer this.Wg.Done()

	if this.addr == "" || this.db == "" {
		log.Warn("empty addr or db, quit...")
		return
	}

	ticker := time.NewTicker(this.Tick)
	defer ticker.Stop()

	// SELECT mean("p99") FROM "pub.latency.histogram" WHERE $timeFilter GROUP BY time(10s)
	// DB: pubsub
	pubLatency := metrics.NewRegisteredGauge("_pub.latency.99", nil) // private metric name

	for {
		select {
		case <-this.Stop:
			log.Info("influx.query stopped")
			return

		case <-ticker.C:
			p99, err := this.pubLatency()
			if err != nil {
				log.Error(err.Error())
			} else {
				pubLatency.Update(int64(p99))
			}
		}
	}
}

func (this *WatchInfluxDB) pubLatency() (float64, error) {
	res, err := this.queryDB(`SELECT mean("p99") FROM "pub.latency.histogram" where time > now() - 1m`)
	if err != nil {
		return 0, err
	}

	p99 := res[0].Series[0].Values[0][1].(json.Number) // values[0][0] is "time"
	return p99.Float64()
}

// queryDB convenience function to query the database
func (this *WatchInfluxDB) queryDB(cmd string) (res []client.Result, err error) {
	if this.cli == nil {
		this.cli, err = client.NewHTTPClient(client.HTTPConfig{
			Addr:     this.addr,
			Username: "",
			Password: "",
		})
		if err != nil {
			return
		}
	}

	q := client.Query{
		Command:  cmd,
		Database: this.db,
	}
	if response, err := this.cli.Query(q); err == nil {
		if response.Error() != nil {
			return res, response.Error()
		}
		res = response.Results
	} else {
		return res, err
	}

	return res, nil
}
<commit_msg>for historical mistakes, use a magic number for now: FIXME latter<commit_after>package influx

import (
	"encoding/json"
	"sync"
	"time"

	"github.com/funkygao/gafka/cmd/kguard/monitor"
	"github.com/funkygao/gafka/zk"
	log "github.com/funkygao/log4go"
	"github.com/influxdata/influxdb/client/v2"
	"github.com/rcrowley/go-metrics"
)

func init() {
	monitor.RegisterWatcher("influx.query", func() monitor.Watcher {
		return &WatchInfluxDB{
			Tick: time.Minute,
		}
	})
}

// WatchInfluxDB continuously query InfluxDB for major metrics.
//
// kateway itself will report metrics to influxdb, but there are
// several kateway instances in a cluster, we need kguard to aggregate them.
type WatchInfluxDB struct {
	Zkzone *zk.ZkZone
	Stop   <-chan struct{}
	Tick   time.Duration
	Wg     *sync.WaitGroup

	addr string
	db   string
	cli  client.Client
}

func (this *WatchInfluxDB) Init(ctx monitor.Context) {
	this.Zkzone = ctx.ZkZone()
	this.Stop = ctx.StopChan()
	this.Wg = ctx.WaitGroup()
	this.addr = ctx.InfluxAddr()
	this.db = ctx.InfluxDB()
}

func (this *WatchInfluxDB) Run() {
	defer this.Wg.Done()

	if this.addr == "" || this.db == "" {
		log.Warn("empty addr or db, quit...")
		return
	}

	ticker := time.NewTicker(this.Tick)
	defer ticker.Stop()

	// SELECT mean("p99") FROM "pub.latency.histogram" WHERE $timeFilter GROUP BY time(10s)
	// DB: pubsub
	pubLatency := metrics.NewRegisteredGauge("_pub.latency.99", nil) // private metric name

	for {
		select {
		case <-this.Stop:
			log.Info("influx.query stopped")
			return

		case <-ticker.C:
			p99, err := this.pubLatency()
			if err != nil {
				log.Error(err.Error())
			} else {
				pubLatency.Update(int64(p99))
			}
		}
	}
}

func (this *WatchInfluxDB) pubLatency() (float64, error) {
	res, err := this.queryDB(`SELECT mean("p99") FROM "pub.latency.histogram" where time > now() - 1m`)
	if err != nil {
		return 0, err
	}

	p99 := res[0].Series[0].Values[0][1].(json.Number) // values[0][0] is "time"
	return p99.Float64()
}

// queryDB convenience function to query the database
func (this *WatchInfluxDB) queryDB(cmd string) (res []client.Result, err error) {
	if this.cli == nil {
		this.cli, err = client.NewHTTPClient(client.HTTPConfig{
			Addr:     this.addr,
			Username: "",
			Password: "",
		})
		if err != nil {
			return
		}
	}

	q := client.Query{
		Command:  cmd,
		Database: "pubsub", // FIXME for historical mistakes, we are using another db, not this.db
	}
	if response, err := this.cli.Query(q); err == nil {
		if response.Error() != nil {
			return res, response.Error()
		}
		res = response.Results
	} else {
		return res, err
	}

	return res, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/spf13/cobra"
)

var (
	completionLong = `Output shell completion code for the specified shell.
The shell code must be evaluated to provide interactive completions
of openshift-install commands.

For examples of loading/evaluating the completions see:
  openshift-install completion bash --help`

	completionExampleBash = `  # Installing bash completion on macOS using homebrew
  ## If running Bash 3.2 included with macOS
      brew install bash-completion
  ## or, if running Bash 4.1+
      brew install bash-completion@2
  ## If you've installed via other means, you may need add the completion to your completion directory
      openshift-install completion bash > $(brew --prefix)/etc/bash_completion.d/openshift-install

  # Installing bash completion on Linux
  ## Load the openshift-install completion code for bash into the current shell
      source <(openshift-install completion bash)
  ## Write bash completion code to a file and source if from .bash_profile
      openshift-install completion bash > ~/.openshift-install/completion.bash.inc
      printf "
        # Kubectl shell completion
        source '$HOME/.openshift-install/completion.bash.inc'
        " >> $HOME/.bash_profile
      source $HOME/.bash_profile`

	completionExampleZsh = `# Load the openshift-install completion code for zsh[1] into the current shell
      source <(openshift-install completion zsh)
  # Set the openshift-install completion code for zsh[1] to autoload on startup
      openshift-install completion zsh > "${fpath[1]}/_openshift-install"`
)

func newCompletionCmd() *cobra.Command {
	completionCmd := &cobra.Command{
		Use:   "completion",
		Short: "Outputs shell completions for the openshift-install command",
		Long:  completionLong,
	}

	bashCompletionCmd := &cobra.Command{
		Use:     "bash",
		Short:   "Outputs the bash shell completions",
		Example: completionExampleBash,
		RunE: func(cmd *cobra.Command, _ []string) error {
			return cmd.Root().GenBashCompletion(os.Stdout)
		},
	}
	completionCmd.AddCommand(bashCompletionCmd)

	// The zsh completions didn't work for crawford, so commenting them out
	//zshCompletionCmd := &cobra.Command{
	//Use:     "zsh",
	//Short:   "Outputs the zsh shell completions",
	//Example: completionExampleZsh,
	//RunE: func(cmd *cobra.Command, _ []string) error {
	//return cmd.Root().GenZshCompletion(os.Stdout)
	//},
	//}
	//completionCmd.AddCommand(zshCompletionCmd)

	return completionCmd
}
<commit_msg>Fix typo<commit_after>package main

import (
	"os"

	"github.com/spf13/cobra"
)

var (
	completionLong = `Output shell completion code for the specified shell.
The shell code must be evaluated to provide interactive completions
of openshift-install commands.

For examples of loading/evaluating the completions see:
  openshift-install completion bash --help`

	completionExampleBash = `  # Installing bash completion on macOS using homebrew
  ## If running Bash 3.2 included with macOS
      brew install bash-completion
  ## or, if running Bash 4.1+
      brew install bash-completion@2
  ## If you've installed via other means, you may need add the completion to your completion directory
      openshift-install completion bash > $(brew --prefix)/etc/bash_completion.d/openshift-install

  # Installing bash completion on Linux
  ## Load the openshift-install completion code for bash into the current shell
      source <(openshift-install completion bash)
  ## Write bash completion code to a file and source it from .bash_profile
      openshift-install completion bash > ~/.openshift-install/completion.bash.inc
      printf "
        # Kubectl shell completion
        source '$HOME/.openshift-install/completion.bash.inc'
        " >> $HOME/.bash_profile
      source $HOME/.bash_profile`

	completionExampleZsh = `# Load the openshift-install completion code for zsh[1] into the current shell
      source <(openshift-install completion zsh)
  # Set the openshift-install completion code for zsh[1] to autoload on startup
      openshift-install completion zsh > "${fpath[1]}/_openshift-install"`
)

func newCompletionCmd() *cobra.Command {
	completionCmd := &cobra.Command{
		Use:   "completion",
		Short: "Outputs shell completions for the openshift-install command",
		Long:  completionLong,
	}

	bashCompletionCmd := &cobra.Command{
		Use:     "bash",
		Short:   "Outputs the bash shell completions",
		Example: completionExampleBash,
		RunE: func(cmd *cobra.Command, _ []string) error {
			return cmd.Root().GenBashCompletion(os.Stdout)
		},
	}
	completionCmd.AddCommand(bashCompletionCmd)

	// The zsh completions didn't work for crawford, so commenting them out
	//zshCompletionCmd := &cobra.Command{
	//Use:     "zsh",
	//Short:   "Outputs the zsh shell completions",
	//Example: completionExampleZsh,
	//RunE: func(cmd *cobra.Command, _ []string) error {
	//return cmd.Root().GenZshCompletion(os.Stdout)
	//},
	//}
	//completionCmd.AddCommand(zshCompletionCmd)

	return completionCmd
}
<|endoftext|>


<commit_before>package cgroups

type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods,omitempty"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time,omitempty"`
}

// All CPU stats are aggregate since container inception.
type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage,omitempty"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage,omitempty"`
	ThrottlingData ThrottlingData `json:"throlling_data,omitempty"`
}

type MemoryStats struct {
	// current res_counter usage for memory
	Usage uint64 `json:"usage,omitempty"`
	// maximum usage ever recorded.
	MaxUsage uint64 `json:"max_usage,omitempty"`
	// TODO(vishh): Export these as stronger types.
	// all the stats exported via memory.stat.
	Stats map[string]uint64 `json:"stats,omitempty"`
	// number of times memory usage hits limits.
	Failcnt uint64 `json:"failcnt"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major,omitempty"`
	Minor uint64 `json:"minor,omitempty"`
	Op    string `json:"op,omitempty"`
	Value uint64 `json:"value,omitempty"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive,omitempty"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive,omitempty"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive,omitempty"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive,omitempty"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive,omitempty"`
}

type Stats struct {
	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}

func NewStats() *Stats {
	memoryStats := MemoryStats{Stats: make(map[string]uint64)}
	return &Stats{MemoryStats: memoryStats}
}
<commit_msg>Fix typo in json tag<commit_after>package cgroups

type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods,omitempty"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time,omitempty"`
}

// All CPU stats are aggregate since container inception.
type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage,omitempty"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage,omitempty"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	// current res_counter usage for memory
	Usage uint64 `json:"usage,omitempty"`
	// maximum usage ever recorded.
	MaxUsage uint64 `json:"max_usage,omitempty"`
	// TODO(vishh): Export these as stronger types.
	// all the stats exported via memory.stat.
	Stats map[string]uint64 `json:"stats,omitempty"`
	// number of times memory usage hits limits.
	Failcnt uint64 `json:"failcnt"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major,omitempty"`
	Minor uint64 `json:"minor,omitempty"`
	Op    string `json:"op,omitempty"`
	Value uint64 `json:"value,omitempty"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive,omitempty"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive,omitempty"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive,omitempty"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive,omitempty"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive,omitempty"`
}

type Stats struct {
	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}

func NewStats() *Stats {
	memoryStats := MemoryStats{Stats: make(map[string]uint64)}
	return &Stats{MemoryStats: memoryStats}
}
<|endoftext|>


<commit_before>package setting

//import "github.com/go-ini/ini"

var (
	Connection *Connection
)

type Connection struct {
	Host string
	Username string
	Password string
	Database string
	Schema string
}

func (c *Connection) GetConnectionSettings() Connection {
	return &Connection{
		Host: "localhost",
		Schema: "public",
		Database: "goclerk",
	}
}<commit_msg>Fix connection settings<commit_after>package setting

//import "github.com/go-ini/ini"

var (
	Connection connection
)

type connection struct {
	Host string
	Username string
	Password string
	Database string
	Schema string
}

func GetConnectionSettings() *connection {
	c := &connection{
		Host: "localhost",
		Schema: "public",
		Database: "goclerk",
	}

	return c
}<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	homedir "github.com/mitchellh/go-homedir"
)

type iobeamConfig struct {
	Name string `json:"profile"`
}

const (
	// CLIVersion is the version of the CLI.
	CLIVersion = "0.6.3"
	// DefaultApiServer is the default iobeam server.
	DefaultApiServer = "https://api.iobeam.com"

	pathSeparator   = string(os.PathSeparator)
	dotDirName      = ".iobeam"
	defaultConfig   = "profile"
	profileFileName = "profile.config"
)

// InitConfig sets up the default config.
func InitConfig() (*iobeamConfig, error) {
	c := &iobeamConfig{
		Name: "default",
	}
	err := c.save()
	if err != nil {
		return nil, err
	}
	return c, nil
}

func getDotDir() string {
	homeDir, err := homedir.Dir()

	if err != nil {
		// We cannot gracefully use the temp directory with profiles.
		panic(err)
	}

	return homeDir + pathSeparator + dotDirName
}

func defaultConfigPath() string {
	return getDotDir() + pathSeparator + defaultConfig
}

func makeAllOnPath(path string) error {
	err := os.MkdirAll(path, 0700)
	if err != nil {
		return err
	}
	return nil
}

func saveJson(path string, obj interface{}) error {
	_ = os.Remove(path) // error only if it does not exist, ignore.

	file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewEncoder(file).Encode(obj)
}

func readJson(path string, obj interface{}) error {
	file, err := os.Open(path)

	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewDecoder(file).Decode(obj)
}

// save writes the config to disk in the user's .iobeam directory.
func (c *iobeamConfig) save() error {
	err := makeAllOnPath(getDotDir())
	if err != nil {
		return err
	}
	return saveJson(defaultConfigPath(), c)
}

func (c *iobeamConfig) read(path string) error {
	return readJson(path, c)
}

func readConfig(path string) (*iobeamConfig, error) {
	c := new(iobeamConfig)

	err := c.read(path)
	if err != nil {
		return nil, err
	}

	return c, err
}

func ReadDefaultConfig() (*iobeamConfig, error) {
	return readConfig(defaultConfigPath())
}

// Profile represents a CLI profile, which is similar to a workspace
// that tracks active user, project, and other metadata.
type Profile struct {
	Name            string `json:"-"`
	Server          string `json:"server"`
	ActiveProject   uint64 `json:"active_project"`
	ActiveUser      uint64 `json:"active_user"`
	ActiveUserEmail string `json:"activer_user_email"`
	// TODO: Don't export active fields.
}

// InitProfile creates a new profile on the system named 'name'.
func InitProfile(name string) (*Profile, error) {
	return InitProfileWithServer(name, DefaultApiServer)
}

// InitProfileWithServer creates a new profile on the system named
// 'name' and uses 'server' for the API server.
func InitProfileWithServer(name, server string) (*Profile, error) {
	p := &Profile{
		Name:          name,
		Server:        server,
		ActiveProject: 0,
		ActiveUser:    0,
	}
	err := p.save()
	if err != nil {
		return nil, err
	}
	return p, nil
}

func baseProfilePath(name string) string {
	return getDotDir() + pathSeparator + name
}

func profilePath(name string) string {
	// e.x. ~user/.iobeam/default/profile.config
	return baseProfilePath(name) + pathSeparator + profileFileName
}

func (p *Profile) save() error {
	err := makeAllOnPath(p.GetDir())
	if err != nil {
		return err
	}
	return saveJson(profilePath(p.Name), p)
}

func (p *Profile) read() error {
	return readJson(p.GetFile(), p)
}

// GetDir returns the path to where p's data is stored.
func (p *Profile) GetDir() string {
	return baseProfilePath(p.Name)
}

// GetFile returns the path to where p's metadata is stored.
func (p *Profile) GetFile() string {
	return profilePath(p.Name)
}

// UpdateActiveUser changes the active user id and email of p.
func (p *Profile) UpdateActiveUser(uid uint64, email string) error {
	p.ActiveUser = uid
	p.ActiveUserEmail = email
	return p.save()
}

// UpdateActiveProject changes the active project id of p.
func (p *Profile) UpdateActiveProject(pid uint64) error {
	p.ActiveProject = pid
	return p.save()
}

// ReadProfile attempts to read and create a *Profile object.
func ReadProfile(name string) (*Profile, error) {
	p := new(Profile)
	p.Name = name

	err := p.read()
	if err != nil {
		return nil, err
	}

	return p, nil
}

// GetProfileList returns a list of available profiles.
func GetProfileList() ([]string, error) {
	files, err := ioutil.ReadDir(getDotDir())
	if err != nil {
		return nil, err
	}

	var list []string
	for _, f := range files {
		if f.IsDir() {
			list = append(list, f.Name())
		}
	}

	return list, nil
}

// SwitchProfile attempts to change the active profile.
func SwitchProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	}

	if err == nil {
		c := &iobeamConfig{
			Name: name,
		}
		err = c.save()
	}
	return err
}

// DeleteProfile removes a profile from the system.
func DeleteProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if err == nil {
		return os.RemoveAll(path)
	} else if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	} else {
		return err
	}
}
<commit_msg>release: v0.7.0<commit_after>package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	homedir "github.com/mitchellh/go-homedir"
)

type iobeamConfig struct {
	Name string `json:"profile"`
}

const (
	// CLIVersion is the version of the CLI.
	CLIVersion = "0.7.0"
	// DefaultApiServer is the default iobeam server.
	DefaultApiServer = "https://api.iobeam.com"

	pathSeparator   = string(os.PathSeparator)
	dotDirName      = ".iobeam"
	defaultConfig   = "profile"
	profileFileName = "profile.config"
)

// InitConfig sets up the default config.
func InitConfig() (*iobeamConfig, error) {
	c := &iobeamConfig{
		Name: "default",
	}
	err := c.save()
	if err != nil {
		return nil, err
	}
	return c, nil
}

func getDotDir() string {
	homeDir, err := homedir.Dir()

	if err != nil {
		// We cannot gracefully use the temp directory with profiles.
		panic(err)
	}

	return homeDir + pathSeparator + dotDirName
}

func defaultConfigPath() string {
	return getDotDir() + pathSeparator + defaultConfig
}

func makeAllOnPath(path string) error {
	err := os.MkdirAll(path, 0700)
	if err != nil {
		return err
	}
	return nil
}

func saveJson(path string, obj interface{}) error {
	_ = os.Remove(path) // error only if it does not exist, ignore.

	file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewEncoder(file).Encode(obj)
}

func readJson(path string, obj interface{}) error {
	file, err := os.Open(path)

	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewDecoder(file).Decode(obj)
}

// save writes the config to disk in the user's .iobeam directory.
func (c *iobeamConfig) save() error {
	err := makeAllOnPath(getDotDir())
	if err != nil {
		return err
	}
	return saveJson(defaultConfigPath(), c)
}

func (c *iobeamConfig) read(path string) error {
	return readJson(path, c)
}

func readConfig(path string) (*iobeamConfig, error) {
	c := new(iobeamConfig)

	err := c.read(path)
	if err != nil {
		return nil, err
	}

	return c, err
}

func ReadDefaultConfig() (*iobeamConfig, error) {
	return readConfig(defaultConfigPath())
}

// Profile represents a CLI profile, which is similar to a workspace
// that tracks active user, project, and other metadata.
type Profile struct {
	Name            string `json:"-"`
	Server          string `json:"server"`
	ActiveProject   uint64 `json:"active_project"`
	ActiveUser      uint64 `json:"active_user"`
	ActiveUserEmail string `json:"activer_user_email"`
	// TODO: Don't export active fields.
}

// InitProfile creates a new profile on the system named 'name'.
func InitProfile(name string) (*Profile, error) {
	return InitProfileWithServer(name, DefaultApiServer)
}

// InitProfileWithServer creates a new profile on the system named
// 'name' and uses 'server' for the API server.
func InitProfileWithServer(name, server string) (*Profile, error) {
	p := &Profile{
		Name:          name,
		Server:        server,
		ActiveProject: 0,
		ActiveUser:    0,
	}
	err := p.save()
	if err != nil {
		return nil, err
	}
	return p, nil
}

func baseProfilePath(name string) string {
	return getDotDir() + pathSeparator + name
}

func profilePath(name string) string {
	// e.x. ~user/.iobeam/default/profile.config
	return baseProfilePath(name) + pathSeparator + profileFileName
}

func (p *Profile) save() error {
	err := makeAllOnPath(p.GetDir())
	if err != nil {
		return err
	}
	return saveJson(profilePath(p.Name), p)
}

func (p *Profile) read() error {
	return readJson(p.GetFile(), p)
}

// GetDir returns the path to where p's data is stored.
func (p *Profile) GetDir() string {
	return baseProfilePath(p.Name)
}

// GetFile returns the path to where p's metadata is stored.
func (p *Profile) GetFile() string {
	return profilePath(p.Name)
}

// UpdateActiveUser changes the active user id and email of p.
func (p *Profile) UpdateActiveUser(uid uint64, email string) error {
	p.ActiveUser = uid
	p.ActiveUserEmail = email
	return p.save()
}

// UpdateActiveProject changes the active project id of p.
func (p *Profile) UpdateActiveProject(pid uint64) error {
	p.ActiveProject = pid
	return p.save()
}

// ReadProfile attempts to read and create a *Profile object.
func ReadProfile(name string) (*Profile, error) {
	p := new(Profile)
	p.Name = name

	err := p.read()
	if err != nil {
		return nil, err
	}

	return p, nil
}

// GetProfileList returns a list of available profiles.
func GetProfileList() ([]string, error) {
	files, err := ioutil.ReadDir(getDotDir())
	if err != nil {
		return nil, err
	}

	var list []string
	for _, f := range files {
		if f.IsDir() {
			list = append(list, f.Name())
		}
	}

	return list, nil
}

// SwitchProfile attempts to change the active profile.
func SwitchProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	}

	if err == nil {
		c := &iobeamConfig{
			Name: name,
		}
		err = c.save()
	}
	return err
}

// DeleteProfile removes a profile from the system.
func DeleteProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if err == nil {
		return os.RemoveAll(path)
	} else if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	} else {
		return err
	}
}
<|endoftext|>


<commit_before>package config

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"

	"gopkg.in/yaml.v2"
)

// 自动加载配置项
type configInfo struct {
	Server   *serverModel   `yaml:"server"`
	Wechat   *wechatModel   `yaml:"wechat"`
	DataBase *dataBaseModel `yaml:"database"`
	MQ       *mqModel       `yaml:"mq"`
	Email    *emailModel    `yaml:"email"`
}

// 服务器配置项
type serverModel struct {
	Mode string `yaml:"mode"` // run mode
	Host string `yaml:"host"` // server host
	Port string `yaml:"port"` // server port
}

// 微信配置项
type wechatModel struct {
	AppID     string `yaml:"appID"`
	AppSecret string `yaml:"appSecret"`
}

// 数据库配置项
type dataBaseModel struct {
	Dburl    string `yaml:"dburl"`
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
	Dbname   string `yaml:"dbname"`
}

// 消息队列配置项
type mqModel struct {
	MqUrl    string `yaml:"mqurl"`
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
}

// 邮箱服务配置
type emailModel struct {
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	User     string `yaml:"user"`
	Password string `yaml:"password"`
}

//
var Config configInfo

// 加载配置
func loadConfigInformation(fPath string) error {
	filePath := path.Join(fPath, "config.yaml")
	configData, err := ioutil.ReadFile(filePath)
	if err != nil {
		fmt.Printf(" config file read failed: %s", err)
		return err
	}
	err = yaml.Unmarshal(configData, &Config)
	if err != nil {
		fmt.Printf(" config parse failed: %s", err)
		return err
	}
	return nil
}

func init() {
	LoadConfig()
}

func LoadConfig() {
	var err error
	fPath, _ := os.Getwd()
	fPath = path.Join(fPath, "config")
	configPath := flag.String("c", fPath, "config file path")
	flag.Parse()
	err = loadConfigInformation(*configPath)
	// fmt.Printf("%+v\n%+v",Config.Server, Config.Wechat)
	if err != nil {
		panic(err)
		return
	}
}
<commit_msg>新增redis配置<commit_after>package config

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path"

	"gopkg.in/yaml.v2"
)

// 自动加载配置项
type configInfo struct {
	Server   *serverModel   `yaml:"server"`
	Wechat   *wechatModel   `yaml:"wechat"`
	DataBase *dataBaseModel `yaml:"database"`
	Redis    *redisModel    `yaml:"redis"`
	MQ       *mqModel       `yaml:"mq"`
	Email    *emailModel    `yaml:"email"`
}

// 服务器配置项
type serverModel struct {
	Mode string `yaml:"mode"` // run mode
	Host string `yaml:"host"` // server host
	Port string `yaml:"port"` // server port
}

// 微信配置项
type wechatModel struct {
	AppID     string `yaml:"appID"`
	AppSecret string `yaml:"appSecret"`
}

// 数据库配置项
type dataBaseModel struct {
	Dburl    string `yaml:"dburl"`
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
	Dbname   string `yaml:"dbname"`
}

// redis配置项
type redisModel struct {
	redisUrl string `yaml:"redisUrl"`
	Password string `yaml:"password"`
	Db       int    `yaml:"db"`
}

// 消息队列配置项
type mqModel struct {
	MqUrl    string `yaml:"mqurl"`
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
}

// 邮箱服务配置
type emailModel struct {
	Host     string `yaml:"host"`
	Port     string `yaml:"port"`
	User     string `yaml:"user"`
	Password string `yaml:"password"`
}

//
var Config configInfo

// 加载配置
func loadConfigInformation(fPath string) error {
	filePath := path.Join(fPath, "config.yaml")
	configData, err := ioutil.ReadFile(filePath)
	if err != nil {
		log.Printf(" config file read failed: %s", err)
		return err
	}
	err = yaml.Unmarshal(configData, &Config)
	if err != nil {
		log.Printf(" config parse failed: %s", err)
		return err
	}
	return nil
}

func init() {
	LoadConfig()
}

func LoadConfig() {
	var err error
	fPath, _ := os.Getwd()
	fPath = path.Join(fPath, "config")
	configPath := flag.String("c", fPath, "config file path")
	flag.Parse()
	err = loadConfigInformation(*configPath)
	// log.Printf("%+v\n%+v",Config.Server, Config.Wechat)
	if err != nil {
		panic(err)
		return
	}
}
<|endoftext|>