<commit_before>package calendar

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	gcalendar "google.golang.org/api/calendar/v3"
	"sort"
	"log"
)

// helper for extracting calendar data
type calendarItem struct {
	id   string
	name string
}

type ByStart []TimedEvent

func (a ByStart) Len() int           { return len(a) }
func (a ByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByStart) Less(i, j int) bool { return a[i].Start.Unix() < a[j].Start.Unix() }

// FetchToken reaches out to Google OAuth with the clients credentials to get a valid token
// Interactive user action is required here
func FetchToken(jsonKey []byte) (*oauth2.Token, error) {
	config, err := google.ConfigFromJSON(jsonKey, gcalendar.CalendarReadonlyScope)
	if err != nil {
		return nil, err
	}
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
	fmt.Printf("Go to the following link in your browser then type the "+"authorization code: \n%v\n", authURL)

	var code string
	if _, err := fmt.Scan(&code); err != nil {
		return nil, err
	}

	tok, err := config.Exchange(context.TODO(), code)
	if err != nil {
		return nil, err
	}
	return tok, nil
}

// CloseEvent fetches the events from today (or tomorrow if none are there for today)
func GetNextEvents(oauthToken *oauth2.Token, jsonKey []byte, todayCalendarNames []string, allDayCalendarNames [] string) (*NextEvents, error) {
	ctx := context.Background()

	config, err := google.ConfigFromJSON(jsonKey, gcalendar.CalendarReadonlyScope)
	if err != nil {
		return nil, err
	}
	client := config.Client(ctx, oauthToken)

	srv, err := gcalendar.New(client)
	if err != nil {
		return nil, err
	}

	calendars, err := getCalendarIds(srv, todayCalendarNames)
	if err != nil {
		return nil, err
	}
	log.Printf("Calendars: %v", calendars)

	start, midnight, end := getTimeWindow()
	log.Printf("Start: %v Midnight: %v End: %v",start.Format(time.RFC3339), midnight, end)

	todayEvents, err := extractEventsForCalendars(srv, calendars, start, midnight)
	if err != nil {
		return nil, err
	}
	var tomorrowEvents *[]TimedEvent
	if len(*todayEvents) == 0 {
		todayEvents = nil
		tomorrowEvents, err = extractEventsForCalendars(srv, calendars, start, end)
		if err != nil {
			return nil, err
		}
	}

	allDayCalendars, err := getCalendarIds(srv, allDayCalendarNames)
	if err != nil {
		return nil, err
	}

	tomorrowAllDayEvents, err := extractAllDayEvents(srv, allDayCalendars, midnight, end)
	if err != nil {
		return nil, err
	}

	return &NextEvents{
		TodayEvents:    todayEvents,
		TomorrowEvents: tomorrowEvents,
		TomorrowAllDayEvents: tomorrowAllDayEvents,
	}, nil
}
func extractAllDayEvents(srv *gcalendar.Service, calendars []calendarItem, start time.Time, end time.Time) (*[]Event, error) {
	ret := []Event{}
	for _, cal := range calendars {
		events, err := getEvents(srv, cal, start, end)
		if err != nil {
			return nil, err
		}

		if len(events.Items) > 0 {
			for _, i := range events.Items {
				// If the DateTime is an empty string the Event is an all-day Event.
				// So only Date is available.
				if i.Start.DateTime == "" {
					event := Event{
						Calendar: cal.name,
						Summary:  i.Summary,
					}
					ret = append(ret, event)
				}
			}
		}
	}
	if len(ret) == 0 {
		return nil, nil
	} else {
		return &ret, nil
	}
}

func extractEventsForCalendars(srv *gcalendar.Service, calendars []calendarItem, start time.Time, end time.Time) (*[]TimedEvent, error) {
	ret := []TimedEvent{}
	for _, cal := range calendars {
		events, err := getEvents(srv, cal, start, end)
		if err != nil {
			return nil, err
		}
		e, err := extractTimedEvents(cal, events)
		if err != nil {
			return nil, err
		}
		ret = append(ret, *e...)
	}
	sort.Sort(ByStart(ret))
	return &ret, nil
}

func extractTimedEvents(cal calendarItem, events *gcalendar.Events) (*[]TimedEvent, error) {
	ret := []TimedEvent{}
	if len(events.Items) > 0 {
		for _, i := range events.Items {
			// If the DateTime is an empty string the Event is an all-day Event.
			// So only Date is available.
			if i.Start.DateTime != "" {
				startTime, err := parseRfc339(i.Start.DateTime)
				if err != nil {
					return nil, err
				}
				endTime, err := parseRfc339(i.End.DateTime)
				if err != nil {
					return nil, err
				}
				event := TimedEvent{
					Start:     startTime,
					End:       endTime,
					Event: Event{
						Calendar: cal.name,
						Summary:  i.Summary,
					},
				}
				ret = append(ret, event)
			}
		}
	}
	return &ret, nil
}

func getEvents(srv *gcalendar.Service, cal calendarItem, start time.Time, end time.Time) (*gcalendar.Events, error) {
	events, err := srv.Events.List(cal.id).ShowDeleted(false).
		SingleEvents(true).TimeMin(start.Format(time.RFC3339)).TimeMax(end.Format(time.RFC3339)).OrderBy("startTime").Do()
	return events, err
}

func getCalendarIds(srv *gcalendar.Service, summaries []string) ([]calendarItem, error) {
	cl, err := srv.CalendarList.List().Do()
	if err != nil {
		return nil, err
	}
	ret := []calendarItem{}

	for _, i := range cl.Items {
		for _, j := range summaries {
			if j == i.Summary {
				ret = append(ret, calendarItem{
					id:   i.Id,
					name: i.Summary,
				})
			}
		}
	}
	return ret, nil
}

func parseRfc339(rfc3339 string) (*time.Time, error) {
	t, err := time.Parse(time.RFC3339, rfc3339)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

// Get the time window for which to fetch events
func getTimeWindow() (time.Time, time.Time, time.Time) {
	start := time.Now()
	year, month, day := start.Date()
	lastMidnight := time.Date(year, month, day, 0, 0, 0, 0, start.Location())
	midnight := lastMidnight.Add(time.Hour * 24)
	end := lastMidnight.Add(2 * time.Hour * 24)
	return start, midnight, end
}
<commit_msg>Fix extraction of tommorrow events<commit_after>package calendar

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	gcalendar "google.golang.org/api/calendar/v3"
	"sort"
	"log"
)

// helper for extracting calendar data
type calendarItem struct {
	id   string
	name string
}

type ByStart []TimedEvent

func (a ByStart) Len() int           { return len(a) }
func (a ByStart) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByStart) Less(i, j int) bool { return a[i].Start.Unix() < a[j].Start.Unix() }

// FetchToken reaches out to Google OAuth with the clients credentials to get a valid token
// Interactive user action is required here
func FetchToken(jsonKey []byte) (*oauth2.Token, error) {
	config, err := google.ConfigFromJSON(jsonKey, gcalendar.CalendarReadonlyScope)
	if err != nil {
		return nil, err
	}
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
	fmt.Printf("Go to the following link in your browser then type the "+"authorization code: \n%v\n", authURL)

	var code string
	if _, err := fmt.Scan(&code); err != nil {
		return nil, err
	}

	tok, err := config.Exchange(context.TODO(), code)
	if err != nil {
		return nil, err
	}
	return tok, nil
}

// CloseEvent fetches the events from today (or tomorrow if none are there for today)
func GetNextEvents(oauthToken *oauth2.Token, jsonKey []byte, todayCalendarNames []string, allDayCalendarNames [] string) (*NextEvents, error) {
	ctx := context.Background()

	config, err := google.ConfigFromJSON(jsonKey, gcalendar.CalendarReadonlyScope)
	if err != nil {
		return nil, err
	}
	client := config.Client(ctx, oauthToken)

	srv, err := gcalendar.New(client)
	if err != nil {
		return nil, err
	}

	calendars, err := getCalendarIds(srv, todayCalendarNames)
	if err != nil {
		return nil, err
	}
	log.Printf("Calendars: %v", calendars)

	start, midnight, end := getTimeWindow()
	log.Printf("Start: %v Midnight: %v End: %v",start.Format(time.RFC3339), midnight, end)

	todayEvents, err := extractEventsForCalendars(srv, calendars, start, midnight)
	if err != nil {
		return nil, err
	}
	var tomorrowEvents *[]TimedEvent
	if len(*todayEvents) == 0 {
		todayEvents = nil
		tomorrowEvents, err = extractEventsForCalendars(srv, calendars, start, end)
		if err != nil {
			return nil, err
		}
		if len(*tomorrowEvents) == 0 {
			tomorrowEvents = nil
		}
	}

	allDayCalendars, err := getCalendarIds(srv, allDayCalendarNames)
	if err != nil {
		return nil, err
	}

	tomorrowAllDayEvents, err := extractAllDayEvents(srv, allDayCalendars, midnight, end)
	if err != nil {
		return nil, err
	}

	return &NextEvents{
		TodayEvents:    todayEvents,
		TomorrowEvents: tomorrowEvents,
		TomorrowAllDayEvents: tomorrowAllDayEvents,
	}, nil
}
func extractAllDayEvents(srv *gcalendar.Service, calendars []calendarItem, start time.Time, end time.Time) (*[]Event, error) {
	ret := []Event{}
	for _, cal := range calendars {
		events, err := getEvents(srv, cal, start, end)
		if err != nil {
			return nil, err
		}

		if len(events.Items) > 0 {
			for _, i := range events.Items {
				// If the DateTime is an empty string the Event is an all-day Event.
				// So only Date is available.
				if i.Start.DateTime == "" {
					event := Event{
						Calendar: cal.name,
						Summary:  i.Summary,
					}
					ret = append(ret, event)
				}
			}
		}
	}
	if len(ret) == 0 {
		return nil, nil
	} else {
		return &ret, nil
	}
}

func extractEventsForCalendars(srv *gcalendar.Service, calendars []calendarItem, start time.Time, end time.Time) (*[]TimedEvent, error) {
	ret := []TimedEvent{}
	for _, cal := range calendars {
		events, err := getEvents(srv, cal, start, end)
		if err != nil {
			return nil, err
		}
		e, err := extractTimedEvents(cal, events)
		if err != nil {
			return nil, err
		}
		ret = append(ret, *e...)
	}
	sort.Sort(ByStart(ret))
	return &ret, nil
}

func extractTimedEvents(cal calendarItem, events *gcalendar.Events) (*[]TimedEvent, error) {
	ret := []TimedEvent{}
	if len(events.Items) > 0 {
		for _, i := range events.Items {
			// If the DateTime is an empty string the Event is an all-day Event.
			// So only Date is available.
			if i.Start.DateTime != "" {
				startTime, err := parseRfc339(i.Start.DateTime)
				if err != nil {
					return nil, err
				}
				endTime, err := parseRfc339(i.End.DateTime)
				if err != nil {
					return nil, err
				}
				event := TimedEvent{
					Start:     startTime,
					End:       endTime,
					Event: Event{
						Calendar: cal.name,
						Summary:  i.Summary,
					},
				}
				ret = append(ret, event)
			}
		}
	}
	return &ret, nil
}

func getEvents(srv *gcalendar.Service, cal calendarItem, start time.Time, end time.Time) (*gcalendar.Events, error) {
	events, err := srv.Events.List(cal.id).ShowDeleted(false).
		SingleEvents(true).TimeMin(start.Format(time.RFC3339)).TimeMax(end.Format(time.RFC3339)).OrderBy("startTime").Do()
	return events, err
}

func getCalendarIds(srv *gcalendar.Service, summaries []string) ([]calendarItem, error) {
	cl, err := srv.CalendarList.List().Do()
	if err != nil {
		return nil, err
	}
	ret := []calendarItem{}

	for _, i := range cl.Items {
		for _, j := range summaries {
			if j == i.Summary {
				ret = append(ret, calendarItem{
					id:   i.Id,
					name: i.Summary,
				})
			}
		}
	}
	return ret, nil
}

func parseRfc339(rfc3339 string) (*time.Time, error) {
	t, err := time.Parse(time.RFC3339, rfc3339)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

// Get the time window for which to fetch events
func getTimeWindow() (time.Time, time.Time, time.Time) {
	start := time.Now()
	year, month, day := start.Date()
	lastMidnight := time.Date(year, month, day, 0, 0, 0, 0, start.Location())
	midnight := lastMidnight.Add(time.Hour * 24)
	end := lastMidnight.Add(2 * time.Hour * 24)
	return start, midnight, end
}
<|endoftext|>


<commit_before>package chkitErrors

import (
	"bytes"
	"fmt"

	"gopkg.in/urfave/cli.v2"
)

type Err string

var (
	_ error          = Err("")
	_ cli.ExitCoder  = Err("")
	_ cli.MultiError = Err("")
	_ ErrMatcher     = Err("")

	_ error          = &Wrapper{}
	_ cli.ExitCoder  = &Wrapper{}
	_ cli.MultiError = &Wrapper{}
	_ ErrMatcher     = &Wrapper{}
)

type ErrMatcher interface {
	error
	Match(...error) bool
}

func (err Err) Error() string {
	return string(err)
}
func (err Err) Errors() []error {
	return []error{err}
}

func (err Err) ExitCode() int {
	return 1
}
func (err Err) Wrap(errs ...error) *Wrapper {
	return Wrap(err, errs...)
}

func (err Err) Match(errs ...error) bool {
	for _, er := range errs {
		switch er := er.(type) {
		case *Wrapper:
			if er.main == err {
				return true
			}
		default:
			if err == er {
				return true
			}
		}
	}
	return false
}

type Wrapper struct {
	main          error
	reasons       []error
	cachedMessage string
}

func Wrap(err error, reasons ...error) *Wrapper {
	return &Wrapper{
		main:    err,
		reasons: reasons,
	}
}

func (wrapper *Wrapper) AddReasons(reasons ...error) *Wrapper {
	for _, reason := range reasons {
		wrapper.reasons = append(wrapper.reasons, reason)
	}
	return wrapper
}

func (wrapper *Wrapper) AddReasonF(f string, vals ...interface{}) *Wrapper {
	return wrapper.AddReasons(fmt.Errorf(f, vals...))
}
func (wrapper *Wrapper) Error() string {
	if wrapper.cachedMessage != "" {
		return wrapper.cachedMessage
	}
	buf := bytes.NewBufferString(wrapper.main.Error())
	if len(wrapper.reasons) > 0 {
		buf.WriteString(": ")
	}
	for i, reason := range wrapper.reasons {
		if i != 0 {
			buf.WriteString(", " + reason.Error())
		} else {
			buf.WriteString(reason.Error())
		}
	}
	wrapper.cachedMessage = buf.String()
	return wrapper.cachedMessage
}

func (wrapper *Wrapper) Match(errs ...error) bool {
	for _, err := range errs {
		if wrapper.main == err {
			return true
		}
	}
	return false
}

func (wrapper *Wrapper) Errors() []error {
	errs := make([]error, len(wrapper.reasons))
	copy(errs, wrapper.reasons)
	return errs
}

func (wrapper *Wrapper) ExitCode() int {
	return 1
}
<commit_msg>add comment method<commit_after>package chkitErrors

import (
	"bytes"
	"fmt"

	"gopkg.in/urfave/cli.v2"
)

type Err string

var (
	_ error          = Err("")
	_ cli.ExitCoder  = Err("")
	_ cli.MultiError = Err("")
	_ ErrMatcher     = Err("")

	_ error          = &Wrapper{}
	_ cli.ExitCoder  = &Wrapper{}
	_ cli.MultiError = &Wrapper{}
	_ ErrMatcher     = &Wrapper{}
)

type ErrMatcher interface {
	error
	Match(...error) bool
}

func (err Err) Error() string {
	return string(err)
}
func (err Err) Errors() []error {
	return []error{err}
}

func (err Err) ExitCode() int {
	return 1
}
func (err Err) Wrap(errs ...error) *Wrapper {
	return Wrap(err, errs...)
}

func (err Err) Comment(comments ...string) *Wrapper {
	return Wrap(err).Comment(comments...)
}
func (err Err) Match(errs ...error) bool {
	for _, er := range errs {
		switch er := er.(type) {
		case *Wrapper:
			if er.main == err {
				return true
			}
		default:
			if err == er {
				return true
			}
		}
	}
	return false
}

type Wrapper struct {
	main          error
	reasons       []error
	comments      []string
	cachedMessage string
}

func (wrapper *Wrapper) Comment(comments ...string) *Wrapper {
	wrapper.comments = append(wrapper.comments, comments...)
	return wrapper
}
func Wrap(err error, reasons ...error) *Wrapper {
	return &Wrapper{
		main:    err,
		reasons: reasons,
	}
}

func (wrapper *Wrapper) AddReasons(reasons ...error) *Wrapper {
	for _, reason := range reasons {
		wrapper.reasons = append(wrapper.reasons, reason)
	}
	return wrapper
}

func (wrapper *Wrapper) AddReasonF(f string, vals ...interface{}) *Wrapper {
	return wrapper.AddReasons(fmt.Errorf(f, vals...))
}
func (wrapper *Wrapper) Error() string {
	if wrapper.cachedMessage != "" {
		return wrapper.cachedMessage
	}
	buf := bytes.NewBufferString(wrapper.main.Error())
	if len(wrapper.reasons) > 0 {
		buf.WriteString(": ")
	}
	for i, reason := range wrapper.reasons {
		if i != 0 {
			buf.WriteString(", " + reason.Error())
		} else {
			buf.WriteString(reason.Error())
		}
	}
	wrapper.cachedMessage = buf.String()
	return wrapper.cachedMessage
}

func (wrapper *Wrapper) Match(errs ...error) bool {
	for _, err := range errs {
		if wrapper.main == err {
			return true
		}
	}
	return false
}

func (wrapper *Wrapper) Errors() []error {
	errs := make([]error, len(wrapper.reasons))
	copy(errs, wrapper.reasons)
	return errs
}

func (wrapper *Wrapper) ExitCode() int {
	return 1
}
<|endoftext|>


<commit_before>package chunkymonkey

import (
	"bytes"
	"fmt"
	"log"
	"net"
	"os"
	"rand"
	"time"

	. "chunkymonkey/entity"
	"chunkymonkey/gamerules"
	"chunkymonkey/itemtype"
	"chunkymonkey/player"
	"chunkymonkey/proto"
	"chunkymonkey/server_auth"
	"chunkymonkey/shardserver"
	. "chunkymonkey/types"
	"chunkymonkey/worldstore"
)

type Game struct {
	chunkManager     *shardserver.LocalShardManager
	mainQueue        chan func(*Game)
	playerDisconnect chan EntityId
	entityManager    EntityManager
	players          map[EntityId]*player.Player
	time             TimeOfDay
	gameRules        gamerules.GameRules
	itemTypes        itemtype.ItemTypeMap
	rand             *rand.Rand
	serverId         string
	worldStore       *worldstore.WorldStore
	// If set, logins are not allowed.
	UnderMaintenanceMsg string
}

func NewGame(worldPath string, gameRules *gamerules.GameRules) (game *Game, err os.Error) {
	worldStore, err := worldstore.LoadWorldStore(worldPath)

	game = &Game{
		mainQueue:        make(chan func(*Game), 256),
		playerDisconnect: make(chan EntityId),
		players:          make(map[EntityId]*player.Player),
		gameRules:        *gameRules,
		rand:             rand.New(rand.NewSource(time.UTC().Seconds())),
		worldStore:       worldStore,
	}

	game.entityManager.Init()

	game.serverId = fmt.Sprintf("%x", game.rand.Int63())
	//game.serverId = "-"

	game.chunkManager = shardserver.NewLocalShardManager(worldStore.ChunkStore, &game.entityManager, &game.gameRules)

	go game.mainLoop()
	return
}

// login negotiates a player client login, and adds a new player if successful.
// Note that it does not run in the game's goroutine.
func (game *Game) login(conn net.Conn) {
	username, err := proto.ServerReadHandshake(conn)
	if err != nil {
		log.Print("ServerReadHandshake: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}
	log.Print("Client ", conn.RemoteAddr(), " connected as ", username)
	if game.UnderMaintenanceMsg != "" {
		log.Println("Server under maintenance, kicking player:", username)
		proto.WriteDisconnect(conn, game.UnderMaintenanceMsg)
		return
	}

	err = proto.ServerWriteHandshake(conn, game.serverId)
	if err != nil {
		log.Print("ServerWriteHandshake: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}

	if game.serverId != "-" {
		var authenticated bool
		authserver := &server_auth.ServerAuth{"http://www.minecraft.net/game/checkserver.jsp"}
		authenticated, err = authserver.Authenticate(game.serverId, username)
		if !authenticated || err != nil {
			var reason string
			if err != nil {
				reason = "Authentication check failed: " + err.String()
			} else {
				reason = "Failed authentication"
			}
			log.Print("Client ", conn.RemoteAddr(), " ", reason)
			proto.WriteDisconnect(conn, reason)
			conn.Close()
			return
		}
		log.Print("Client ", conn.RemoteAddr(), " passed minecraft.net authentication")
	}

	_, err = proto.ServerReadLogin(conn)
	if err != nil {
		log.Print("ServerReadLogin: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}

	startPosition := game.worldStore.StartPosition

	entityId := game.entityManager.NewEntity()

	// TODO pass player's last position in the world, not necessarily the spawn
	// position.
	player := player.NewPlayer(entityId, game.chunkManager, &game.gameRules, conn, username, startPosition, game.playerDisconnect)

	addedChan := make(chan struct{})
	game.enqueue(func(_ *Game) {
		game.addPlayer(player)
		addedChan <- struct{}{}
	})
	_ = <-addedChan

	player.Start()

	buf := &bytes.Buffer{}
	// TODO pass proper dimension. This is low priority, because there is
	// currently no way to update the client's dimension after login.
	proto.ServerWriteLogin(buf, player.EntityId, 0, DimensionNormal)
	proto.WriteSpawnPosition(buf, startPosition.ToBlockXyz())
	player.TransmitPacket(buf.Bytes())
}

func (game *Game) Serve(addr string) {
	listener, e := net.Listen("tcp", addr)
	if e != nil {
		log.Fatalf("Listen: %s", e.String())
	}
	log.Print("Listening on ", addr)

	for {
		conn, e2 := listener.Accept()
		if e2 != nil {
			log.Print("Accept: ", e2.String())
			continue
		}

		go game.login(conn)
	}
}

// addPlayer sends spawn messages to all players in range. It also spawns all
// existing players so the new player can see them.
func (game *Game) addPlayer(newPlayer *player.Player) {
	game.players[newPlayer.GetEntityId()] = newPlayer
}

func (game *Game) removePlayer(entityId EntityId) {
	game.players[entityId] = nil, false
	game.entityManager.RemoveEntityById(entityId)
}

func (game *Game) multicastPacket(packet []byte, except interface{}) {
	for _, player := range game.players {
		if player == except {
			continue
		}

		player.TransmitPacket(packet)
	}
}

func (game *Game) enqueue(f func(*Game)) {
	game.mainQueue <- f
}

func (game *Game) mainLoop() {
	ticker := time.NewTicker(NanosecondsInSecond / TicksPerSecond)

	for {
		select {
		case f := <-game.mainQueue:
			f(game)
		case <-ticker.C:
			game.tick()
		case entityId := <-game.playerDisconnect:
			game.removePlayer(entityId)
		}
	}
}

func (game *Game) sendTimeUpdate() {
	buf := new(bytes.Buffer)
	proto.ServerWriteTimeUpdate(buf, game.time)

	// The "keep-alive" packet to client(s) sent here as well, as there
	// seems no particular reason to send time and keep-alive separately
	// for now.
	proto.WriteKeepAlive(buf)

	game.multicastPacket(buf.Bytes(), nil)
}

func (game *Game) tick() {
	game.time++
	if game.time%TicksPerSecond == 0 {
		game.sendTimeUpdate()
	}
}
<commit_msg>Check for when LoadWorldStore fails<commit_after>package chunkymonkey

import (
	"bytes"
	"fmt"
	"log"
	"net"
	"os"
	"rand"
	"time"

	. "chunkymonkey/entity"
	"chunkymonkey/gamerules"
	"chunkymonkey/itemtype"
	"chunkymonkey/player"
	"chunkymonkey/proto"
	"chunkymonkey/server_auth"
	"chunkymonkey/shardserver"
	. "chunkymonkey/types"
	"chunkymonkey/worldstore"
)

type Game struct {
	chunkManager     *shardserver.LocalShardManager
	mainQueue        chan func(*Game)
	playerDisconnect chan EntityId
	entityManager    EntityManager
	players          map[EntityId]*player.Player
	time             TimeOfDay
	gameRules        gamerules.GameRules
	itemTypes        itemtype.ItemTypeMap
	rand             *rand.Rand
	serverId         string
	worldStore       *worldstore.WorldStore
	// If set, logins are not allowed.
	UnderMaintenanceMsg string
}

func NewGame(worldPath string, gameRules *gamerules.GameRules) (game *Game, err os.Error) {
	worldStore, err := worldstore.LoadWorldStore(worldPath)
	if worldStore == nil {
		log.Fatalf("Error loading world store for '%s': %s", worldPath, err)
	}

	game = &Game{
		mainQueue:        make(chan func(*Game), 256),
		playerDisconnect: make(chan EntityId),
		players:          make(map[EntityId]*player.Player),
		gameRules:        *gameRules,
		rand:             rand.New(rand.NewSource(time.UTC().Seconds())),
		worldStore:       worldStore,
	}

	game.entityManager.Init()

	game.serverId = fmt.Sprintf("%x", game.rand.Int63())
	//game.serverId = "-"

	game.chunkManager = shardserver.NewLocalShardManager(worldStore.ChunkStore, &game.entityManager, &game.gameRules)

	go game.mainLoop()
	return
}

// login negotiates a player client login, and adds a new player if successful.
// Note that it does not run in the game's goroutine.
func (game *Game) login(conn net.Conn) {
	username, err := proto.ServerReadHandshake(conn)
	if err != nil {
		log.Print("ServerReadHandshake: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}
	log.Print("Client ", conn.RemoteAddr(), " connected as ", username)
	if game.UnderMaintenanceMsg != "" {
		log.Println("Server under maintenance, kicking player:", username)
		proto.WriteDisconnect(conn, game.UnderMaintenanceMsg)
		return
	}

	err = proto.ServerWriteHandshake(conn, game.serverId)
	if err != nil {
		log.Print("ServerWriteHandshake: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}

	if game.serverId != "-" {
		var authenticated bool
		authserver := &server_auth.ServerAuth{"http://www.minecraft.net/game/checkserver.jsp"}
		authenticated, err = authserver.Authenticate(game.serverId, username)
		if !authenticated || err != nil {
			var reason string
			if err != nil {
				reason = "Authentication check failed: " + err.String()
			} else {
				reason = "Failed authentication"
			}
			log.Print("Client ", conn.RemoteAddr(), " ", reason)
			proto.WriteDisconnect(conn, reason)
			conn.Close()
			return
		}
		log.Print("Client ", conn.RemoteAddr(), " passed minecraft.net authentication")
	}

	_, err = proto.ServerReadLogin(conn)
	if err != nil {
		log.Print("ServerReadLogin: ", err.String())
		proto.WriteDisconnect(conn, err.String())
		conn.Close()
		return
	}

	startPosition := game.worldStore.StartPosition

	entityId := game.entityManager.NewEntity()

	// TODO pass player's last position in the world, not necessarily the spawn
	// position.
	player := player.NewPlayer(entityId, game.chunkManager, &game.gameRules, conn, username, startPosition, game.playerDisconnect)

	addedChan := make(chan struct{})
	game.enqueue(func(_ *Game) {
		game.addPlayer(player)
		addedChan <- struct{}{}
	})
	_ = <-addedChan

	player.Start()

	buf := &bytes.Buffer{}
	// TODO pass proper dimension. This is low priority, because there is
	// currently no way to update the client's dimension after login.
	proto.ServerWriteLogin(buf, player.EntityId, 0, DimensionNormal)
	proto.WriteSpawnPosition(buf, startPosition.ToBlockXyz())
	player.TransmitPacket(buf.Bytes())
}

func (game *Game) Serve(addr string) {
	listener, e := net.Listen("tcp", addr)
	if e != nil {
		log.Fatalf("Listen: %s", e.String())
	}
	log.Print("Listening on ", addr)

	for {
		conn, e2 := listener.Accept()
		if e2 != nil {
			log.Print("Accept: ", e2.String())
			continue
		}

		go game.login(conn)
	}
}

// addPlayer sends spawn messages to all players in range. It also spawns all
// existing players so the new player can see them.
func (game *Game) addPlayer(newPlayer *player.Player) {
	game.players[newPlayer.GetEntityId()] = newPlayer
}

func (game *Game) removePlayer(entityId EntityId) {
	game.players[entityId] = nil, false
	game.entityManager.RemoveEntityById(entityId)
}

func (game *Game) multicastPacket(packet []byte, except interface{}) {
	for _, player := range game.players {
		if player == except {
			continue
		}

		player.TransmitPacket(packet)
	}
}

func (game *Game) enqueue(f func(*Game)) {
	game.mainQueue <- f
}

func (game *Game) mainLoop() {
	ticker := time.NewTicker(NanosecondsInSecond / TicksPerSecond)

	for {
		select {
		case f := <-game.mainQueue:
			f(game)
		case <-ticker.C:
			game.tick()
		case entityId := <-game.playerDisconnect:
			game.removePlayer(entityId)
		}
	}
}

func (game *Game) sendTimeUpdate() {
	buf := new(bytes.Buffer)
	proto.ServerWriteTimeUpdate(buf, game.time)

	// The "keep-alive" packet to client(s) sent here as well, as there
	// seems no particular reason to send time and keep-alive separately
	// for now.
	proto.WriteKeepAlive(buf)

	game.multicastPacket(buf.Bytes(), nil)
}

func (game *Game) tick() {
	game.time++
	if game.time%TicksPerSecond == 0 {
		game.sendTimeUpdate()
	}
}
<|endoftext|>


<commit_before>package chClient

import (
	"git.containerum.net/ch/kube-client/pkg/cherry"
	"git.containerum.net/ch/kube-client/pkg/cherry/auth"
	"git.containerum.net/ch/kube-client/pkg/cherry/kube-api"
	"git.containerum.net/ch/kube-client/pkg/cherry/resource-service"
	"github.com/containerum/chkit/pkg/model/deployment"
)

func (client *Client) GetDeployment(namespace, deplName string) (deployment.Deployment, error) {
	var depl deployment.Deployment
	err := retry(4, func() (bool, error) {
		kubeDeployment, err := client.kubeAPIClient.GetDeployment(namespace, deplName)
		switch {
		case err == nil:
			depl = deployment.DeploymentFromKube(kubeDeployment)
			return false, nil
		case cherry.In(err,
			kubeErrors.ErrResourceNotExist(),
			kubeErrors.ErrAccessError(),
			kubeErrors.ErrUnableGetResource()):
			return false, ErrResourceNotExists
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
	return depl, err
}

func (client *Client) GetDeploymentList(namespace string) (deployment.DeploymentList, error) {
	var list deployment.DeploymentList
	err := retry(4, func() (bool, error) {
		kubeList, err := client.kubeAPIClient.GetDeploymentList(namespace)
		switch {
		case err == nil:
			list = deployment.DeploymentListFromKube(kubeList)
			return false, nil
		case cherry.In(err,
			kubeErrors.ErrResourceNotExist(),
			kubeErrors.ErrAccessError(),
			kubeErrors.ErrUnableGetResource()):
			return false, ErrNamespaceNotExists
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
	return list, err
}

func (client *Client) DeleteDeployment(namespace, deplName string) error {
	return retry(4, func() (bool, error) {
		err := client.kubeAPIClient.DeleteDeployment(namespace, deplName)
		switch {
		case err == nil:
			return false, nil
		case cherry.In(err,
			rserrors.ErrResourceNotExists()):
			return false, ErrResourceNotExists.Wrap(err)
		case cherry.In(err,
			rserrors.ErrResourceNotOwned(),
			rserrors.ErrAccessRecordNotExists()):
			return false, ErrYouDoNotHaveAccessToResource
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
}
<commit_msg>add CreateDeployment method<commit_after>package chClient

import (
	"git.containerum.net/ch/kube-client/pkg/cherry"
	"git.containerum.net/ch/kube-client/pkg/cherry/auth"
	"git.containerum.net/ch/kube-client/pkg/cherry/kube-api"
	"git.containerum.net/ch/kube-client/pkg/cherry/resource-service"
	"github.com/containerum/chkit/pkg/model/deployment"
	"github.com/sirupsen/logrus"
)

func (client *Client) GetDeployment(namespace, deplName string) (deployment.Deployment, error) {
	var depl deployment.Deployment
	err := retry(4, func() (bool, error) {
		kubeDeployment, err := client.kubeAPIClient.GetDeployment(namespace, deplName)
		switch {
		case err == nil:
			depl = deployment.DeploymentFromKube(kubeDeployment)
			return false, nil
		case cherry.In(err,
			kubeErrors.ErrResourceNotExist(),
			kubeErrors.ErrAccessError(),
			kubeErrors.ErrUnableGetResource()):
			return false, ErrResourceNotExists
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
	return depl, err
}

func (client *Client) GetDeploymentList(namespace string) (deployment.DeploymentList, error) {
	var list deployment.DeploymentList
	err := retry(4, func() (bool, error) {
		kubeList, err := client.kubeAPIClient.GetDeploymentList(namespace)
		switch {
		case err == nil:
			list = deployment.DeploymentListFromKube(kubeList)
			return false, nil
		case cherry.In(err,
			kubeErrors.ErrResourceNotExist(),
			kubeErrors.ErrAccessError(),
			kubeErrors.ErrUnableGetResource()):
			return false, ErrNamespaceNotExists
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
	return list, err
}

func (client *Client) DeleteDeployment(namespace, deplName string) error {
	return retry(4, func() (bool, error) {
		err := client.kubeAPIClient.DeleteDeployment(namespace, deplName)
		switch {
		case err == nil:
			return false, nil
		case cherry.In(err,
			rserrors.ErrResourceNotExists()):
			return false, ErrResourceNotExists.Wrap(err)
		case cherry.In(err,
			rserrors.ErrResourceNotOwned(),
			rserrors.ErrAccessRecordNotExists()):
			return false, ErrYouDoNotHaveAccessToResource
		case cherry.In(err, autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			return true, client.Auth()
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
}

func (client *Client) CreateDeployment(ns string, depl deployment.Deployment) error {
	return retry(4, func() (bool, error) {
		err := client.kubeAPIClient.CreateDeployment(ns, depl.ToKube())
		switch {
		case err == nil:
			return false, nil
		case cherry.In(err,
			rserrors.ErrResourceNotExists()):
			logrus.WithError(ErrResourceNotExists.Wrap(err)).
				Debugf("error while creating service %q", depl.Name)
			return false, ErrResourceNotExists.CommentF("namespace %q doesn't exist", ns)
		case cherry.In(err,
			rserrors.ErrResourceNotOwned(),
			rserrors.ErrAccessRecordNotExists(),
			rserrors.ErrPermissionDenied()):
			logrus.WithError(ErrYouDoNotHaveAccessToResource.Wrap(err)).
				Debugf("error while creating service %q", depl.Name)
			return false, ErrYouDoNotHaveAccessToResource.
				CommentF("you don't have create access to namespace %q", ns)
		case cherry.In(err,
			autherr.ErrInvalidToken(),
			autherr.ErrTokenNotFound()):
			err = client.Auth()
			if err != nil {
				logrus.WithError(err).
					Debugf("error while creating service %q", depl.Name)
			}
			return true, err
		default:
			return true, ErrFatalError.Wrap(err)
		}
	})
}
<|endoftext|>


<commit_before>package master

import (
	"net/http"
	"os"
	"path"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
	// "github.com/GoogleCloudPlatform/kubernetes/pkg/build"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
	kconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/proxy"
	pconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/proxy/config"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	etcdconfig "github.com/coreos/etcd/config"
	"github.com/coreos/etcd/etcd"
	etcdclient "github.com/coreos/go-etcd/etcd"
	"github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/google/cadvisor/client"
	"github.com/openshift/origin/pkg/api"
	"github.com/openshift/origin/pkg/service"
	"github.com/spf13/cobra"
)

func NewCommandStartAllInOne(name string) *cobra.Command {
	return &cobra.Command{
		Use:   name,
		Short: "Launch in all-in-one mode",
		Run: func(c *cobra.Command, args []string) {
			startAllInOne()
		},
	}
}

func startAllInOne() {
	dockerAddr := getDockerEndpoint("")
	dockerClient, err := docker.NewClient(dockerAddr)
	if err != nil {
		glog.Fatal("Couldn't connect to docker.")
	}
	if err := dockerClient.Ping(); err != nil {
		glog.Errorf("WARNING: Docker could not be reached at %s.  Docker must be installed and running to start containers.\n%v", dockerAddr, err)
	}

	cadvisorClient, err := cadvisor.NewClient("http://127.0.0.1:4194")
	if err != nil {
		glog.Errorf("Error on creating cadvisor client: %v", err)
	}

	// initialize etcd
	etcdAddr := "127.0.0.1:4001"
	etcdServers := []string{} // default
	etcdConfig := etcdconfig.New()
	etcdConfig.BindAddr = etcdAddr
	etcdServer := etcd.New(etcdConfig)
	go util.Forever(func() {
		glog.Infof("Started etcd at http://%s", etcdAddr)
		etcdServer.Run()
	}, 0)

	etcdClient := etcdclient.NewClient(etcdServers)
	for i := 0; ; i += 1 {
		_, err := etcdClient.Get("/", false, false)
		if err == nil || tools.IsEtcdNotFound(err) {
			break
		}
		if i > 100 {
			glog.Fatal("Could not reach etcd: %v", err)
		}
		time.Sleep(50 * time.Millisecond)
	}

	// initialize Kubelet
	minionHost := "127.0.0.1"
	minionPort := 10250
	rootDirectory := path.Clean("/var/lib/openshift")
	os.MkdirAll(rootDirectory, 0750)
	cfg := kconfig.NewPodConfig(kconfig.PodConfigNotificationSnapshotAndUpdates)
	kconfig.NewSourceEtcd(kconfig.EtcdKeyForHost(minionHost), etcdClient, cfg.Channel("etcd"))
	k := kubelet.NewMainKubelet(
		minionHost,
		dockerClient,
		cadvisorClient,
		etcdClient,
		rootDirectory,
		30*time.Second)
	go util.Forever(func() { k.Run(cfg.Updates()) }, 0)
	go util.Forever(func() {
		kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), minionHost, uint(minionPort))
	}, 0)

	// initialize OpenShift API
	storage := map[string]apiserver.RESTStorage{
		"services": service.NewRESTStorage(service.MakeMemoryRegistry()),
	}
	osAddr := "127.0.0.1:8080"
	osPrefix := "/osapi/v1beta1"

	osMux := http.NewServeMux()

	// initialize Kubernetes API
	kubePrefix := "/api/v1beta1"
	kubeClient := client.New("http://"+osAddr, nil)
	podInfoGetter := &client.HTTPPodInfoGetter{
		Client: http.DefaultClient,
		Port:   uint(minionPort),
	}
	masterConfig := &master.Config{
		Client:             kubeClient,
		EtcdServers:        etcdServers,
		HealthCheckMinions: true,
		Minions:            []string{minionHost},
		PodInfoGetter:      podInfoGetter,
	}
	m := master.New(masterConfig)

	apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, kubePrefix)
	apiserver.NewAPIGroup(storage, api.Codec).InstallREST(osMux, osPrefix)
	apiserver.InstallSupport(osMux)

	osApi := &http.Server{
		Addr:           osAddr,
		Handler:        apiserver.RecoverPanics(osMux),
		ReadTimeout:    5 * time.Minute,
		WriteTimeout:   5 * time.Minute,
		MaxHeaderBytes: 1 << 20,
	}

	go util.Forever(func() {
		glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kubePrefix)
		glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix)
		glog.Fatal(osApi.ListenAndServe())
	}, 0)

	// initialize kube proxy
	serviceConfig := pconfig.NewServiceConfig()
	endpointsConfig := pconfig.NewEndpointsConfig()
	pconfig.NewConfigSourceEtcd(etcdClient,
		serviceConfig.Channel("etcd"),
		endpointsConfig.Channel("etcd"))
	loadBalancer := proxy.NewLoadBalancerRR()
	proxier := proxy.NewProxier(loadBalancer)
	serviceConfig.RegisterHandler(proxier)
	endpointsConfig.RegisterHandler(loadBalancer)
	glog.Infof("Started Kubernetes Proxy")

	// initialize replication manager
	controllerManager := controller.NewReplicationManager(kubeClient)
	controllerManager.Run(10 * time.Second)
	glog.Infof("Started Kubernetes Replication Manager")

	// initialize build controller
	// if env("BUILD_POD_CLEANUP_ENABLED", "true") == "true" {
	// 	os.Setenv("BUILD_POD_CLEANUP_ENABLED", "true")
	// }
	// buildController := build.MakeBuildController(kubeClient, "openshift/docker-builder",
	// 	env("DOCKER_REGISTRY_URL", ""), "openshift/sti-builder", 120)
	// buildController.Run(10 * time.Second)

	select {}
}

func env(key string, defaultValue string) string {
	val := os.Getenv(key)
	if len(val) == 0 {
		return defaultValue
	} else {
		return val
	}
}

func getDockerEndpoint(dockerEndpoint string) string {
	var endpoint string
	if len(dockerEndpoint) > 0 {
		endpoint = dockerEndpoint
	} else if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	glog.Infof("Connecting to docker on %s", endpoint)

	return endpoint
}
<commit_msg>Start the scheduler in the all-in-one<commit_after>package master

import (
	"net/http"
	"os"
	"path"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
	kconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/proxy"
	pconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/proxy/config"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler"
	"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler/factory"
	etcdconfig "github.com/coreos/etcd/config"
	"github.com/coreos/etcd/etcd"
	etcdclient "github.com/coreos/go-etcd/etcd"
	"github.com/fsouza/go-dockerclient"
	"github.com/golang/glog"
	"github.com/google/cadvisor/client"
	"github.com/openshift/origin/pkg/api"
	"github.com/openshift/origin/pkg/service"
	"github.com/spf13/cobra"
)

func NewCommandStartAllInOne(name string) *cobra.Command {
	return &cobra.Command{
		Use:   name,
		Short: "Launch in all-in-one mode",
		Run: func(c *cobra.Command, args []string) {
			startAllInOne()
		},
	}
}

func startAllInOne() {
	dockerAddr := getDockerEndpoint("")
	dockerClient, err := docker.NewClient(dockerAddr)
	if err != nil {
		glog.Fatal("Couldn't connect to docker.")
	}
	if err := dockerClient.Ping(); err != nil {
		glog.Errorf("WARNING: Docker could not be reached at %s.  Docker must be installed and running to start containers.\n%v", dockerAddr, err)
	}

	cadvisorClient, err := cadvisor.NewClient("http://127.0.0.1:4194")
	if err != nil {
		glog.Errorf("Error on creating cadvisor client: %v", err)
	}

	// initialize etcd
	etcdAddr := "127.0.0.1:4001"
	etcdServers := []string{} // default
	etcdConfig := etcdconfig.New()
	etcdConfig.BindAddr = etcdAddr
	etcdServer := etcd.New(etcdConfig)
	go util.Forever(func() {
		glog.Infof("Started etcd at http://%s", etcdAddr)
		etcdServer.Run()
	}, 0)

	etcdClient := etcdclient.NewClient(etcdServers)
	for i := 0; ; i += 1 {
		_, err := etcdClient.Get("/", false, false)
		if err == nil || tools.IsEtcdNotFound(err) {
			break
		}
		if i > 100 {
			glog.Fatal("Could not reach etcd: %v", err)
		}
		time.Sleep(50 * time.Millisecond)
	}

	// initialize Kubelet
	minionHost := "127.0.0.1"
	minionPort := 10250
	rootDirectory := path.Clean("/var/lib/openshift")
	os.MkdirAll(rootDirectory, 0750)
	cfg := kconfig.NewPodConfig(kconfig.PodConfigNotificationSnapshotAndUpdates)
	kconfig.NewSourceEtcd(kconfig.EtcdKeyForHost(minionHost), etcdClient, cfg.Channel("etcd"))
	k := kubelet.NewMainKubelet(
		minionHost,
		dockerClient,
		cadvisorClient,
		etcdClient,
		rootDirectory,
		30*time.Second)
	go util.Forever(func() { k.Run(cfg.Updates()) }, 0)
	go util.Forever(func() {
		kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), minionHost, uint(minionPort))
	}, 0)

	// initialize OpenShift API
	storage := map[string]apiserver.RESTStorage{
		"services": service.NewRESTStorage(service.MakeMemoryRegistry()),
	}
	osAddr := "127.0.0.1:8080"
	osPrefix := "/osapi/v1beta1"

	osMux := http.NewServeMux()

	// initialize Kubernetes API
	kubePrefix := "/api/v1beta1"
	kubeClient := client.New("http://"+osAddr, nil)
	podInfoGetter := &client.HTTPPodInfoGetter{
		Client: http.DefaultClient,
		Port:   uint(minionPort),
	}
	masterConfig := &master.Config{
		Client:             kubeClient,
		EtcdServers:        etcdServers,
		HealthCheckMinions: true,
		Minions:            []string{minionHost},
		PodInfoGetter:      podInfoGetter,
	}
	m := master.New(masterConfig)

	apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(osMux, kubePrefix)
	apiserver.NewAPIGroup(storage, api.Codec).InstallREST(osMux, osPrefix)
	apiserver.InstallSupport(osMux)

	osApi := &http.Server{
		Addr:           osAddr,
		Handler:        apiserver.RecoverPanics(osMux),
		ReadTimeout:    5 * time.Minute,
		WriteTimeout:   5 * time.Minute,
		MaxHeaderBytes: 1 << 20,
	}

	go util.Forever(func() {
		glog.Infof("Started Kubernetes API at http://%s%s", osAddr, kubePrefix)
		glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix)
		glog.Fatal(osApi.ListenAndServe())
	}, 0)

	// initialize kube proxy
	serviceConfig := pconfig.NewServiceConfig()
	endpointsConfig := pconfig.NewEndpointsConfig()
	pconfig.NewConfigSourceEtcd(etcdClient,
		serviceConfig.Channel("etcd"),
		endpointsConfig.Channel("etcd"))
	loadBalancer := proxy.NewLoadBalancerRR()
	proxier := proxy.NewProxier(loadBalancer)
	serviceConfig.RegisterHandler(proxier)
	endpointsConfig.RegisterHandler(loadBalancer)
	glog.Infof("Started Kubernetes Proxy")

	// initialize replication manager
	controllerManager := controller.NewReplicationManager(kubeClient)
	controllerManager.Run(10 * time.Second)
	glog.Infof("Started Kubernetes Replication Manager")

	// initialize scheduler
	configFactory := &factory.ConfigFactory{Client: kubeClient}
	config := configFactory.Create()
	s := scheduler.New(config)
	s.Run()
	glog.Infof("Started Kubernetes Scheduler")

	select {}
}

func env(key string, defaultValue string) string {
	val := os.Getenv(key)
	if len(val) == 0 {
		return defaultValue
	} else {
		return val
	}
}

func getDockerEndpoint(dockerEndpoint string) string {
	var endpoint string
	if len(dockerEndpoint) > 0 {
		endpoint = dockerEndpoint
	} else if len(os.Getenv("DOCKER_HOST")) > 0 {
		endpoint = os.Getenv("DOCKER_HOST")
	} else {
		endpoint = "unix:///var/run/docker.sock"
	}
	glog.Infof("Connecting to docker on %s", endpoint)

	return endpoint
}
<|endoftext|>


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

package fileutil

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	// PrivateFileMode grants owner to read/write a file.
	PrivateFileMode = 0600
)

// IsDirWriteable checks if dir is writable by writing and removing a file
// to dir. It returns nil if dir is writable.
func IsDirWriteable(dir string) error {
	f := filepath.Join(dir, ".touch")
	if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
		return err
	}
	return os.Remove(f)
}

// TouchDirAll is similar to os.MkdirAll. It creates directories with 0700 permission if any directory
// does not exists. TouchDirAll also ensures the given directory is writable.
func TouchDirAll(dir string) error {
	// If path is already a directory, MkdirAll does nothing and returns nil, so,
	// first check if dir exist with an expected permission mode.
	if Exist(dir) {
		err := CheckDirPermission(dir, PrivateDirMode)
		if err != nil {
			return err
		}
	} else {
		err := os.MkdirAll(dir, PrivateDirMode)
		if err != nil {
			// if mkdirAll("a/text") and "text" is not
			// a directory, this will return syscall.ENOTDIR
			return err
		}
	}

	return IsDirWriteable(dir)
}

// CreateDirAll is similar to TouchDirAll but returns error
// if the deepest directory was not empty.
func CreateDirAll(dir string) error {
	err := TouchDirAll(dir)
	if err == nil {
		var ns []string
		ns, err = ReadDir(dir)
		if err != nil {
			return err
		}
		if len(ns) != 0 {
			err = fmt.Errorf("expected %q to be empty, got %q", dir, ns)
		}
	}
	return err
}

// Exist returns true if a file or directory exists.
func Exist(name string) bool {
	_, err := os.Stat(name)
	return err == nil
}

// DirEmpty returns true if a directory empty and can access.
func DirEmpty(name string) bool {
	ns, err := ReadDir(name)
	return len(ns) == 0 && err == nil
}

// ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily
// shorten the length of the file.
func ZeroToEnd(f *os.File) error {
	// TODO: support FALLOC_FL_ZERO_RANGE
	off, err := f.Seek(0, io.SeekCurrent)
	if err != nil {
		return err
	}
	lenf, lerr := f.Seek(0, io.SeekEnd)
	if lerr != nil {
		return lerr
	}
	if err = f.Truncate(off); err != nil {
		return err
	}
	// make sure blocks remain allocated
	if err = Preallocate(f, lenf, true); err != nil {
		return err
	}
	_, err = f.Seek(off, io.SeekStart)
	return err
}

// CheckDirPermission checks permission on an existing dir.
// Returns error if dir is empty or exist with a different permission than specified.
func CheckDirPermission(dir string, perm os.FileMode) error {
	if !Exist(dir) {
		return fmt.Errorf("directory %q empty, cannot check permission.", dir)
	}
	//check the existing permission on the directory
	dirInfo, err := os.Stat(dir)
	if err != nil {
		return err
	}
	dirMode := dirInfo.Mode().Perm()
	if dirMode != perm {
		err = fmt.Errorf("directory %q exist without desired file permission. %q", dir, dirInfo.Mode())
		return err
	}
	return nil
}
<commit_msg>pkg/fileutil: print desired file permission in error log<commit_after>// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fileutil

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	// PrivateFileMode grants owner to read/write a file.
	PrivateFileMode = 0600
)

// IsDirWriteable checks if dir is writable by writing and removing a file
// to dir. It returns nil if dir is writable.
func IsDirWriteable(dir string) error {
	f := filepath.Join(dir, ".touch")
	if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
		return err
	}
	return os.Remove(f)
}

// TouchDirAll is similar to os.MkdirAll. It creates directories with 0700 permission if any directory
// does not exists. TouchDirAll also ensures the given directory is writable.
func TouchDirAll(dir string) error {
	// If path is already a directory, MkdirAll does nothing and returns nil, so,
	// first check if dir exist with an expected permission mode.
	if Exist(dir) {
		err := CheckDirPermission(dir, PrivateDirMode)
		if err != nil {
			return err
		}
	} else {
		err := os.MkdirAll(dir, PrivateDirMode)
		if err != nil {
			// if mkdirAll("a/text") and "text" is not
			// a directory, this will return syscall.ENOTDIR
			return err
		}
	}

	return IsDirWriteable(dir)
}

// CreateDirAll is similar to TouchDirAll but returns error
// if the deepest directory was not empty.
func CreateDirAll(dir string) error {
	err := TouchDirAll(dir)
	if err == nil {
		var ns []string
		ns, err = ReadDir(dir)
		if err != nil {
			return err
		}
		if len(ns) != 0 {
			err = fmt.Errorf("expected %q to be empty, got %q", dir, ns)
		}
	}
	return err
}

// Exist returns true if a file or directory exists.
func Exist(name string) bool {
	_, err := os.Stat(name)
	return err == nil
}

// DirEmpty returns true if a directory empty and can access.
func DirEmpty(name string) bool {
	ns, err := ReadDir(name)
	return len(ns) == 0 && err == nil
}

// ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily
// shorten the length of the file.
func ZeroToEnd(f *os.File) error {
	// TODO: support FALLOC_FL_ZERO_RANGE
	off, err := f.Seek(0, io.SeekCurrent)
	if err != nil {
		return err
	}
	lenf, lerr := f.Seek(0, io.SeekEnd)
	if lerr != nil {
		return lerr
	}
	if err = f.Truncate(off); err != nil {
		return err
	}
	// make sure blocks remain allocated
	if err = Preallocate(f, lenf, true); err != nil {
		return err
	}
	_, err = f.Seek(off, io.SeekStart)
	return err
}

// CheckDirPermission checks permission on an existing dir.
// Returns error if dir is empty or exist with a different permission than specified.
func CheckDirPermission(dir string, perm os.FileMode) error {
	if !Exist(dir) {
		return fmt.Errorf("directory %q empty, cannot check permission.", dir)
	}
	//check the existing permission on the directory
	dirInfo, err := os.Stat(dir)
	if err != nil {
		return err
	}
	dirMode := dirInfo.Mode().Perm()
	if dirMode != perm {
		err = fmt.Errorf("directory %q,%q exist without desired file permission %q.", dir, dirInfo.Mode(), os.FileMode(PrivateDirMode))
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"encoding/json"
	"net"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/event"
	"github.com/bitfinexcom/bitfinex-api-go/pkg/mux/subs"
	"github.com/gobwas/ws"
	"github.com/gobwas/ws/wsutil"
)

type Msg struct {
	Data []byte
	Err  error
	CID  int
}

type Client struct {
	Conn net.Conn
	Subs *subs.Subs
	Err  error
	ID   int
}

// New returns pointer to Client instance
func New(ID int) *Client {
	return &Client{
		ID:   ID,
		Subs: subs.New(),
	}
}

// Public creates and returns public client to interact with public channels
func (c *Client) Public() *Client {
	if c.Err != nil {
		return c
	}

	c.Conn, _, _, c.Err = ws.DefaultDialer.Dial(context.Background(), "wss://api-pub.bitfinex.com/ws/2")
	return c
}

// Subscribe takes subscription payload as per docs and subscribes connection to it
func (c *Client) Subscribe(sub event.Subscribe) *Client {
	if c.Err != nil {
		return c
	}

	c.Subs.Add(sub)
	b, _ := json.Marshal(sub)
	if c.Err = wsutil.WriteClientBinary(c.Conn, b); c.Err != nil {
		c.Subs.Remove(sub)
		return c
	}

	return c
}

func (c *Client) Read(ch chan<- Msg) {
	for {
		msg, _, err := wsutil.ReadServerData(c.Conn)
		if err != nil {
			c.Conn.Close()
			ch <- Msg{nil, err, c.ID}
			return
		}

		ch <- Msg{msg, nil, c.ID}
	}
}
<commit_msg>making subs limit a bit more flexible<commit_after>package client

import (
	"context"
	"encoding/json"
	"net"

	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/event"
	"github.com/bitfinexcom/bitfinex-api-go/pkg/mux/subs"
	"github.com/gobwas/ws"
	"github.com/gobwas/ws/wsutil"
)

type Msg struct {
	Data []byte
	Err  error
	CID  int
}

type Client struct {
	Conn net.Conn
	Subs *subs.Subs
	Err  error
	ID   int
}

// New returns pointer to Client instance
func New(ID int) *Client {
	return &Client{
		ID:   ID,
		Subs: subs.New(),
	}
}

// Public creates and returns public client to interact with public channels
func (c *Client) Public() *Client {
	if c.Err != nil {
		return c
	}

	c.Subs.SubsLimit = 30
	c.Conn, _, _, c.Err = ws.DefaultDialer.Dial(context.Background(), "wss://api-pub.bitfinex.com/ws/2")
	return c
}

// Subscribe takes subscription payload as per docs and subscribes connection to it
func (c *Client) Subscribe(sub event.Subscribe) *Client {
	if c.Err != nil {
		return c
	}

	c.Subs.Add(sub)
	b, _ := json.Marshal(sub)
	if c.Err = wsutil.WriteClientBinary(c.Conn, b); c.Err != nil {
		c.Subs.Remove(sub)
		return c
	}

	return c
}

func (c *Client) Read(ch chan<- Msg) {
	for {
		msg, _, err := wsutil.ReadServerData(c.Conn)
		if err != nil {
			c.Conn.Close()
			ch <- Msg{nil, err, c.ID}
			return
		}

		ch <- Msg{msg, nil, c.ID}
	}
}
<|endoftext|>


<commit_before>package paxos

import (
	"fmt"
	"log"
	"os"
)

const (
	rRnd = iota
	rVrnd
	rVval
	rNumParts
)

var (
	IdOutOfRange = os.NewError("Id Out of Range")
)

// TODO temporary name
type C struct {
	crnd uint64
	quorum uint64
	modulus uint64

	ins chan Msg
	outs Putter
	clock chan int
	logger *log.Logger
}

func coordinator(crnd, quorum, modulus uint64, tCh chan string, ins chan Msg, outs Putter, clock chan int, logger *log.Logger) {
	c := NewC()
	c.crnd = crnd
	c.quorum = quorum
	c.modulus = modulus
	c.ins = ins
	c.outs = outs
	c.clock = clock
	c.logger = logger

	target := <-tCh
	if target == "" && closed(tCh) {
		return
	}

	c.process(target)
}

func NewC() *C {
	return &C{}
}

func (c *C) process(target string) {
	//if c.crnd > c.modulus {
	//	panic(IdOutOfRange)
	//}

	var cval string

Start:
	cval = ""
	start := Msg{
		Cmd:  "INVITE",
		To:   0, // send to all acceptors
		Body: fmt.Sprintf("%d", c.crnd),
	}
	c.outs.Put(start)

	var rsvps uint64
	var vr uint64
	var vv string

	for {
		select {
		case in := <-c.ins:
			if closed(c.ins) {
				goto Done
			}
			switch in.Cmd {
			case "RSVP":
				bodyParts := splitExactly(in.Body, rNumParts)
				i := dtoui64(bodyParts[rRnd])
				vrnd := dtoui64(bodyParts[rVrnd])
				vval := bodyParts[rVval]

				if cval != "" {
					continue
				}

				if i < c.crnd {
					continue
				}

				if vrnd > vr {
					vr = vrnd
					vv = vval
				}

				rsvps++
				if rsvps >= c.quorum {
					var v string

					if vr > 0 {
						v = vv
					} else {
						v = target
					}
					cval = v

					choosen := Msg{
						Cmd:  "NOMINATE",
						To:   0, // send to all acceptors
						Body: fmt.Sprintf("%d:%s", c.crnd, v),
					}
					c.outs.Put(choosen)
				}
			}
		case <-c.clock:
			c.crnd += c.modulus
			goto Start
		}
	}

Done:
	return
}
<commit_msg>remove unused param<commit_after>package paxos

import (
	"fmt"
	"log"
	"os"
)

const (
	rRnd = iota
	rVrnd
	rVval
	rNumParts
)

var (
	IdOutOfRange = os.NewError("Id Out of Range")
)

// TODO temporary name
type C struct {
	crnd uint64
	quorum uint64
	modulus uint64

	ins chan Msg
	outs Putter
	clock chan int
}

func coordinator(crnd, quorum, modulus uint64, tCh chan string, ins chan Msg, outs Putter, clock chan int, logger *log.Logger) {
	c := NewC()
	c.crnd = crnd
	c.quorum = quorum
	c.modulus = modulus
	c.ins = ins
	c.outs = outs
	c.clock = clock

	target := <-tCh
	if target == "" && closed(tCh) {
		return
	}

	c.process(target)
}

func NewC() *C {
	return &C{}
}

func (c *C) process(target string) {
	//if c.crnd > c.modulus {
	//	panic(IdOutOfRange)
	//}

	var cval string

Start:
	cval = ""
	start := Msg{
		Cmd:  "INVITE",
		To:   0, // send to all acceptors
		Body: fmt.Sprintf("%d", c.crnd),
	}
	c.outs.Put(start)

	var rsvps uint64
	var vr uint64
	var vv string

	for {
		select {
		case in := <-c.ins:
			if closed(c.ins) {
				goto Done
			}
			switch in.Cmd {
			case "RSVP":
				bodyParts := splitExactly(in.Body, rNumParts)
				i := dtoui64(bodyParts[rRnd])
				vrnd := dtoui64(bodyParts[rVrnd])
				vval := bodyParts[rVval]

				if cval != "" {
					continue
				}

				if i < c.crnd {
					continue
				}

				if vrnd > vr {
					vr = vrnd
					vv = vval
				}

				rsvps++
				if rsvps >= c.quorum {
					var v string

					if vr > 0 {
						v = vv
					} else {
						v = target
					}
					cval = v

					choosen := Msg{
						Cmd:  "NOMINATE",
						To:   0, // send to all acceptors
						Body: fmt.Sprintf("%d:%s", c.crnd, v),
					}
					c.outs.Put(choosen)
				}
			}
		case <-c.clock:
			c.crnd += c.modulus
			goto Start
		}
	}

Done:
	return
}
<|endoftext|>


<commit_before>package planar

import (
	"log"
	"math/big"

	"github.com/go-spatial/geom"
)

const (

	// Experimental testing produced this result.
	// For finding the intersect we need higher precision.
	// Then geom.PrecisionLevelBigFloat
	PrecisionLevelBigFloat = 110
)

func AreLinesColinear(l1, l2 geom.Line) bool {
	x1, y1 := l1.Point1().X(), l1.Point1().Y()
	x2, y2 := l1.Point2().X(), l1.Point2().Y()
	x3, y3 := l2.Point1().X(), l2.Point1().Y()
	x4, y4 := l2.Point2().X(), l2.Point2().Y()

	denom := ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
	// The lines are parallel or they overlap fi denom is 0.
	if denom != 0 {
		return false
	}

	// now we just need to see if one of the end points is on the other one.
	xmin, xmax := x1, x2
	if x1 > x2 {
		xmin, xmax = x2, x1
	}
	ymin, ymax := y1, y2
	if y1 > y2 {
		ymin, ymax = y2, y1
	}

	fn := func(x, y float64) bool { return xmin <= x && x <= xmax && ymin <= y && y <= ymax }
	return fn(x3, y3) || fn(x4, y4)
}

// LineIntersect find the intersection point (x,y) between two lines if there is one. Ok will be true if it found an interseciton point.
// ok being false, means there isn't just one intersection point, there could be zero, or more then one.
// ref: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
func LineIntersect(l1, l2 geom.Line) (pt [2]float64, ok bool) {

	x1, y1 := l1.Point1().X(), l1.Point1().Y()
	x2, y2 := l1.Point2().X(), l1.Point2().Y()
	x3, y3 := l2.Point1().X(), l2.Point1().Y()
	x4, y4 := l2.Point2().X(), l2.Point2().Y()

	denom := ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
	// The lines are parallel or they overlap. No single point.
	if denom == 0 {
		return pt, false
	}

	xnom := (((x1 * y2) - (y1 * x2)) * (x3 - x4)) - ((x1 - x2) * ((x3 * y4) - (y3 * x4)))
	ynom := (((x1 * y2) - (y1 * x2)) * (y3 - y4)) - ((y1 - y2) * ((x3 * y4) - (y3 * x4)))
	x := xnom / denom
	if x == -0 {
		x = 0
	}
	y := ynom / denom
	if y == -0 {
		y = 0
	}
	return [2]float64{x, y}, true
}

func bigFloat(f float64) *big.Float { return big.NewFloat(f).SetPrec(PrecisionLevelBigFloat) }

// LineIntersectBigFloat find the intersection point (x,y) between two lines if there is one. Ok will be true if it found an interseciton point. Internally uses math/big
// ok being false, means there isn't just one intersection point, there could be zero, or more then one.
// ref: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
func LineIntersectBigFloat(l1, l2 geom.Line) (pt [2]*big.Float, ok bool) {

	x1, y1 := bigFloat(l1.Point1().X()), bigFloat(l1.Point1().Y())
	x2, y2 := bigFloat(l1.Point2().X()), bigFloat(l1.Point2().Y())
	x3, y3 := bigFloat(l2.Point1().X()), bigFloat(l2.Point1().Y())
	x4, y4 := bigFloat(l2.Point2().X()), bigFloat(l2.Point2().Y())

	deltaX12 := bigFloat(0).Sub(x1, x2)
	deltaX34 := bigFloat(0).Sub(x3, x4)
	deltaY12 := bigFloat(0).Sub(y1, y2)
	deltaY34 := bigFloat(0).Sub(y3, y4)
	denom := bigFloat(0).Sub(
		bigFloat(0).Mul(deltaX12, deltaY34),
		bigFloat(0).Mul(deltaY12, deltaX34),
	)

	// The lines are parallel or they overlap. No single point.
	if d, _ := denom.Float64(); d == 0 {
		return pt, false
	}

	xnom := bigFloat(0).Sub(
		bigFloat(0).Mul(
			bigFloat(0).Sub(
				bigFloat(0).Mul(x1, y2),
				bigFloat(0).Mul(y1, x2),
			),
			deltaX34,
		),
		bigFloat(0).Mul(
			deltaX12,
			bigFloat(0).Sub(
				bigFloat(0).Mul(x3, y4),
				bigFloat(0).Mul(y3, x4),
			),
		),
	)
	ynom := bigFloat(0).Sub(
		bigFloat(0).Mul(
			bigFloat(0).Sub(
				bigFloat(0).Mul(x1, y2),
				bigFloat(0).Mul(y1, x2),
			),
			deltaY34,
		),
		bigFloat(0).Mul(
			deltaY12,
			bigFloat(0).Sub(
				bigFloat(0).Mul(x3, y4),
				bigFloat(0).Mul(y3, x4),
			),
		),
	)
	bx := bigFloat(0).Quo(xnom, denom)
	by := bigFloat(0).Quo(ynom, denom)
	return [2]*big.Float{bx, by}, true

}

// SegmentIntersect finds the intersection point (x,y) between two lines if there is one. Ok will be true if it found a point that is on both line segments, otherwise it will be false.
func SegmentIntersect(l1, l2 geom.Line) (pt [2]float64, ok bool) {
	if pt, ok = LineIntersect(l1, l2); !ok {
		if debug {
			log.Printf("Lines don't intersect: %v %v", l1, l2)
		}
		return pt, false
	}
	l1c, l2c := l1.ContainsPoint(pt), l2.ContainsPoint(pt)
	if debug {
		log.Printf("LineIntersect returns %v %v", pt, ok)
		log.Printf("line (%v) contains point(%v) :%v ", l1, pt, l1c)
		log.Printf("line (%v) contains point(%v) :%v ", l2, pt, l2c)
	}
	// Check to see if the pt is on both line segments.
	return pt, l1c && l2c
}
<commit_msg>avoid allocations and function calls in AreLinesColinear<commit_after>package planar

import (
	"log"
	"math/big"

	"github.com/go-spatial/geom"
)

const (

	// Experimental testing produced this result.
	// For finding the intersect we need higher precision.
	// Then geom.PrecisionLevelBigFloat
	PrecisionLevelBigFloat = 110
)

func AreLinesColinear(l1, l2 geom.Line) bool {
	x1, y1 := l1[0][0], l1[0][1]
	x2, y2 := l1[1][0], l1[1][1]
	x3, y3 := l2[0][0], l2[0][1]
	x4, y4 := l2[1][0], l2[1][1]

	denom := ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
	// The lines are parallel or they overlap fi denom is 0.
	if denom != 0 {
		return false
	}

	// now we just need to see if one of the end points is on the other one.
	xmin, xmax := x1, x2
	if x1 > x2 {
		xmin, xmax = x2, x1
	}
	ymin, ymax := y1, y2
	if y1 > y2 {
		ymin, ymax = y2, y1
	}

	return (xmin <= x3 && x3 <= xmax && ymin <= y3 && y3 <= ymax) ||
		(xmin <= x4 && x4 <= xmax && ymin <= y4 && y4 <= ymax)
}

// LineIntersect find the intersection point (x,y) between two lines if there is one. Ok will be true if it found an interseciton point.
// ok being false, means there isn't just one intersection point, there could be zero, or more then one.
// ref: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
func LineIntersect(l1, l2 geom.Line) (pt [2]float64, ok bool) {

	x1, y1 := l1.Point1().X(), l1.Point1().Y()
	x2, y2 := l1.Point2().X(), l1.Point2().Y()
	x3, y3 := l2.Point1().X(), l2.Point1().Y()
	x4, y4 := l2.Point2().X(), l2.Point2().Y()

	denom := ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
	// The lines are parallel or they overlap. No single point.
	if denom == 0 {
		return pt, false
	}

	xnom := (((x1 * y2) - (y1 * x2)) * (x3 - x4)) - ((x1 - x2) * ((x3 * y4) - (y3 * x4)))
	ynom := (((x1 * y2) - (y1 * x2)) * (y3 - y4)) - ((y1 - y2) * ((x3 * y4) - (y3 * x4)))
	x := xnom / denom
	if x == -0 {
		x = 0
	}
	y := ynom / denom
	if y == -0 {
		y = 0
	}
	return [2]float64{x, y}, true
}

func bigFloat(f float64) *big.Float { return big.NewFloat(f).SetPrec(PrecisionLevelBigFloat) }

// LineIntersectBigFloat find the intersection point (x,y) between two lines if there is one. Ok will be true if it found an interseciton point. Internally uses math/big
// ok being false, means there isn't just one intersection point, there could be zero, or more then one.
// ref: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
func LineIntersectBigFloat(l1, l2 geom.Line) (pt [2]*big.Float, ok bool) {

	x1, y1 := bigFloat(l1.Point1().X()), bigFloat(l1.Point1().Y())
	x2, y2 := bigFloat(l1.Point2().X()), bigFloat(l1.Point2().Y())
	x3, y3 := bigFloat(l2.Point1().X()), bigFloat(l2.Point1().Y())
	x4, y4 := bigFloat(l2.Point2().X()), bigFloat(l2.Point2().Y())

	deltaX12 := bigFloat(0).Sub(x1, x2)
	deltaX34 := bigFloat(0).Sub(x3, x4)
	deltaY12 := bigFloat(0).Sub(y1, y2)
	deltaY34 := bigFloat(0).Sub(y3, y4)
	denom := bigFloat(0).Sub(
		bigFloat(0).Mul(deltaX12, deltaY34),
		bigFloat(0).Mul(deltaY12, deltaX34),
	)

	// The lines are parallel or they overlap. No single point.
	if d, _ := denom.Float64(); d == 0 {
		return pt, false
	}

	xnom := bigFloat(0).Sub(
		bigFloat(0).Mul(
			bigFloat(0).Sub(
				bigFloat(0).Mul(x1, y2),
				bigFloat(0).Mul(y1, x2),
			),
			deltaX34,
		),
		bigFloat(0).Mul(
			deltaX12,
			bigFloat(0).Sub(
				bigFloat(0).Mul(x3, y4),
				bigFloat(0).Mul(y3, x4),
			),
		),
	)
	ynom := bigFloat(0).Sub(
		bigFloat(0).Mul(
			bigFloat(0).Sub(
				bigFloat(0).Mul(x1, y2),
				bigFloat(0).Mul(y1, x2),
			),
			deltaY34,
		),
		bigFloat(0).Mul(
			deltaY12,
			bigFloat(0).Sub(
				bigFloat(0).Mul(x3, y4),
				bigFloat(0).Mul(y3, x4),
			),
		),
	)
	bx := bigFloat(0).Quo(xnom, denom)
	by := bigFloat(0).Quo(ynom, denom)
	return [2]*big.Float{bx, by}, true

}

// SegmentIntersect finds the intersection point (x,y) between two lines if there is one. Ok will be true if it found a point that is on both line segments, otherwise it will be false.
func SegmentIntersect(l1, l2 geom.Line) (pt [2]float64, ok bool) {
	if pt, ok = LineIntersect(l1, l2); !ok {
		if debug {
			log.Printf("Lines don't intersect: %v %v", l1, l2)
		}
		return pt, false
	}
	l1c, l2c := l1.ContainsPoint(pt), l2.ContainsPoint(pt)
	if debug {
		log.Printf("LineIntersect returns %v %v", pt, ok)
		log.Printf("line (%v) contains point(%v) :%v ", l1, pt, l1c)
		log.Printf("line (%v) contains point(%v) :%v ", l2, pt, l2c)
	}
	// Check to see if the pt is on both line segments.
	return pt, l1c && l2c
}
<|endoftext|>


<commit_before>package main

import (
	"bazil.org/fuse/fs"
	"github.com/garyburd/redigo/redis"
	pb "github.com/pandemicsyn/ort/api/proto"
	"golang.org/x/net/context"
	"os"
	"sync"
	"sync/atomic"
	"time"
)

type dirServer struct {
	sync.RWMutex
	rpool     *redis.Pool
	nodes     map[string]*Entry
	nodeCount uint64
}

type Entry struct {
	path  string
	isdir bool
	sync.RWMutex
	attr     *pb.Attr
	parent   string
	nodes    map[string]fs.Node
	UUIDNode int64
}

func (s *dirServer) GetAttr(ctx context.Context, r *pb.DirRequest) (*pb.Attr, error) {
	s.RLock()
	defer s.RUnlock()
	if entry, ok := s.nodes[r.Name]; ok {
		return entry.attr, nil
	}
	return &pb.Attr{Name: r.Name}, nil
}

func (s *dirServer) Create(ctx context.Context, r *pb.FileEnt) (*pb.FileEnt, error) {
	if _, exists := s.nodes[r.Name]; exists {
		return &pb.FileEnt{}, nil
	}
	n := &Entry{
		path:     r.Name,
		UUIDNode: time.Now().UnixNano(),
	}
	ts := time.Now().Unix()
	n.attr = &pb.Attr{
		Inode:  uint64(n.UUIDNode),
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   uint32(0777),
		Name:   r.Name,
	}
	s.nodes[r.Name] = n
	atomic.AddUint64(&s.nodeCount, 1)
	return &pb.FileEnt{Name: n.path, Attr: n.attr}, nil
}

func (s *dirServer) MkDir(ctx context.Context, r *pb.DirEnt) (*pb.DirEnt, error) {
	if _, exists := s.nodes[r.Name]; exists {
		return &pb.DirEnt{}, nil
	}
	n := &Entry{
		path:     r.Name,
		UUIDNode: time.Now().UnixNano(),
	}
	ts := time.Now().Unix()
	n.attr = &pb.Attr{
		Inode:  uint64(n.UUIDNode),
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   uint32(os.ModeDir | 0777),
		Name:   r.Name,
	}
	s.nodes[r.Name] = n
	atomic.AddUint64(&s.nodeCount, 1)
	return &pb.DirEnt{Name: n.path, Attr: n.attr}, nil
}

func (s *dirServer) Lookup(ctx context.Context, r *pb.DirRequest) (*pb.DirEnt, error) {
	s.RLock()
	defer s.RUnlock()
	_, exists := s.nodes[r.Name]
	if !exists {
		return &pb.DirEnt{}, nil
	}
	// fake for now
	ts := time.Now().Unix()
	dattr := &pb.Attr{
		Name:   r.Name,
		Inode:  uint64(time.Now().UnixNano()),
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   1777,
		Valid:  5,
	}
	return &pb.DirEnt{Name: r.Name, Attr: dattr}, nil
}

func (s *dirServer) ReadDirAll(ctx context.Context, f *pb.DirRequest) (*pb.DirEntries, error) {
	return &pb.DirEntries{}, nil
}

func (s *dirServer) Remove(ctx context.Context, f *pb.DirEnt) (*pb.WriteResponse, error) {
	return &pb.WriteResponse{}, nil
}
<commit_msg>Return correct attr's on Lookup()<commit_after>package main

import (
	"os"
	"sync"
	"sync/atomic"
	"time"

	"bazil.org/fuse/fs"
	"github.com/garyburd/redigo/redis"
	pb "github.com/pandemicsyn/ort/api/proto"
	"golang.org/x/net/context"
)

type dirServer struct {
	sync.RWMutex
	rpool     *redis.Pool
	nodes     map[string]*Entry
	nodeCount uint64
}

type Entry struct {
	path  string
	isdir bool
	sync.RWMutex
	attr     *pb.Attr
	parent   string
	nodes    map[string]fs.Node
	UUIDNode int64
}

func (s *dirServer) GetAttr(ctx context.Context, r *pb.DirRequest) (*pb.Attr, error) {
	s.RLock()
	defer s.RUnlock()
	if entry, ok := s.nodes[r.Name]; ok {
		return entry.attr, nil
	}
	return &pb.Attr{Name: r.Name}, nil
}

func (s *dirServer) Create(ctx context.Context, r *pb.FileEnt) (*pb.FileEnt, error) {
	if _, exists := s.nodes[r.Name]; exists {
		return &pb.FileEnt{}, nil
	}
	n := &Entry{
		path:     r.Name,
		UUIDNode: time.Now().UnixNano(),
	}
	ts := time.Now().Unix()
	n.attr = &pb.Attr{
		Inode:  uint64(n.UUIDNode),
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   uint32(0777),
		Name:   r.Name,
	}
	s.nodes[r.Name] = n
	atomic.AddUint64(&s.nodeCount, 1)
	return &pb.FileEnt{Name: n.path, Attr: n.attr}, nil
}

func (s *dirServer) MkDir(ctx context.Context, r *pb.DirEnt) (*pb.DirEnt, error) {
	if _, exists := s.nodes[r.Name]; exists {
		return &pb.DirEnt{}, nil
	}
	n := &Entry{
		path:     r.Name,
		UUIDNode: time.Now().UnixNano(),
	}
	ts := time.Now().Unix()
	n.attr = &pb.Attr{
		Inode:  uint64(n.UUIDNode),
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   uint32(os.ModeDir | 0777),
		Name:   r.Name,
	}
	s.nodes[r.Name] = n
	atomic.AddUint64(&s.nodeCount, 1)
	return &pb.DirEnt{Name: n.path, Attr: n.attr}, nil
}

func (s *dirServer) Lookup(ctx context.Context, r *pb.DirRequest) (*pb.DirEnt, error) {
	s.RLock()
	defer s.RUnlock()
	entry, exists := s.nodes[r.Name]
	if !exists {
		return &pb.DirEnt{}, nil
	}
	return &pb.DirEnt{Name: r.Name, Attr: entry.attr}, nil
}

func (s *dirServer) ReadDirAll(ctx context.Context, f *pb.DirRequest) (*pb.DirEntries, error) {
	return &pb.DirEntries{}, nil
}

func (s *dirServer) Remove(ctx context.Context, f *pb.DirEnt) (*pb.WriteResponse, error) {
	return &pb.WriteResponse{}, nil
}
<|endoftext|>


<commit_before>package install

import (
	"fmt"

	"github.com/go-xorm/builder"
	"github.com/google/uuid"
	"github.com/itchio/butler/butlerd"
	"github.com/itchio/butler/cmd/operate"
	"github.com/itchio/butler/database/models"
	"github.com/itchio/butler/endpoints/fetch"
	"github.com/itchio/butler/installer"
	"github.com/itchio/butler/installer/bfs"
	"github.com/itchio/butler/manager"
	itchio "github.com/itchio/go-itchio"
	"github.com/itchio/hades"
	"github.com/itchio/ox"
	"github.com/itchio/wharf/eos"
	"github.com/itchio/wharf/eos/option"
	"github.com/pkg/errors"
	"github.com/sourcegraph/jsonrpc2"
)

func InstallPlan(rc *butlerd.RequestContext, params butlerd.InstallPlanParams) (*butlerd.InstallPlanResult, error) {
	consumer := rc.Consumer
	conn := rc.GetConn()
	defer rc.PutConn(conn)

	game := fetch.LazyFetchGame(rc, params.GameID)
	consumer.Opf("Planning install for %s", operate.GameToString(game))

	baseUploads := fetch.LazyFetchGameUploads(rc, params.GameID)
	baseUploads = manager.NarrowDownUploads(consumer, game, baseUploads, ox.CurrentRuntime()).Uploads

	// exclude already-installed and currently-installing uploads
	var uploadIDs []interface{}
	for _, u := range baseUploads {
		uploadIDs = append(uploadIDs, u.ID)
	}
	var validUploads []*itchio.Upload
	models.MustSelect(conn, &validUploads, builder.And(
		builder.In("id", uploadIDs...),
		builder.Expr(`not exists (select 1 from caves where upload_id = uploads.id)`),
		builder.Expr(`not exists (select 1 from downloads where upload_id = uploads.id)`),
	), hades.Search{})
	validUploadIDs := make(map[int64]bool)
	for _, u := range validUploads {
		validUploadIDs[u.ID] = true
	}
	// do a little dance to keep the ordering proper
	var uploads []*itchio.Upload
	for _, u := range baseUploads {
		if validUploadIDs[u.ID] {
			uploads = append(uploads, u)
		}
	}

	res := &butlerd.InstallPlanResult{
		Game:    game,
		Uploads: uploads,
	}

	if len(uploads) == 0 {
		consumer.Statf("No compatible uploads, returning early.")
		return res, nil
	}

	info := &butlerd.InstallPlanInfo{}
	res.Info = info

	setResError := func(err error) {
		info.Error = fmt.Sprintf("%+v", err)
		if be, ok := butlerd.AsButlerdError(err); ok {
			info.ErrorCode = be.RpcErrorCode()
			info.ErrorMessage = be.RpcErrorMessage()
		} else {
			info.ErrorCode = int64(jsonrpc2.CodeInternalError)
			info.ErrorMessage = err.Error()
		}
	}

	var upload *itchio.Upload
	if params.UploadID != 0 {
		for _, u := range uploads {
			if u.ID == params.UploadID {
				consumer.Infof("Using specified upload.")
				upload = u
				break
			}
		}
	}

	if upload == nil {
		consumer.Infof("Picking first upload.")
		upload = uploads[0]
	}

	operate.LogUpload(consumer, upload, upload.Build)
	info.Upload = upload
	info.Build = upload.Build

	if upload.Storage == itchio.UploadStorageExternal && operate.IsBadExternalHost(upload.Host) {
		setResError(errors.WithStack(butlerd.CodeUnsupportedHost))
		return res, nil
	}

	sessionID := params.DownloadSessionID
	if sessionID == "" {
		sessionID = uuid.New().String()
		consumer.Infof("No download session ID passed, using %s", sessionID)
	}

	access := operate.AccessForGameID(conn, game.ID)
	client := rc.Client(access.APIKey)

	installParams := &operate.InstallParams{
		Upload: info.Upload,
		Build:  info.Build,
		Access: access,
	}
	sourceURL := operate.MakeSourceURL(client, consumer, sessionID, installParams, "")

	file, err := eos.Open(sourceURL, option.WithConsumer(consumer))
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}
	defer file.Close()

	installerInfo, err := installer.GetInstallerInfo(consumer, file)
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}

	info.Type = string(installerInfo.Type)

	// planning is always for a fresh install
	receiptIn := (*bfs.Receipt)(nil)
	installFolder := ""

	dui, err := operate.AssessDiskUsage(file, receiptIn, installFolder, installerInfo)
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}

	info.DiskUsage = &butlerd.DiskUsageInfo{
		FinalDiskUsage:  dui.FinalDiskUsage,
		NeededFreeSpace: dui.NeededFreeSpace,
		Accuracy:        dui.Accuracy.String(),
	}

	return res, nil
}
<commit_msg>Install.Plan: log error if we failed to plan<commit_after>package install

import (
	"fmt"

	"github.com/go-xorm/builder"
	"github.com/google/uuid"
	"github.com/itchio/butler/butlerd"
	"github.com/itchio/butler/cmd/operate"
	"github.com/itchio/butler/database/models"
	"github.com/itchio/butler/endpoints/fetch"
	"github.com/itchio/butler/installer"
	"github.com/itchio/butler/installer/bfs"
	"github.com/itchio/butler/manager"
	itchio "github.com/itchio/go-itchio"
	"github.com/itchio/hades"
	"github.com/itchio/ox"
	"github.com/itchio/wharf/eos"
	"github.com/itchio/wharf/eos/option"
	"github.com/pkg/errors"
	"github.com/sourcegraph/jsonrpc2"
)

func InstallPlan(rc *butlerd.RequestContext, params butlerd.InstallPlanParams) (*butlerd.InstallPlanResult, error) {
	consumer := rc.Consumer
	conn := rc.GetConn()
	defer rc.PutConn(conn)

	game := fetch.LazyFetchGame(rc, params.GameID)
	consumer.Opf("Planning install for %s", operate.GameToString(game))

	baseUploads := fetch.LazyFetchGameUploads(rc, params.GameID)
	baseUploads = manager.NarrowDownUploads(consumer, game, baseUploads, ox.CurrentRuntime()).Uploads

	// exclude already-installed and currently-installing uploads
	var uploadIDs []interface{}
	for _, u := range baseUploads {
		uploadIDs = append(uploadIDs, u.ID)
	}
	var validUploads []*itchio.Upload
	models.MustSelect(conn, &validUploads, builder.And(
		builder.In("id", uploadIDs...),
		builder.Expr(`not exists (select 1 from caves where upload_id = uploads.id)`),
		builder.Expr(`not exists (select 1 from downloads where upload_id = uploads.id)`),
	), hades.Search{})
	validUploadIDs := make(map[int64]bool)
	for _, u := range validUploads {
		validUploadIDs[u.ID] = true
	}
	// do a little dance to keep the ordering proper
	var uploads []*itchio.Upload
	for _, u := range baseUploads {
		if validUploadIDs[u.ID] {
			uploads = append(uploads, u)
		}
	}

	res := &butlerd.InstallPlanResult{
		Game:    game,
		Uploads: uploads,
	}

	if len(uploads) == 0 {
		consumer.Statf("No compatible uploads, returning early.")
		return res, nil
	}

	info := &butlerd.InstallPlanInfo{}
	res.Info = info

	setResError := func(err error) {
		consumer.Errorf("Planning failed: %+v", err)
		info.Error = fmt.Sprintf("%+v", err)
		if be, ok := butlerd.AsButlerdError(err); ok {
			info.ErrorCode = be.RpcErrorCode()
			info.ErrorMessage = be.RpcErrorMessage()
		} else {
			info.ErrorCode = int64(jsonrpc2.CodeInternalError)
			info.ErrorMessage = err.Error()
		}
	}

	var upload *itchio.Upload
	if params.UploadID != 0 {
		for _, u := range uploads {
			if u.ID == params.UploadID {
				consumer.Infof("Using specified upload.")
				upload = u
				break
			}
		}
	}

	if upload == nil {
		consumer.Infof("Picking first upload.")
		upload = uploads[0]
	}

	operate.LogUpload(consumer, upload, upload.Build)
	info.Upload = upload
	info.Build = upload.Build

	if upload.Storage == itchio.UploadStorageExternal && operate.IsBadExternalHost(upload.Host) {
		setResError(errors.WithStack(butlerd.CodeUnsupportedHost))
		return res, nil
	}

	sessionID := params.DownloadSessionID
	if sessionID == "" {
		sessionID = uuid.New().String()
		consumer.Infof("No download session ID passed, using %s", sessionID)
	}

	access := operate.AccessForGameID(conn, game.ID)
	client := rc.Client(access.APIKey)

	installParams := &operate.InstallParams{
		Upload: info.Upload,
		Build:  info.Build,
		Access: access,
	}
	sourceURL := operate.MakeSourceURL(client, consumer, sessionID, installParams, "")

	file, err := eos.Open(sourceURL, option.WithConsumer(consumer))
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}
	defer file.Close()

	installerInfo, err := installer.GetInstallerInfo(consumer, file)
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}

	info.Type = string(installerInfo.Type)

	// planning is always for a fresh install
	receiptIn := (*bfs.Receipt)(nil)
	installFolder := ""

	dui, err := operate.AssessDiskUsage(file, receiptIn, installFolder, installerInfo)
	if err != nil {
		setResError(errors.WithStack(err))
		return res, nil
	}

	info.DiskUsage = &butlerd.DiskUsageInfo{
		FinalDiskUsage:  dui.FinalDiskUsage,
		NeededFreeSpace: dui.NeededFreeSpace,
		Accuracy:        dui.Accuracy.String(),
	}

	return res, nil
}
<|endoftext|>


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

// +build linux

package unix_test

import (
	"io/ioutil"
	"os"
	"testing"
	"time"

	"golang.org/x/sys/unix"
)

func TestFchmodat(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")
	os.Symlink("file1", "symlink1")

	err := unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, 0)
	if err != nil {
		t.Fatalf("Fchmodat: unexpected error: %v", err)
	}

	fi, err := os.Stat("file1")
	if err != nil {
		t.Fatal(err)
	}

	if fi.Mode() != 0444 {
		t.Errorf("Fchmodat: failed to change mode: expected %v, got %v", 0444, fi.Mode())
	}

	err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, unix.AT_SYMLINK_NOFOLLOW)
	if err != unix.EOPNOTSUPP {
		t.Fatalf("Fchmodat: unexpected error: %v, expected EOPNOTSUPP", err)
	}
}

func TestIoctlGetInt(t *testing.T) {
	f, err := os.Open("/dev/random")
	if err != nil {
		t.Fatalf("failed to open device: %v", err)
	}
	defer f.Close()

	v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT)
	if err != nil {
		t.Fatalf("failed to perform ioctl: %v", err)
	}

	t.Logf("%d bits of entropy available", v)
}

func TestPpoll(t *testing.T) {
	f, cleanup := mktmpfifo(t)
	defer cleanup()

	const timeout = 100 * time.Millisecond

	ok := make(chan bool, 1)
	go func() {
		select {
		case <-time.After(10 * timeout):
			t.Errorf("Ppoll: failed to timeout after %d", 10*timeout)
		case <-ok:
		}
	}()

	fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
	timeoutTs := unix.NsecToTimespec(int64(timeout))
	n, err := unix.Ppoll(fds, &timeoutTs, nil)
	ok <- true
	if err != nil {
		t.Errorf("Ppoll: unexpected error: %v", err)
		return
	}
	if n != 0 {
		t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0)
		return
	}
}

func TestTime(t *testing.T) {
	var ut unix.Time_t
	ut2, err := unix.Time(&ut)
	if err != nil {
		t.Fatalf("Time: %v", err)
	}
	if ut != ut2 {
		t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut)
	}

	var now time.Time

	for i := 0; i < 10; i++ {
		ut, err = unix.Time(nil)
		if err != nil {
			t.Fatalf("Time: %v", err)
		}

		now = time.Now()

		if int64(ut) == now.Unix() {
			return
		}
	}

	t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix())
}

func TestUtime(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")

	buf := &unix.Utimbuf{
		Modtime: 12345,
	}

	err := unix.Utime("file1", buf)
	if err != nil {
		t.Fatalf("Utime: %v", err)
	}

	fi, err := os.Stat("file1")
	if err != nil {
		t.Fatal(err)
	}

	if fi.ModTime().Unix() != 12345 {
		t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix())
	}
}

func TestUtimesNanoAt(t *testing.T) {
	defer chtmpdir(t)()

	symlink := "symlink1"
	os.Remove(symlink)
	err := os.Symlink("nonexisting", symlink)
	if err != nil {
		t.Fatal(err)
	}

	ts := []unix.Timespec{
		{Sec: 1111, Nsec: 2222},
		{Sec: 3333, Nsec: 4444},
	}
	err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW)
	if err != nil {
		t.Fatalf("UtimesNanoAt: %v", err)
	}

	var st unix.Stat_t
	err = unix.Lstat(symlink, &st)
	if err != nil {
		t.Fatalf("Lstat: %v", err)
	}
	if st.Atim != ts[0] {
		t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim)
	}
	if st.Mtim != ts[1] {
		t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim)
	}
}

func TestGetrlimit(t *testing.T) {
	var rlim unix.Rlimit
	err := unix.Getrlimit(unix.RLIMIT_AS, &rlim)
	if err != nil {
		t.Fatalf("Getrlimit: %v", err)
	}
}

func TestSelect(t *testing.T) {
	_, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
	if err != nil {
		t.Fatalf("Select: %v", err)
	}
}

func TestFstatat(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")

	var st1 unix.Stat_t
	err := unix.Stat("file1", &st1)
	if err != nil {
		t.Fatalf("Stat: %v", err)
	}

	var st2 unix.Stat_t
	err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0)
	if err != nil {
		t.Fatalf("Fstatat: %v", err)
	}

	if st1 != st2 {
		t.Errorf("Fstatat: returned stat does not match Stat")
	}

	os.Symlink("file1", "symlink1")

	err = unix.Lstat("symlink1", &st1)
	if err != nil {
		t.Fatalf("Lstat: %v", err)
	}

	err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW)
	if err != nil {
		t.Fatalf("Fstatat: %v", err)
	}

	if st1 != st2 {
		t.Errorf("Fstatat: returned stat does not match Lstat")
	}
}

// utilities taken from os/os_test.go

func touch(t *testing.T, name string) {
	f, err := os.Create(name)
	if err != nil {
		t.Fatal(err)
	}
	if err := f.Close(); err != nil {
		t.Fatal(err)
	}
}

// chtmpdir changes the working directory to a new temporary directory and
// provides a cleanup function. Used when PWD is read-only.
func chtmpdir(t *testing.T) func() {
	oldwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	d, err := ioutil.TempDir("", "test")
	if err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	return func() {
		if err := os.Chdir(oldwd); err != nil {
			t.Fatalf("chtmpdir: %v", err)
		}
		os.RemoveAll(d)
	}
}
<commit_msg>unix: add timeout tests for Select and Pselect on Linux<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux

package unix_test

import (
	"io/ioutil"
	"os"
	"testing"
	"time"

	"golang.org/x/sys/unix"
)

func TestFchmodat(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")
	os.Symlink("file1", "symlink1")

	err := unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, 0)
	if err != nil {
		t.Fatalf("Fchmodat: unexpected error: %v", err)
	}

	fi, err := os.Stat("file1")
	if err != nil {
		t.Fatal(err)
	}

	if fi.Mode() != 0444 {
		t.Errorf("Fchmodat: failed to change mode: expected %v, got %v", 0444, fi.Mode())
	}

	err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, unix.AT_SYMLINK_NOFOLLOW)
	if err != unix.EOPNOTSUPP {
		t.Fatalf("Fchmodat: unexpected error: %v, expected EOPNOTSUPP", err)
	}
}

func TestIoctlGetInt(t *testing.T) {
	f, err := os.Open("/dev/random")
	if err != nil {
		t.Fatalf("failed to open device: %v", err)
	}
	defer f.Close()

	v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT)
	if err != nil {
		t.Fatalf("failed to perform ioctl: %v", err)
	}

	t.Logf("%d bits of entropy available", v)
}

func TestPpoll(t *testing.T) {
	f, cleanup := mktmpfifo(t)
	defer cleanup()

	const timeout = 100 * time.Millisecond

	ok := make(chan bool, 1)
	go func() {
		select {
		case <-time.After(10 * timeout):
			t.Errorf("Ppoll: failed to timeout after %d", 10*timeout)
		case <-ok:
		}
	}()

	fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
	timeoutTs := unix.NsecToTimespec(int64(timeout))
	n, err := unix.Ppoll(fds, &timeoutTs, nil)
	ok <- true
	if err != nil {
		t.Errorf("Ppoll: unexpected error: %v", err)
		return
	}
	if n != 0 {
		t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0)
		return
	}
}

func TestTime(t *testing.T) {
	var ut unix.Time_t
	ut2, err := unix.Time(&ut)
	if err != nil {
		t.Fatalf("Time: %v", err)
	}
	if ut != ut2 {
		t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut)
	}

	var now time.Time

	for i := 0; i < 10; i++ {
		ut, err = unix.Time(nil)
		if err != nil {
			t.Fatalf("Time: %v", err)
		}

		now = time.Now()

		if int64(ut) == now.Unix() {
			return
		}
	}

	t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix())
}

func TestUtime(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")

	buf := &unix.Utimbuf{
		Modtime: 12345,
	}

	err := unix.Utime("file1", buf)
	if err != nil {
		t.Fatalf("Utime: %v", err)
	}

	fi, err := os.Stat("file1")
	if err != nil {
		t.Fatal(err)
	}

	if fi.ModTime().Unix() != 12345 {
		t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix())
	}
}

func TestUtimesNanoAt(t *testing.T) {
	defer chtmpdir(t)()

	symlink := "symlink1"
	os.Remove(symlink)
	err := os.Symlink("nonexisting", symlink)
	if err != nil {
		t.Fatal(err)
	}

	ts := []unix.Timespec{
		{Sec: 1111, Nsec: 2222},
		{Sec: 3333, Nsec: 4444},
	}
	err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW)
	if err != nil {
		t.Fatalf("UtimesNanoAt: %v", err)
	}

	var st unix.Stat_t
	err = unix.Lstat(symlink, &st)
	if err != nil {
		t.Fatalf("Lstat: %v", err)
	}
	if st.Atim != ts[0] {
		t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim)
	}
	if st.Mtim != ts[1] {
		t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim)
	}
}

func TestGetrlimit(t *testing.T) {
	var rlim unix.Rlimit
	err := unix.Getrlimit(unix.RLIMIT_AS, &rlim)
	if err != nil {
		t.Fatalf("Getrlimit: %v", err)
	}
}

func TestSelect(t *testing.T) {
	_, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
	if err != nil {
		t.Fatalf("Select: %v", err)
	}

	dur := 150 * time.Millisecond
	tv := unix.NsecToTimeval(int64(dur))
	start := time.Now()
	_, err = unix.Select(0, nil, nil, nil, &tv)
	took := time.Since(start)
	if err != nil {
		t.Fatalf("Select: %v", err)
	}

	if took < dur {
		t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
	}
}

func TestPselect(t *testing.T) {
	_, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil)
	if err != nil {
		t.Fatalf("Pselect: %v", err)
	}

	dur := 2500 * time.Microsecond
	ts := unix.NsecToTimespec(int64(dur))
	start := time.Now()
	_, err = unix.Pselect(0, nil, nil, nil, &ts, nil)
	took := time.Since(start)
	if err != nil {
		t.Fatalf("Pselect: %v", err)
	}

	if took < dur {
		t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took)
	}
}

func TestFstatat(t *testing.T) {
	defer chtmpdir(t)()

	touch(t, "file1")

	var st1 unix.Stat_t
	err := unix.Stat("file1", &st1)
	if err != nil {
		t.Fatalf("Stat: %v", err)
	}

	var st2 unix.Stat_t
	err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0)
	if err != nil {
		t.Fatalf("Fstatat: %v", err)
	}

	if st1 != st2 {
		t.Errorf("Fstatat: returned stat does not match Stat")
	}

	os.Symlink("file1", "symlink1")

	err = unix.Lstat("symlink1", &st1)
	if err != nil {
		t.Fatalf("Lstat: %v", err)
	}

	err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW)
	if err != nil {
		t.Fatalf("Fstatat: %v", err)
	}

	if st1 != st2 {
		t.Errorf("Fstatat: returned stat does not match Lstat")
	}
}

// utilities taken from os/os_test.go

func touch(t *testing.T, name string) {
	f, err := os.Create(name)
	if err != nil {
		t.Fatal(err)
	}
	if err := f.Close(); err != nil {
		t.Fatal(err)
	}
}

// chtmpdir changes the working directory to a new temporary directory and
// provides a cleanup function. Used when PWD is read-only.
func chtmpdir(t *testing.T) func() {
	oldwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	d, err := ioutil.TempDir("", "test")
	if err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatalf("chtmpdir: %v", err)
	}
	return func() {
		if err := os.Chdir(oldwd); err != nil {
			t.Fatalf("chtmpdir: %v", err)
		}
		os.RemoveAll(d)
	}
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/base64"
	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/labstack/echo"
	"github.com/danjac/podbaby/config"
	"net/http"
	"time"

	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/gorilla/securecookie"
)

const sessionTimeout = 24 * 30

type session interface {
	write(*echo.Context, string, interface{}) error
	read(*echo.Context, string, interface{}) (bool, error)
	readInt(*echo.Context, string) (int, bool, error)
}

type secureCookieSession struct {
	*securecookie.SecureCookie
	isSecure bool
}

func (s *secureCookieSession) write(c *echo.Context, key string, value interface{}) error {
	encoded, err := s.Encode(key, value)
	if err == nil {
		cookie := &http.Cookie{
			Name:     key,
			Value:    encoded,
			Expires:  time.Now().Add(time.Hour * sessionTimeout),
			Secure:   s.isSecure,
			HttpOnly: true,
			Path:     "/",
		}
		http.SetCookie(c.Response(), cookie)
	}
	return err
}

func (s *secureCookieSession) read(c *echo.Context, key string, dst interface{}) (bool, error) {
	cookie, err := c.Request().Cookie(key)
	if err == http.ErrNoCookie {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	err = s.Decode(key, cookie.Value, dst)
	return err != nil, err
}

func (s *secureCookieSession) readInt(c *echo.Context, key string) (int, bool, error) {
	var rv int
	ok, err := s.read(c, key, &rv)
	return rv, ok, err
}

func newSession(cfg *config.Config) session {
	secureCookieKey, _ := base64.StdEncoding.DecodeString(cfg.SecureCookieKey)
	cookie := securecookie.New(
		[]byte(cfg.SecretKey),
		secureCookieKey,
	)
	return &secureCookieSession{
		SecureCookie: cookie,
		isSecure:     !cfg.IsDev(),
	}
}
<commit_msg>Test fixes<commit_after>package api

import (
	"encoding/base64"
	"fmt"
	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/labstack/echo"
	"github.com/danjac/podbaby/config"
	"net/http"
	"time"

	"github.com/danjac/podbaby/api/Godeps/_workspace/src/github.com/gorilla/securecookie"
)

const sessionTimeout = 24 * 30

type session interface {
	write(*echo.Context, string, interface{}) error
	read(*echo.Context, string, interface{}) (bool, error)
	readInt(*echo.Context, string) (int, bool, error)
}

type secureCookieSession struct {
	*securecookie.SecureCookie
	isSecure bool
}

func (s *secureCookieSession) write(c *echo.Context, key string, value interface{}) error {
	encoded, err := s.Encode(key, value)
	if err == nil {
		cookie := &http.Cookie{
			Name:     key,
			Value:    encoded,
			Expires:  time.Now().Add(time.Hour * sessionTimeout),
			Secure:   s.isSecure,
			HttpOnly: true,
			Path:     "/",
		}
		http.SetCookie(c.Response(), cookie)
	}
	return err
}

func (s *secureCookieSession) read(c *echo.Context, key string, dst interface{}) (bool, error) {
	cookie, err := c.Request().Cookie(key)
	if err == http.ErrNoCookie {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	err = s.Decode(key, cookie.Value, dst)
	fmt.Println("ERROR", err)
	return err != nil, err
}

func (s *secureCookieSession) readInt(c *echo.Context, key string) (int, bool, error) {
	var rv int
	ok, err := s.read(c, key, &rv)
	return rv, ok, err
}

func newSession(cfg *config.Config) session {
	secureCookieKey, _ := base64.StdEncoding.DecodeString(cfg.SecureCookieKey)
	cookie := securecookie.New(
		[]byte(cfg.SecretKey),
		secureCookieKey,
	)
	return &secureCookieSession{
		SecureCookie: cookie,
		isSecure:     !cfg.IsDev(),
	}
}
<|endoftext|>