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

package tp

import (
	"context"
	"crypto/tls"
	"math"
	"net"
	"sync"
	"time"

	"github.com/henrylee2cn/goutil"
	"github.com/henrylee2cn/goutil/errors"
)

// Peer peer which is server or client.
type Peer struct {
	PullRouter           *Router
	PushRouter           *Router
	pluginContainer      PluginContainer
	sessHub              *SessionHub
	closeCh              chan struct{}
	freeContext          *readHandleCtx
	ctxLock              sync.Mutex
	defaultReadTimeout   int64 // time.Duration // readdeadline for underlying net.Conn
	defaultWriteTimeout  int64 // time.Duration // writedeadline for underlying net.Conn
	tlsConfig            *tls.Config
	slowCometDuration    time.Duration
	defaultHeaderCodec   string
	defaultBodyCodec     string
	defaultBodyGzipLevel int32
	printBody            bool
	mu                   sync.Mutex

	// for client role
	defaultDialTimeout time.Duration

	// for server role
	listenAddrs []string
	listens     []net.Listener
}

// NewPeer creates a new peer.
func NewPeer(cfg *PeerConfig, plugin ...Plugin) *Peer {
	var slowCometDuration time.Duration = math.MaxInt64
	if cfg.SlowCometDuration > 0 {
		slowCometDuration = cfg.SlowCometDuration
	}
	var pluginContainer = newPluginContainer()
	if err := pluginContainer.Add(plugin...); err != nil {
		Fatalf("%v", err)
	}
	var p = &Peer{
		PullRouter:           newPullRouter(pluginContainer),
		PushRouter:           newPushRouter(pluginContainer),
		pluginContainer:      pluginContainer,
		sessHub:              newSessionHub(),
		defaultReadTimeout:   int64(cfg.DefaultReadTimeout),
		defaultWriteTimeout:  int64(cfg.DefaultWriteTimeout),
		closeCh:              make(chan struct{}),
		slowCometDuration:    slowCometDuration,
		defaultDialTimeout:   cfg.DefaultDialTimeout,
		listenAddrs:          cfg.ListenAddrs,
		defaultHeaderCodec:   cfg.DefaultHeaderCodec,
		defaultBodyCodec:     cfg.DefaultBodyCodec,
		defaultBodyGzipLevel: cfg.DefaultBodyGzipLevel,
		printBody:            cfg.PrintBody,
	}
	addPeer(p)
	return p
}

// GetSession gets the session by id.
func (p *Peer) GetSession(sessionId string) (Session, bool) {
	return p.sessHub.Get(sessionId)
}

// ServeConn serves the connection and returns a session.
func (p *Peer) ServeConn(conn net.Conn, id ...string) Session {
	var session = newSession(p, conn, id...)
	p.sessHub.Set(session)
	return session
}

// Dial connects with the peer of the destination address.
func (p *Peer) Dial(addr string, id ...string) (Session, error) {
	var conn, err = net.DialTimeout("tcp", addr, p.defaultDialTimeout)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	var sess = newSession(p, conn, id...)
	if err = p.pluginContainer.PostDial(sess); err != nil {
		Printf("post dial fail (addr: %s, id: %s) ", addr, sess.Id())
		sess.Close()
		return nil, err
	}
	Go(sess.startReadAndHandle)
	p.sessHub.Set(sess)
	Printf("dial ok (addr: %s, id: %s)", addr, sess.Id())
	return sess, nil
}

// DialContext connects with the peer of the destination address,
// using the provided context.
func (p *Peer) DialContext(ctx context.Context, addr string, id ...string) (Session, error) {
	var d net.Dialer
	var conn, err = d.DialContext(ctx, "tcp", addr)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	var sess = newSession(p, conn, id...)
	if err = p.pluginContainer.PostDial(sess); err != nil {
		Printf("post dial fail (addr: %s, id: %s) ", addr, sess.Id())
		sess.Close()
		return nil, err
	}
	Go(sess.startReadAndHandle)
	p.sessHub.Set(sess)
	Printf("dial ok (addr: %s, id: %s)", addr, sess.Id())
	return sess, nil
}

// ErrListenClosed listener is closed error.
var ErrListenClosed = errors.New("listener is closed")

// Listen turns on the listening service.
func (p *Peer) Listen() error {
	var (
		wg    sync.WaitGroup
		count = len(p.listenAddrs)
		errCh = make(chan error, count)
	)
	wg.Add(count)
	for _, addr := range p.listenAddrs {
		go func(addr string) {
			defer wg.Done()
			errCh <- p.listen(addr)
		}(addr)
	}
	wg.Wait()
	close(errCh)
	var errs error
	for err := range errCh {
		e := err
		errs = errors.Append(errs, e)
	}
	return errs
}

func (p *Peer) listen(addr string) error {
	var lis, err = listen(addr, p.tlsConfig)
	if err != nil {
		Fatalf("%v", err)
	}
	p.listens = append(p.listens, lis)
	defer lis.Close()

	Printf("listen ok (addr: %s)", addr)

	var (
		tempDelay time.Duration // how long to sleep on accept failure
		closeCh   = p.closeCh
	)
	for {
		rw, e := lis.Accept()
		if e != nil {
			select {
			case <-closeCh:
				return ErrListenClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}

				Tracef("accept error: %s; retrying in %v", e.Error(), tempDelay)

				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0

		func(sess *session) {
			Go(func() {
				if err := p.pluginContainer.PostAccept(sess); err != nil {
					sess.Close()
					Tracef("accept session(addr: %s, id: %s) error: %s", sess.RemoteIp(), sess.Id(), err.Error())
					return
				}
				Tracef("accept session(addr: %s, id: %s) ok", sess.RemoteIp(), sess.Id())
				p.sessHub.Set(sess)
				sess.startReadAndHandle()
			})
		}(newSession(p, rw))
	}
}

// Close closes peer.
func (p *Peer) Close() (err error) {
	defer func() {
		if p := recover(); p != nil {
			err = errors.Errorf("panic:\n%v\n%s", p, goutil.PanicTrace(2))
		}
	}()
	close(p.closeCh)
	delete(peers.list, p)
	var (
		count int
		errCh = make(chan error, 10)
	)
	p.sessHub.Range(func(sess *session) bool {
		count++
		Go(func() {
			errCh <- sess.Close()
		})
		return true
	})
	for i := 0; i < count; i++ {
		err = errors.Merge(err, <-errCh)
	}
	close(errCh)
	return err
}

func (p *Peer) getContext(s *session, withWg bool) *readHandleCtx {
	p.ctxLock.Lock()
	if withWg {
		// count get context
		s.graceCtxWaitGroup.Add(1)
	}
	ctx := p.freeContext
	if ctx == nil {
		ctx = newReadHandleCtx()
	} else {
		p.freeContext = ctx.next
	}
	ctx.reInit(s)
	p.ctxLock.Unlock()
	return ctx
}

func (p *Peer) putContext(ctx *readHandleCtx, withWg bool) {
	p.ctxLock.Lock()
	defer func() {
		recover()
		p.ctxLock.Unlock()
	}()
	if withWg {
		// count get context
		ctx.sess.graceCtxWaitGroup.Done()
	}
	ctx.clean()
	ctx.next = p.freeContext
	p.freeContext = ctx
}
<commit_msg>Optimization the accepting connection  strategy of overflow<commit_after>// Copyright 2015-2017 HenryLee. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tp

import (
	"context"
	"crypto/tls"
	"math"
	"net"
	"sync"
	"time"

	"github.com/henrylee2cn/goutil"
	"github.com/henrylee2cn/goutil/errors"
)

// Peer peer which is server or client.
type Peer struct {
	PullRouter           *Router
	PushRouter           *Router
	pluginContainer      PluginContainer
	sessHub              *SessionHub
	closeCh              chan struct{}
	freeContext          *readHandleCtx
	ctxLock              sync.Mutex
	defaultReadTimeout   int64 // time.Duration // readdeadline for underlying net.Conn
	defaultWriteTimeout  int64 // time.Duration // writedeadline for underlying net.Conn
	tlsConfig            *tls.Config
	slowCometDuration    time.Duration
	defaultHeaderCodec   string
	defaultBodyCodec     string
	defaultBodyGzipLevel int32
	printBody            bool
	mu                   sync.Mutex

	// for client role
	defaultDialTimeout time.Duration

	// for server role
	listenAddrs []string
	listens     []net.Listener
}

// NewPeer creates a new peer.
func NewPeer(cfg *PeerConfig, plugin ...Plugin) *Peer {
	var slowCometDuration time.Duration = math.MaxInt64
	if cfg.SlowCometDuration > 0 {
		slowCometDuration = cfg.SlowCometDuration
	}
	var pluginContainer = newPluginContainer()
	if err := pluginContainer.Add(plugin...); err != nil {
		Fatalf("%v", err)
	}
	var p = &Peer{
		PullRouter:           newPullRouter(pluginContainer),
		PushRouter:           newPushRouter(pluginContainer),
		pluginContainer:      pluginContainer,
		sessHub:              newSessionHub(),
		defaultReadTimeout:   int64(cfg.DefaultReadTimeout),
		defaultWriteTimeout:  int64(cfg.DefaultWriteTimeout),
		closeCh:              make(chan struct{}),
		slowCometDuration:    slowCometDuration,
		defaultDialTimeout:   cfg.DefaultDialTimeout,
		listenAddrs:          cfg.ListenAddrs,
		defaultHeaderCodec:   cfg.DefaultHeaderCodec,
		defaultBodyCodec:     cfg.DefaultBodyCodec,
		defaultBodyGzipLevel: cfg.DefaultBodyGzipLevel,
		printBody:            cfg.PrintBody,
	}
	addPeer(p)
	return p
}

// GetSession gets the session by id.
func (p *Peer) GetSession(sessionId string) (Session, bool) {
	return p.sessHub.Get(sessionId)
}

// ServeConn serves the connection and returns a session.
func (p *Peer) ServeConn(conn net.Conn, id ...string) Session {
	var session = newSession(p, conn, id...)
	p.sessHub.Set(session)
	return session
}

// Dial connects with the peer of the destination address.
func (p *Peer) Dial(addr string, id ...string) (Session, error) {
	var conn, err = net.DialTimeout("tcp", addr, p.defaultDialTimeout)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	var sess = newSession(p, conn, id...)
	if err = p.pluginContainer.PostDial(sess); err != nil {
		Printf("post dial fail (addr: %s, id: %s) ", addr, sess.Id())
		sess.Close()
		return nil, err
	}
	Go(sess.startReadAndHandle)
	p.sessHub.Set(sess)
	Printf("dial ok (addr: %s, id: %s)", addr, sess.Id())
	return sess, nil
}

// DialContext connects with the peer of the destination address,
// using the provided context.
func (p *Peer) DialContext(ctx context.Context, addr string, id ...string) (Session, error) {
	var d net.Dialer
	var conn, err = d.DialContext(ctx, "tcp", addr)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	var sess = newSession(p, conn, id...)
	if err = p.pluginContainer.PostDial(sess); err != nil {
		Printf("post dial fail (addr: %s, id: %s) ", addr, sess.Id())
		sess.Close()
		return nil, err
	}
	Go(sess.startReadAndHandle)
	p.sessHub.Set(sess)
	Printf("dial ok (addr: %s, id: %s)", addr, sess.Id())
	return sess, nil
}

// ErrListenClosed listener is closed error.
var ErrListenClosed = errors.New("listener is closed")

// Listen turns on the listening service.
func (p *Peer) Listen() error {
	var (
		wg    sync.WaitGroup
		count = len(p.listenAddrs)
		errCh = make(chan error, count)
	)
	wg.Add(count)
	for _, addr := range p.listenAddrs {
		go func(addr string) {
			defer wg.Done()
			errCh <- p.listen(addr)
		}(addr)
	}
	wg.Wait()
	close(errCh)
	var errs error
	for err := range errCh {
		e := err
		errs = errors.Append(errs, e)
	}
	return errs
}

func (p *Peer) listen(addr string) error {
	var lis, err = listen(addr, p.tlsConfig)
	if err != nil {
		Fatalf("%v", err)
	}
	p.listens = append(p.listens, lis)
	defer lis.Close()

	Printf("listen ok (addr: %s)", addr)

	var (
		tempDelay time.Duration // how long to sleep on accept failure
		closeCh   = p.closeCh
	)
	for {
		rw, e := lis.Accept()
		if e != nil {
			select {
			case <-closeCh:
				return ErrListenClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}

				Tracef("accept error: %s; retrying in %v", e.Error(), tempDelay)

				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0

		func(sess *session) {
		TRYGO:
			if !Go(func() {
				if err := p.pluginContainer.PostAccept(sess); err != nil {
					sess.Close()
					Tracef("accept session(addr: %s, id: %s) error: %s", sess.RemoteIp(), sess.Id(), err.Error())
					return
				}
				Tracef("accept session(addr: %s, id: %s) ok", sess.RemoteIp(), sess.Id())
				p.sessHub.Set(sess)
				sess.startReadAndHandle()
			}) {
				time.Sleep(time.Second)
				goto TRYGO
			}
		}(newSession(p, rw))
	}
}

// Close closes peer.
func (p *Peer) Close() (err error) {
	defer func() {
		if p := recover(); p != nil {
			err = errors.Errorf("panic:\n%v\n%s", p, goutil.PanicTrace(2))
		}
	}()
	close(p.closeCh)
	delete(peers.list, p)
	var (
		count int
		errCh = make(chan error, 10)
	)
	p.sessHub.Range(func(sess *session) bool {
		count++
		Go(func() {
			errCh <- sess.Close()
		})
		return true
	})
	for i := 0; i < count; i++ {
		err = errors.Merge(err, <-errCh)
	}
	close(errCh)
	return err
}

func (p *Peer) getContext(s *session, withWg bool) *readHandleCtx {
	p.ctxLock.Lock()
	if withWg {
		// count get context
		s.graceCtxWaitGroup.Add(1)
	}
	ctx := p.freeContext
	if ctx == nil {
		ctx = newReadHandleCtx()
	} else {
		p.freeContext = ctx.next
	}
	ctx.reInit(s)
	p.ctxLock.Unlock()
	return ctx
}

func (p *Peer) putContext(ctx *readHandleCtx, withWg bool) {
	p.ctxLock.Lock()
	defer func() {
		recover()
		p.ctxLock.Unlock()
	}()
	if withWg {
		// count get context
		ctx.sess.graceCtxWaitGroup.Done()
	}
	ctx.clean()
	ctx.next = p.freeContext
	p.freeContext = ctx
}
<|endoftext|>


<commit_before>package gontpd

import (
	"context"
	"fmt"
	"math/bits"
	"time"

	"github.com/beevik/ntp"
)

const (
	ReplyCount           = 8
	MaxRootDelay         = 10 * time.Second
	MaxStratum     uint8 = 15
	minFilterCount       = 3
	maxInterval          = 1024 * time.Second
	minInterval          = 4 * time.Second
	reachStable    uint8 = 1<<8 - 1
	phi                  = 15 * time.Microsecond
)

const (
	stateInit = iota
	stateInvalid
	stateTemporaryDown
	stateSyncing
	stateStable
)

const (
	NoLeap uint8 = iota
	LeapIns
	LeapDel
	NotSync
)

const (
	queryMinInterval = 5 * time.Second
	queryMaxInterval = (1 << 12) * time.Minute
)

var (
	peerTransTable []peerTransitionFunc
	epoch          = time.Unix(0, 0)
)

type peer struct {
	addr       string
	filter     [ReplyCount]*filter
	referTime  time.Time
	updateAt   time.Time
	interval   time.Duration
	offset     time.Duration
	delay      time.Duration
	rootDelay  time.Duration
	rootDisp   time.Duration
	dispersion time.Duration

	filterIndex int
	best        int
	queryCount  int
	referId     uint32
	poll        int8
	leap        uint8
	reach       uint8
	stratum     uint8
	state       uint8
}

type filter struct {
	updateAt   time.Time
	offset     time.Duration
	delay      time.Duration
	dispersion time.Duration
	resp       *ntp.Response
}

func peerInit(p *peer, resp *ntp.Response, err error) {
	if p.queryCount < minFilterCount {
		// keep init
		Debug.Printf("query Count:%d keep initing", p.queryCount)
		return
	}

	if p.reach > 1 {
		p.state = stateSyncing
		Info.Printf("%s init -> syncing", p.addr)
		return
	}

	Warn.Printf("peer:%s has no good query while initing", p.addr)
	p.state = stateInvalid
	Info.Printf("%s init -> invalid", p.addr)
}

func peerInvalid(p *peer, resp *ntp.Response, err error) {
	Error.Fatal("we should not go into here")
}

func peerTemporaryDown(p *peer, resp *ntp.Response, err error) {
	Info.Printf("%s temporary down", p.addr)
	if p.reach&3 != 0 {
		p.state = stateSyncing
		Info.Printf("%s down -> syncing", p.addr)
		return
	}

	p.interval = time.Duration(8-bits.OnesCount8(p.reach)) * time.Minute
}

func peerSyncing(p *peer, resp *ntp.Response, err error) {
	if p.reach&3 == 0 {
		p.state = stateTemporaryDown
		Info.Printf("%s syncing -> temporary down", p.addr)
		p.interval = minInterval
		return
	}

	if p.reach == reachStable {
		Info.Printf("%s syncing -> stable", p.addr)
		p.state = stateStable
	}

	if p.checkFilter() {
		syncClock(p)
	}
	p.interval = time.Duration(bits.OnesCount8(p.reach)) * (10 * time.Second)
}
func peerStable(p *peer, resp *ntp.Response, err error) {

	if err != nil || p.reach != reachStable {
		p.state = stateSyncing
		Info.Printf("%s stable -> syncing", p.addr)
		return
	}

	if p.checkFilter() {
		syncClock(p)
	}
	// offset     interval
	// 0.128s  -> 1024s
	// 0.005s  -> 4s
	p.interval = secondToDuration(absDuration(p.offset).Seconds()*-8992.68 + 1065.46)
}

func syncClock(p *peer) {
	if DebugFlag&NoSyncClock != 0 {
		Debug.Printf("syncClock to:%s, offset:%s", p.addr, p.offset)
		return
	}
	// find median offset from all peers
	select {
	case syncLock <- struct{}{}:
	default:
	}
}

func init() {
	peerTransTable = []peerTransitionFunc{
		stateInit:          peerInit,
		stateInvalid:       peerInvalid,
		stateTemporaryDown: peerTemporaryDown,
		stateSyncing:       peerSyncing,
		stateStable:        peerStable,
	}
}

type peerTransitionFunc func(*peer, *ntp.Response, error)

func newPeer(addr string) *peer {
	p := &peer{
		addr:       addr,
		interval:   queryMinInterval,
		best:       -1,
		offset:     time.Duration(0),
		delay:      time.Minute,
		dispersion: time.Minute,
	}
	for i := 0; i < ReplyCount; i++ {
		p.filter[i] = &filter{
			updateAt:   epoch,
			dispersion: MaxRootDelay,
			delay:      MaxRootDelay,
			offset:     MaxRootDelay,
		}
	}
	return p
}

func (p *peer) insertFilter(resp *ntp.Response) {
	// the fisrt filter is the newest
	for i := ReplyCount - 1; i > 0; i-- {
		if p.filter[i].updateAt.Equal(epoch) {
			continue
		}
		interval := time.Now().Sub(p.filter[i].updateAt)
		p.filter[i] = p.filter[i-1]
		p.filter[i].updateAt = time.Now()
		p.filter[i].dispersion += phi * interval // add up dispersion
	}
	p.filter[0].delay = resp.RTT + resp.RootDelay
	p.filter[0].offset = resp.ClockOffset
	p.filter[0].updateAt = time.Now()
	p.filter[0].dispersion = resp.RootDispersion + p.filter[0].delay/2
	p.filter[0].resp = resp
}

func (p *peer) run(pctx context.Context) {
	ctx, cancel := context.WithCancel(pctx)
	defer cancel()

	Info.Printf("%s started %s", p.addr, p.interval)
	defer Info.Printf("%s stopped", p.addr)

	var timer *time.Timer

	for {
		resp, err := ntp.Query(p.addr)
		p.reach <<= 1
		p.queryCount++
		if verr := resp.Validate(); err == nil && verr == nil {
			p.reach |= 1
			p.insertFilter(resp)
		} else {
			Warn.Print(verr, err)
		}

		peerTransTable[p.state](p, resp, err)

		if p.state == stateInvalid {
			Warn.Printf("peer %s invalid, exited looping", p.addr)
			return
		}
		if p.interval > maxInterval {
			p.interval = maxInterval
		}
		if p.interval < minInterval {
			p.interval = minInterval
		}
		p.interval += randDuration()
		Debug.Printf("%s will sleep %s", p.addr, p.interval)
		timer = time.NewTimer(p.interval)
		select {
		case <-timer.C:
		case <-ctx.Done():
			return
		}
		timer.Stop()
	}
}

func (p *peer) checkFilter() (valid bool) {

	bestIndex := -1
	bestDisp := time.Minute
	validCount := 0

	for i, r := range p.filter {
		if r == nil {
			continue
		}
		if r.dispersion >= MaxRootDelay {
			continue
		}
		validCount += 1
		if r.dispersion < bestDisp {
			bestIndex = i
		}
	}

	if validCount == 0 {
		valid = false
		return
	}

	p.best = bestIndex
	r := p.filter[bestIndex]
	p.dispersion = r.dispersion
	p.rootDelay = r.resp.RootDelay + r.resp.RTT
	p.delay = r.delay
	p.rootDisp = r.resp.RootDispersion
	p.offset = r.resp.ClockOffset
	p.interval = r.resp.Poll
	p.referTime = r.resp.ReferenceTime
	p.referId = r.resp.ReferenceID
	p.stratum = r.resp.Stratum
	p.updateAt = time.Now()
	Debug.Printf("%s choice new filter %d offset=%s", p.addr, bestIndex, p.offset)
	valid = true
	return
}

func (p *peer) String() string {
	return fmt.Sprintf("%s[%s]%s", p.addr, stateToString(p.state), p.offset)
}

func stateToString(u uint8) string {
	switch u {
	case stateInit:
		return "Init"
	case stateStable:
		return "stable"
	case stateInvalid:
		return "invalid"
	case stateTemporaryDown:
		return "down"
	case stateSyncing:
		return "syncing"
	}
	return "unknown"
}
<commit_msg>fix nil<commit_after>package gontpd

import (
	"context"
	"fmt"
	"math/bits"
	"time"

	"github.com/beevik/ntp"
)

const (
	ReplyCount           = 8
	MaxRootDelay         = 10 * time.Second
	MaxStratum     uint8 = 15
	minFilterCount       = 3
	maxInterval          = 1024 * time.Second
	minInterval          = 4 * time.Second
	reachStable    uint8 = 1<<8 - 1
	phi                  = 15 * time.Microsecond
)

const (
	stateInit = iota
	stateInvalid
	stateTemporaryDown
	stateSyncing
	stateStable
)

const (
	NoLeap uint8 = iota
	LeapIns
	LeapDel
	NotSync
)

const (
	queryMinInterval = 5 * time.Second
	queryMaxInterval = (1 << 12) * time.Minute
)

var (
	peerTransTable []peerTransitionFunc
	epoch          = time.Unix(0, 0)
)

type peer struct {
	addr       string
	filter     [ReplyCount]*filter
	referTime  time.Time
	updateAt   time.Time
	interval   time.Duration
	offset     time.Duration
	delay      time.Duration
	rootDelay  time.Duration
	rootDisp   time.Duration
	dispersion time.Duration

	filterIndex int
	best        int
	queryCount  int
	referId     uint32
	poll        int8
	leap        uint8
	reach       uint8
	stratum     uint8
	state       uint8
}

type filter struct {
	updateAt   time.Time
	offset     time.Duration
	delay      time.Duration
	dispersion time.Duration
	resp       *ntp.Response
}

func peerInit(p *peer, resp *ntp.Response, err error) {
	if p.queryCount < minFilterCount {
		// keep init
		Debug.Printf("query Count:%d keep initing", p.queryCount)
		return
	}

	if p.reach > 1 {
		p.state = stateSyncing
		Info.Printf("%s init -> syncing", p.addr)
		return
	}

	Warn.Printf("peer:%s has no good query while initing", p.addr)
	p.state = stateInvalid
	Info.Printf("%s init -> invalid", p.addr)
}

func peerInvalid(p *peer, resp *ntp.Response, err error) {
	Error.Fatal("we should not go into here")
}

func peerTemporaryDown(p *peer, resp *ntp.Response, err error) {
	Info.Printf("%s temporary down", p.addr)
	if p.reach&3 != 0 {
		p.state = stateSyncing
		Info.Printf("%s down -> syncing", p.addr)
		return
	}

	p.interval = time.Duration(8-bits.OnesCount8(p.reach)) * time.Minute
}

func peerSyncing(p *peer, resp *ntp.Response, err error) {
	if p.reach&3 == 0 {
		p.state = stateTemporaryDown
		Info.Printf("%s syncing -> temporary down", p.addr)
		p.interval = minInterval
		return
	}

	if p.reach == reachStable {
		Info.Printf("%s syncing -> stable", p.addr)
		p.state = stateStable
	}

	if p.checkFilter() {
		syncClock(p)
	}
	p.interval = time.Duration(bits.OnesCount8(p.reach)) * (10 * time.Second)
}
func peerStable(p *peer, resp *ntp.Response, err error) {

	if err != nil || p.reach != reachStable {
		p.state = stateSyncing
		Info.Printf("%s stable -> syncing", p.addr)
		return
	}

	if p.checkFilter() {
		syncClock(p)
	}
	// offset     interval
	// 0.128s  -> 1024s
	// 0.005s  -> 4s
	p.interval = secondToDuration(absDuration(p.offset).Seconds()*-8992.68 + 1065.46)
}

func syncClock(p *peer) {
	if DebugFlag&NoSyncClock != 0 {
		Debug.Printf("syncClock to:%s, offset:%s", p.addr, p.offset)
		return
	}
	// find median offset from all peers
	select {
	case syncLock <- struct{}{}:
	default:
	}
}

func init() {
	peerTransTable = []peerTransitionFunc{
		stateInit:          peerInit,
		stateInvalid:       peerInvalid,
		stateTemporaryDown: peerTemporaryDown,
		stateSyncing:       peerSyncing,
		stateStable:        peerStable,
	}
}

type peerTransitionFunc func(*peer, *ntp.Response, error)

func newPeer(addr string) *peer {
	p := &peer{
		addr:       addr,
		interval:   queryMinInterval,
		best:       -1,
		offset:     time.Duration(0),
		delay:      time.Minute,
		dispersion: time.Minute,
	}
	for i := 0; i < ReplyCount; i++ {
		p.filter[i] = &filter{
			updateAt:   epoch,
			dispersion: MaxRootDelay,
			delay:      MaxRootDelay,
			offset:     MaxRootDelay,
		}
	}
	return p
}

func (p *peer) insertFilter(resp *ntp.Response) {
	// the fisrt filter is the newest
	for i := ReplyCount - 1; i > 0; i-- {
		if p.filter[i].updateAt.Equal(epoch) {
			continue
		}
		interval := time.Now().Sub(p.filter[i].updateAt)
		p.filter[i] = p.filter[i-1]
		p.filter[i].updateAt = time.Now()
		p.filter[i].dispersion += phi * interval // add up dispersion
	}
	p.filter[0].delay = resp.RTT + resp.RootDelay
	p.filter[0].offset = resp.ClockOffset
	p.filter[0].updateAt = time.Now()
	p.filter[0].dispersion = resp.RootDispersion + p.filter[0].delay/2
	p.filter[0].resp = resp
}

func (p *peer) run(pctx context.Context) {
	ctx, cancel := context.WithCancel(pctx)
	defer cancel()

	Info.Printf("%s started %s", p.addr, p.interval)
	defer Info.Printf("%s stopped", p.addr)

	var timer *time.Timer

	for {
		resp, err := ntp.Query(p.addr)
		p.reach <<= 1
		p.queryCount++
		if err == nil && resp != nil && resp.Validate() == nil {
			p.reach |= 1
			p.insertFilter(resp)
		} else {
			Warn.Print(err)
			if resp != nil {
				Warn.Print(resp.Validate(), resp)
			}
		}

		peerTransTable[p.state](p, resp, err)

		if p.state == stateInvalid {
			Warn.Printf("peer %s invalid, exited looping", p.addr)
			return
		}
		if p.interval > maxInterval {
			p.interval = maxInterval
		}
		if p.interval < minInterval {
			p.interval = minInterval
		}
		p.interval += randDuration()
		Debug.Printf("%s will sleep %s", p.addr, p.interval)
		timer = time.NewTimer(p.interval)
		select {
		case <-timer.C:
		case <-ctx.Done():
			return
		}
		timer.Stop()
	}
}

func (p *peer) checkFilter() (valid bool) {

	bestIndex := -1
	bestDisp := time.Minute
	validCount := 0

	for i, r := range p.filter {
		if r == nil {
			continue
		}
		if r.dispersion >= MaxRootDelay {
			continue
		}
		validCount += 1
		if r.dispersion < bestDisp {
			bestIndex = i
		}
	}

	if validCount == 0 {
		valid = false
		return
	}

	p.best = bestIndex
	r := p.filter[bestIndex]
	p.dispersion = r.dispersion
	p.rootDelay = r.resp.RootDelay + r.resp.RTT
	p.delay = r.delay
	p.rootDisp = r.resp.RootDispersion
	p.offset = r.resp.ClockOffset
	p.interval = r.resp.Poll
	p.referTime = r.resp.ReferenceTime
	p.referId = r.resp.ReferenceID
	p.stratum = r.resp.Stratum
	p.updateAt = time.Now()
	Debug.Printf("%s choice new filter %d offset=%s", p.addr, bestIndex, p.offset)
	valid = true
	return
}

func (p *peer) String() string {
	return fmt.Sprintf("%s[%s]%s", p.addr, stateToString(p.state), p.offset)
}

func stateToString(u uint8) string {
	switch u {
	case stateInit:
		return "Init"
	case stateStable:
		return "stable"
	case stateInvalid:
		return "invalid"
	case stateTemporaryDown:
		return "down"
	case stateSyncing:
		return "syncing"
	}
	return "unknown"
}
<|endoftext|>


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

// Keystone authentication middleware, only support keystone v3.

package auth

import (
	"net/http"
	"strings"
	"time"

	bctx "github.com/astaxie/beego/context"
	log "github.com/golang/glog"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack"
	"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
	"github.com/opensds/opensds/pkg/context"
	"github.com/opensds/opensds/pkg/model"
	"github.com/opensds/opensds/pkg/utils"
	"github.com/opensds/opensds/pkg/utils/config"
	"github.com/opensds/opensds/pkg/utils/constants"
	"github.com/opensds/opensds/pkg/utils/pwd"
)

func NewKeystone() AuthBase {
	k := &Keystone{}
	if err := k.SetUp(); err != nil {
		// If auth set up failed, raise panic.
		panic(err)
	}
	return k
}

type Keystone struct {
	identity *gophercloud.ServiceClient
}

func (k *Keystone) SetUp() error {
	c := config.CONF.KeystoneAuthToken
	// Decrypte the password
	pwdCiphertext := c.Password
	pwdTool := pwd.NewPwdTool(config.CONF.OsdsLet.PasswordDecryptTool)
	password, err := pwdTool.Decrypter(pwdCiphertext)
	if err != nil {
		return err
	}

	opts := gophercloud.AuthOptions{
		IdentityEndpoint: c.AuthUrl,
		DomainName:       c.UserDomainName,
		Username:         c.Username,
		Password:         password,
		TenantName:       c.ProjectName,
	}
	provider, err := openstack.AuthenticatedClient(opts)
	if err != nil {
		log.Error("When get auth client:", err)
		return err
	}
	// Only support keystone v3
	k.identity, err = openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
	if err != nil {
		log.Error("When get identity session:", err)
		return err
	}
	log.V(4).Infof("Service Token Info: %s", provider.TokenID)
	return nil
}

func (k *Keystone) setPolicyContext(ctx *bctx.Context, r tokens.GetResult) error {
	roles, err := r.ExtractRoles()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract roles failed,%v", err)
	}

	var roleNames []string
	for _, role := range roles {
		roleNames = append(roleNames, role.Name)
	}

	project, err := r.ExtractProject()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract project failed,%v", err)
	}

	user, err := r.ExtractUser()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract user failed,%v", err)
	}

	param := map[string]interface{}{
		"TenantId":       project.ID,
		"Roles":          roleNames,
		"UserId":         user.ID,
		"IsAdminProject": strings.ToLower(project.Name) == "admin",
	}
	context.UpdateContext(ctx, param)

	return nil
}

func (k *Keystone) validateToken(ctx *bctx.Context, token string) error {
	if token == "" {
		return model.HttpError(ctx, http.StatusUnauthorized, "token not found in header")
	}

	var r tokens.GetResult
	// The service token may be expired or revoked, so retry to get new token.
	err := utils.Retry(2, "verify token", false, func(retryIdx int, lastErr error) error {
		if retryIdx > 0 {
			// Fixme: Is there any better method ?
			if lastErr.Error() == "Authentication failed" {
				k.SetUp()
			} else {
				return lastErr
			}
		}
		r = tokens.Get(k.identity, token)
		return r.Err
	})
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "get token failed,%v", r.Err)
	}

	t, err := r.ExtractToken()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract token failed,%v", err)

	}
	log.V(8).Infof("token: %v", t)

	if time.Now().After(t.ExpiresAt) {
		return model.HttpError(ctx, http.StatusUnauthorized,
			"token has expired, expire time %v", t.ExpiresAt)
	}
	return k.setPolicyContext(ctx, r)
}

func (k *Keystone) Filter(ctx *bctx.Context) {
	// Strip the spaces around the token
	token := strings.TrimSpace(ctx.Input.Header(constants.AuthTokenHeader))
	k.validateToken(ctx, token)
}
<commit_msg>fix bugs<commit_after>// Copyright (c) 2018 Huawei Technologies Co., Ltd. All Rights Reserved.
//
//    Licensed under the Apache License, Version 2.0 (the "License"); you may
//    not use this file except in compliance with the License. You may obtain
//    a copy of the License at
//
//         http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
//    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
//    License for the specific language governing permissions and limitations
//    under the License.

// Keystone authentication middleware, only support keystone v3.

package auth

import (
	"net/http"
	"strings"
	"time"

	bctx "github.com/astaxie/beego/context"
	log "github.com/golang/glog"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack"
	"github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
	"github.com/opensds/opensds/pkg/context"
	"github.com/opensds/opensds/pkg/model"
	"github.com/opensds/opensds/pkg/utils"
	"github.com/opensds/opensds/pkg/utils/config"
	"github.com/opensds/opensds/pkg/utils/constants"
)

func NewKeystone() AuthBase {
	k := &Keystone{}
	if err := k.SetUp(); err != nil {
		// If auth set up failed, raise panic.
		panic(err)
	}
	return k
}

type Keystone struct {
	identity *gophercloud.ServiceClient
}

func (k *Keystone) SetUp() error {
	c := config.CONF.KeystoneAuthToken

	opts := gophercloud.AuthOptions{
		IdentityEndpoint: c.AuthUrl,
		DomainName:       c.UserDomainName,
		Username:         c.Username,
		Password:         c.Password,
		TenantName:       c.ProjectName,
	}
	provider, err := openstack.AuthenticatedClient(opts)
	if err != nil {
		log.Error("When get auth client:", err)
		return err
	}
	// Only support keystone v3
	k.identity, err = openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
	if err != nil {
		log.Error("When get identity session:", err)
		return err
	}
	log.V(4).Infof("Service Token Info: %s", provider.TokenID)
	return nil
}

func (k *Keystone) setPolicyContext(ctx *bctx.Context, r tokens.GetResult) error {
	roles, err := r.ExtractRoles()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract roles failed,%v", err)
	}

	var roleNames []string
	for _, role := range roles {
		roleNames = append(roleNames, role.Name)
	}

	project, err := r.ExtractProject()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract project failed,%v", err)
	}

	user, err := r.ExtractUser()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract user failed,%v", err)
	}

	param := map[string]interface{}{
		"TenantId":       project.ID,
		"Roles":          roleNames,
		"UserId":         user.ID,
		"IsAdminProject": strings.ToLower(project.Name) == "admin",
	}
	context.UpdateContext(ctx, param)

	return nil
}

func (k *Keystone) validateToken(ctx *bctx.Context, token string) error {
	if token == "" {
		return model.HttpError(ctx, http.StatusUnauthorized, "token not found in header")
	}

	var r tokens.GetResult
	// The service token may be expired or revoked, so retry to get new token.
	err := utils.Retry(2, "verify token", false, func(retryIdx int, lastErr error) error {
		if retryIdx > 0 {
			// Fixme: Is there any better method ?
			if lastErr.Error() == "Authentication failed" {
				k.SetUp()
			} else {
				return lastErr
			}
		}
		r = tokens.Get(k.identity, token)
		return r.Err
	})
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "get token failed,%v", r.Err)
	}

	t, err := r.ExtractToken()
	if err != nil {
		return model.HttpError(ctx, http.StatusUnauthorized, "extract token failed,%v", err)

	}
	log.V(8).Infof("token: %v", t)

	if time.Now().After(t.ExpiresAt) {
		return model.HttpError(ctx, http.StatusUnauthorized,
			"token has expired, expire time %v", t.ExpiresAt)
	}
	return k.setPolicyContext(ctx, r)
}

func (k *Keystone) Filter(ctx *bctx.Context) {
	// Strip the spaces around the token
	token := strings.TrimSpace(ctx.Input.Header(constants.AuthTokenHeader))
	k.validateToken(ctx, token)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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.
*/

// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/testapigroup
// +k8s:openapi-gen=false
// +k8s:defaulter-gen=TypeMeta

// +groupName=testapigroup.apimachinery.k8s.io
package v1 // import "k8s.io/apimachinery/pkg/apis/testapigroup/v1"
<commit_msg>conversion-gen: make staging dirs independent of living in vendor/<commit_after>/*
Copyright 2017 The Kubernetes 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.
*/

// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/apimachinery/pkg/apis/testapigroup
// +k8s:openapi-gen=false
// +k8s:defaulter-gen=TypeMeta

// +groupName=testapigroup.apimachinery.k8s.io
package v1 // import "k8s.io/apimachinery/pkg/apis/testapigroup/v1"
<|endoftext|>


<commit_before>package transaction

import (
	"errors"
	"time"

	"github.com/discoviking/fsm"
	"github.com/stefankopieczek/gossip/base"
	"github.com/stefankopieczek/gossip/log"
)

// SIP Server Transaction FSM
// Implements the behaviour described in RFC 3261 section 17.2

// FSM States
const (
	server_state_trying = iota
	server_state_proceeding
	server_state_completed
	server_state_confirmed
	server_state_terminated
)

// FSM Inputs
const (
	server_input_request fsm.Input = iota
	server_input_ack
	server_input_user_1xx
	server_input_user_2xx
	server_input_user_300_plus
	server_input_timer_g
	server_input_timer_h
	server_input_timer_i
	server_input_transport_err
	server_input_delete
)

// Choose the right FSM init function depending on request method.
func (tx *ServerTransaction) initFSM() {
	if tx.origin.Method == base.INVITE {
		tx.initInviteFSM()
	} else {
		tx.initNonInviteFSM()
	}
}

func (tx *ServerTransaction) initInviteFSM() {
	// Define Actions

	// Send response
	act_respond := func() fsm.Input {
		err := tx.transport.Send(tx.dest, tx.lastResp)
		if err != nil {
			return server_input_transport_err
		}

		return fsm.NO_INPUT
	}

	// Inform user of transport error
	act_trans_err := func() fsm.Input {
		tx.tu_err <- errors.New("failed to send response")
		return server_input_delete
	}

	// Inform user of timeout error
	act_timeout := func() fsm.Input {
		tx.tu_err <- errors.New("transaction timed out")
		return server_input_delete
	}

	// Send response and delete the transaction.
	act_respond_delete := func() fsm.Input {
		tx.Delete()

		err := tx.transport.Send(tx.dest, tx.lastResp)
		if err != nil {
			return server_input_transport_err
		}
		return fsm.NO_INPUT
	}

	// Just delete the transaction.
	act_delete := func() fsm.Input {
		tx.Delete()
		return fsm.NO_INPUT
	}

	// Define States

	// Proceeding
	server_state_def_proceeding := fsm.State{
		Index: server_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_proceeding, act_respond},
			server_input_user_1xx:      {server_state_proceeding, act_respond},
			server_input_user_2xx:      {server_state_terminated, act_respond_delete},
			server_input_user_300_plus: {server_state_completed, act_respond},
			server_input_transport_err: {server_state_terminated, act_trans_err},
		},
	}

	// Completed
	server_state_def_completed := fsm.State{
		Index: server_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_completed, act_respond},
			server_input_ack:           {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_completed, fsm.NO_ACTION},
			server_input_timer_g:       {server_state_completed, act_respond},
			server_input_timer_h:       {server_state_terminated, act_timeout},
			server_input_transport_err: {server_state_terminated, act_trans_err},
		},
	}

	// Confirmed
	server_state_def_confirmed := fsm.State{
		Index: server_state_confirmed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_confirmed, fsm.NO_ACTION},
			server_input_timer_i:       {server_state_terminated, act_delete},
		},
	}

	// Terminated
	server_state_def_terminated := fsm.State{
		Index: server_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_terminated, fsm.NO_ACTION},
			server_input_ack:           {server_state_terminated, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_terminated, fsm.NO_ACTION},
			server_input_delete:        {server_state_terminated, act_delete},
		},
	}

	// Define FSM
	fsm, err := fsm.Define(
		server_state_def_proceeding,
		server_state_def_completed,
		server_state_def_confirmed,
		server_state_def_terminated,
	)
	if err != nil {
		log.Severe("Failed to define transaction FSM. Transaction will be dropped.")
		return
	}

	tx.fsm = fsm
}

func (tx *ServerTransaction) initNonInviteFSM() {
	// Define Actions

	// Send response
	act_respond := func() fsm.Input {
		err := tx.transport.Send(tx.dest, tx.lastResp)
		if err != nil {
			return server_input_transport_err
		}

		return fsm.NO_INPUT
	}

	// Send final response
	act_final := func() fsm.Input {
		err := tx.transport.Send(tx.dest, tx.lastResp)
		if err != nil {
			return server_input_transport_err
		}

		// Start timer J (we just reuse timer h)
		tx.timer_h = time.AfterFunc(64*T1, func() {
			tx.fsm.Spin(server_input_timer_h)
		})

		return fsm.NO_INPUT
	}

	// Inform user of transport error
	act_trans_err := func() fsm.Input {
		tx.tu_err <- errors.New("failed to send response")
		return server_input_delete
	}

	// Inform user of timeout error
	act_timeout := func() fsm.Input {
		tx.tu_err <- errors.New("transaction timed out")
		return server_input_delete
	}

	// Just delete the transaction.
	act_delete := func() fsm.Input {
		tx.Delete()
		return fsm.NO_INPUT
	}

	// Define States

	// Trying
	server_state_def_trying := fsm.State{
		Index: server_state_trying,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_trying, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_proceeding, act_respond},
			server_input_user_2xx:      {server_state_completed, act_respond},
			server_input_user_300_plus: {server_state_completed, act_respond},
		},
	}

	// Proceeding
	server_state_def_proceeding := fsm.State{
		Index: server_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_proceeding, act_respond},
			server_input_user_1xx:      {server_state_proceeding, act_respond},
			server_input_user_2xx:      {server_state_completed, act_final},
			server_input_user_300_plus: {server_state_completed, act_final},
			server_input_transport_err: {server_state_terminated, act_trans_err},
		},
	}

	// Completed
	server_state_def_completed := fsm.State{
		Index: server_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_completed, act_respond},
			server_input_user_1xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_completed, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, act_timeout},
			server_input_transport_err: {server_state_terminated, act_trans_err},
		},
	}

	// Terminated
	server_state_def_terminated := fsm.State{
		Index: server_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_terminated, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_terminated, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, fsm.NO_ACTION},
			server_input_delete:        {server_state_terminated, act_delete},
		},
	}

	// Define FSM
	fsm, err := fsm.Define(
		server_state_def_trying,
		server_state_def_proceeding,
		server_state_def_completed,
		server_state_def_terminated,
	)
	if err != nil {
		log.Severe("Failed to define transaction FSM. Transaction will be dropped.")
		return
	}

	tx.fsm = fsm
}
<commit_msg>Move definitions of FSM actions outside of the the initFSM functions.<commit_after>package transaction

import (
	"errors"
	"time"

	"github.com/discoviking/fsm"
	"github.com/stefankopieczek/gossip/base"
	"github.com/stefankopieczek/gossip/log"
)

// SIP Server Transaction FSM
// Implements the behaviour described in RFC 3261 section 17.2

// FSM States
const (
	server_state_trying = iota
	server_state_proceeding
	server_state_completed
	server_state_confirmed
	server_state_terminated
)

// FSM Inputs
const (
	server_input_request fsm.Input = iota
	server_input_ack
	server_input_user_1xx
	server_input_user_2xx
	server_input_user_300_plus
	server_input_timer_g
	server_input_timer_h
	server_input_timer_i
	server_input_transport_err
	server_input_delete
)

// Define actions.

// Send response
func (tx *ServerTransaction) act_respond() fsm.Input {
	err := tx.transport.Send(tx.dest, tx.lastResp)
	if err != nil {
		return server_input_transport_err
	}

	return fsm.NO_INPUT
}

// Send final response
func (tx *ServerTransaction) act_final() fsm.Input {
	err := tx.transport.Send(tx.dest, tx.lastResp)
	if err != nil {
		return server_input_transport_err
	}

	// Start timer J (we just reuse timer h)
	tx.timer_h = time.AfterFunc(64*T1, func() {
		tx.fsm.Spin(server_input_timer_h)
	})

	return fsm.NO_INPUT
}

// Inform user of transport error
func (tx *ServerTransaction) act_trans_err() fsm.Input {
	tx.tu_err <- errors.New("failed to send response")
	return server_input_delete
}

// Inform user of timeout error
func (tx *ServerTransaction) act_timeout() fsm.Input {
	tx.tu_err <- errors.New("transaction timed out")
	return server_input_delete
}

// Just delete the transaction.
func (tx *ServerTransaction) act_delete() fsm.Input {
	tx.Delete()
	return fsm.NO_INPUT
}

// Send response and delete the transaction.
func (tx *ServerTransaction) act_respond_delete() fsm.Input {
	tx.Delete()

	err := tx.transport.Send(tx.dest, tx.lastResp)
	if err != nil {
		return server_input_transport_err
	}
	return fsm.NO_INPUT
}

// Choose the right FSM init function depending on request method.
func (tx *ServerTransaction) initFSM() {
	if tx.origin.Method == base.INVITE {
		tx.initInviteFSM()
	} else {
		tx.initNonInviteFSM()
	}
}

func (tx *ServerTransaction) initInviteFSM() {
	// Define States

	// Proceeding
	server_state_def_proceeding := fsm.State{
		Index: server_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_proceeding, tx.act_respond},
			server_input_user_1xx:      {server_state_proceeding, tx.act_respond},
			server_input_user_2xx:      {server_state_terminated, tx.act_respond_delete},
			server_input_user_300_plus: {server_state_completed, tx.act_respond},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Completed
	server_state_def_completed := fsm.State{
		Index: server_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_completed, tx.act_respond},
			server_input_ack:           {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_completed, fsm.NO_ACTION},
			server_input_timer_g:       {server_state_completed, tx.act_respond},
			server_input_timer_h:       {server_state_terminated, tx.act_timeout},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Confirmed
	server_state_def_confirmed := fsm.State{
		Index: server_state_confirmed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_confirmed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_confirmed, fsm.NO_ACTION},
			server_input_timer_i:       {server_state_terminated, tx.act_delete},
		},
	}

	// Terminated
	server_state_def_terminated := fsm.State{
		Index: server_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_terminated, fsm.NO_ACTION},
			server_input_ack:           {server_state_terminated, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_terminated, fsm.NO_ACTION},
			server_input_delete:        {server_state_terminated, tx.act_delete},
		},
	}

	// Define FSM
	fsm, err := fsm.Define(
		server_state_def_proceeding,
		server_state_def_completed,
		server_state_def_confirmed,
		server_state_def_terminated,
	)
	if err != nil {
		log.Severe("Failed to define transaction FSM. Transaction will be dropped.")
		return
	}

	tx.fsm = fsm
}

func (tx *ServerTransaction) initNonInviteFSM() {
	// Define States

	// Trying
	server_state_def_trying := fsm.State{
		Index: server_state_trying,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_trying, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_proceeding, tx.act_respond},
			server_input_user_2xx:      {server_state_completed, tx.act_respond},
			server_input_user_300_plus: {server_state_completed, tx.act_respond},
		},
	}

	// Proceeding
	server_state_def_proceeding := fsm.State{
		Index: server_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_proceeding, tx.act_respond},
			server_input_user_1xx:      {server_state_proceeding, tx.act_respond},
			server_input_user_2xx:      {server_state_completed, tx.act_final},
			server_input_user_300_plus: {server_state_completed, tx.act_final},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Completed
	server_state_def_completed := fsm.State{
		Index: server_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_completed, tx.act_respond},
			server_input_user_1xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_completed, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, tx.act_timeout},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Terminated
	server_state_def_terminated := fsm.State{
		Index: server_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_terminated, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_terminated, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, fsm.NO_ACTION},
			server_input_delete:        {server_state_terminated, tx.act_delete},
		},
	}

	// Define FSM
	fsm, err := fsm.Define(
		server_state_def_trying,
		server_state_def_proceeding,
		server_state_def_completed,
		server_state_def_terminated,
	)
	if err != nil {
		log.Severe("Failed to define transaction FSM. Transaction will be dropped.")
		return
	}

	tx.fsm = fsm
}
<|endoftext|>


<commit_before>/*
Copyright 2022 The Fission 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 metrics

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
	// function_name: the function's name
	// function_uid: the function's version id
	// function_address: the address of the pod from which the function was called
	functionLabels = []string{"function_name", "function_namespace"}
	ColdStarts     = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: "fission_function_cold_starts_total",
			Help: "How many cold starts are made by function_name, function_uid.",
		},
		functionLabels,
	)
	FuncRunningSummary = promauto.NewSummaryVec(
		prometheus.SummaryOpts{
			Name:       "fission_function_running_seconds",
			Help:       "The running time (last access - create) in seconds of the function.",
			Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
		},
		functionLabels,
	)
	FuncError = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: "fission_function_cold_start_errors_total",
			Help: "Count of fission cold start errors",
		},
		functionLabels,
	)
)
<commit_msg>Fixed help for ColdStarts metric in executor  according to new labels (#2446)<commit_after>/*
Copyright 2022 The Fission 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 metrics

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
	// function_name: the function's name
	// function_uid: the function's version id
	// function_address: the address of the pod from which the function was called
	functionLabels = []string{"function_name", "function_namespace"}
	ColdStarts     = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: "fission_function_cold_starts_total",
			Help: "How many cold starts are made by function_name, function_namespace.",
		},
		functionLabels,
	)
	FuncRunningSummary = promauto.NewSummaryVec(
		prometheus.SummaryOpts{
			Name:       "fission_function_running_seconds",
			Help:       "The running time (last access - create) in seconds of the function.",
			Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
		},
		functionLabels,
	)
	FuncError = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: "fission_function_cold_start_errors_total",
			Help: "Count of fission cold start errors",
		},
		functionLabels,
	)
)
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 federatedtypes

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/watch"
	federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
	"k8s.io/kubernetes/federation/pkg/federation-controller/util"
	"k8s.io/kubernetes/pkg/api/v1"
	extensionsv1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

const (
	DaemonSetKind           = "daemonset"
	DaemonSetControllerName = "daemonsets"
)

func init() {
	RegisterFederatedType(DaemonSetKind, DaemonSetControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(DaemonSetControllerName)}, NewDaemonSetAdapter)
}

type DaemonSetAdapter struct {
	client federationclientset.Interface
}

func NewDaemonSetAdapter(client federationclientset.Interface) FederatedTypeAdapter {
	return &DaemonSetAdapter{client: client}
}

func (a *DaemonSetAdapter) Kind() string {
	return DaemonSetKind
}

func (a *DaemonSetAdapter) ObjectType() pkgruntime.Object {
	return &extensionsv1.DaemonSet{}
}

func (a *DaemonSetAdapter) IsExpectedType(obj interface{}) bool {
	_, ok := obj.(*extensionsv1.DaemonSet)
	return ok
}

func (a *DaemonSetAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return &extensionsv1.DaemonSet{
		ObjectMeta: util.DeepCopyRelevantObjectMeta(daemonset.ObjectMeta),
		Spec:       *(util.DeepCopyApiTypeOrPanic(&daemonset.Spec).(*extensionsv1.DaemonSetSpec)),
	}
}

func (a *DaemonSetAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
	daemonset1 := obj1.(*extensionsv1.DaemonSet)
	daemonset2 := obj2.(*extensionsv1.DaemonSet)

	// Kubernetes daemonset controller writes a daemonset's hash to
	// the object label as an optimization to avoid recomputing it every
	// time. Adding a new label to the object that the federation is
	// unaware of causes problems because federated controllers compare
	// the objects in federation and their equivalents in clusters and
	// try to reconcile them. This leads to a constant fight between the
	// federated daemonset controller and the cluster controllers, and
	// they never reach a stable state.
	//
	// Ideally, cluster components should not update an object's spec or
	// metadata in a way federation cannot replicate. They can update an
	// object's status though. Therefore, this daemonset hash should
	// be a field in daemonset's status, not a label in object meta.
	// @janetkuo says that this label is only a short term solution. In
	// the near future, they are going to replace it with revision numbers
	// in daemonset status. We can then rip this bandaid out.
	//
	// We are deleting the keys here and that should be fine since we are
	// working on object copies. Also, propagating the deleted labels
	// should also be fine because we don't support daemonset rolling
	// update in federation yet.
	delete(daemonset1.ObjectMeta.Labels, extensionsv1.DefaultDaemonSetUniqueLabelKey)
	delete(daemonset2.ObjectMeta.Labels, extensionsv1.DefaultDaemonSetUniqueLabelKey)

	return util.ObjectMetaEquivalent(daemonset1.ObjectMeta, daemonset2.ObjectMeta) && reflect.DeepEqual(daemonset1.Spec, daemonset2.Spec)
}

func (a *DaemonSetAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return types.NamespacedName{Namespace: daemonset.Namespace, Name: daemonset.Name}
}

func (a *DaemonSetAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
	return &obj.(*extensionsv1.DaemonSet).ObjectMeta
}

func (a *DaemonSetAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Delete(namespacedName.Name, options)
}

func (a *DaemonSetAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return a.client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error {
	return client.Extensions().DaemonSets(nsName.Namespace).Delete(nsName.Name, options)
}

func (a *DaemonSetAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) IsSchedulingAdapter() bool {
	return false
}

func (a *DaemonSetAdapter) NewTestObject(namespace string) pkgruntime.Object {
	return &extensionsv1.DaemonSet{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: "test-daemonset-",
			Namespace:    namespace,
			Labels:       map[string]string{"app": "test-daemonset"},
		},
		Spec: extensionsv1.DaemonSetSpec{
			Template: v1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{"name": "test-pod"},
				},
				Spec: v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:  "test-daemonset",
							Image: "images/test-daemonset",
							Ports: []v1.ContainerPort{{ContainerPort: 9376}},
						},
					},
				},
			},
		},
	}
}
<commit_msg>Revert "Ignore `daemonset-controller-hash` label key in federation before comparing the federated object with its cluster equivalent."<commit_after>/*
Copyright 2017 The Kubernetes 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 federatedtypes

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/watch"
	federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
	"k8s.io/kubernetes/federation/pkg/federation-controller/util"
	"k8s.io/kubernetes/pkg/api/v1"
	extensionsv1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

const (
	DaemonSetKind           = "daemonset"
	DaemonSetControllerName = "daemonsets"
)

func init() {
	RegisterFederatedType(DaemonSetKind, DaemonSetControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(DaemonSetControllerName)}, NewDaemonSetAdapter)
}

type DaemonSetAdapter struct {
	client federationclientset.Interface
}

func NewDaemonSetAdapter(client federationclientset.Interface) FederatedTypeAdapter {
	return &DaemonSetAdapter{client: client}
}

func (a *DaemonSetAdapter) Kind() string {
	return DaemonSetKind
}

func (a *DaemonSetAdapter) ObjectType() pkgruntime.Object {
	return &extensionsv1.DaemonSet{}
}

func (a *DaemonSetAdapter) IsExpectedType(obj interface{}) bool {
	_, ok := obj.(*extensionsv1.DaemonSet)
	return ok
}

func (a *DaemonSetAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return &extensionsv1.DaemonSet{
		ObjectMeta: util.DeepCopyRelevantObjectMeta(daemonset.ObjectMeta),
		Spec:       *(util.DeepCopyApiTypeOrPanic(&daemonset.Spec).(*extensionsv1.DaemonSetSpec)),
	}
}

func (a *DaemonSetAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
	daemonset1 := obj1.(*extensionsv1.DaemonSet)
	daemonset2 := obj2.(*extensionsv1.DaemonSet)
	return util.ObjectMetaEquivalent(daemonset1.ObjectMeta, daemonset2.ObjectMeta) && reflect.DeepEqual(daemonset1.Spec, daemonset2.Spec)
}

func (a *DaemonSetAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return types.NamespacedName{Namespace: daemonset.Namespace, Name: daemonset.Name}
}

func (a *DaemonSetAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
	return &obj.(*extensionsv1.DaemonSet).ObjectMeta
}

func (a *DaemonSetAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Delete(namespacedName.Name, options)
}

func (a *DaemonSetAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return a.client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error {
	return client.Extensions().DaemonSets(nsName.Namespace).Delete(nsName.Name, options)
}

func (a *DaemonSetAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) IsSchedulingAdapter() bool {
	return false
}

func (a *DaemonSetAdapter) NewTestObject(namespace string) pkgruntime.Object {
	return &extensionsv1.DaemonSet{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: "test-daemonset-",
			Namespace:    namespace,
			Labels:       map[string]string{"app": "test-daemonset"},
		},
		Spec: extensionsv1.DaemonSetSpec{
			Template: v1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{"name": "test-pod"},
				},
				Spec: v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:  "test-daemonset",
							Image: "images/test-daemonset",
							Ports: []v1.ContainerPort{{ContainerPort: 9376}},
						},
					},
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package config

import (
	"reflect"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

func TestEtcdSourceExistingBoundPods(t *testing.T) {
	// Arrange
	key := "/registry/nodes/machine/boundpods"
	fakeEtcdClient := tools.NewFakeEtcdClient(t)
	updates := make(chan interface{})

	fakeEtcdClient.Set(
		key,
		runtime.EncodeOrDie(latest.Codec, &api.BoundPods{
			Items: []api.BoundPod{
				{
					ObjectMeta: api.ObjectMeta{
						Name:      "foo",
						Namespace: "default"},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Image: "foo:v1",
							}}}},
				{
					ObjectMeta: api.ObjectMeta{
						Name:      "bar",
						Namespace: "default"},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Image: "foo:v1",
							}}}}}}),
		0)

	// Act
	NewSourceEtcd(key, fakeEtcdClient, updates)

	// Assert
	select {
	case got := <-updates:
		update := got.(kubelet.PodUpdate)
		if len(update.Pods) != 2 ||
			update.Pods[0].ObjectMeta.Name != "foo" ||
			update.Pods[1].ObjectMeta.Name != "bar" {
			t.Errorf("Unexpected update response: %#v", update)
		}
	case <-time.After(2 * time.Millisecond):
		t.Errorf("Expected update, timeout insteam")
	}
}

func TestEventToPods(t *testing.T) {
	tests := []struct {
		input watch.Event
		pods  []api.BoundPod
		fail  bool
	}{
		{
			input: watch.Event{Object: nil},
			pods:  []api.BoundPod{},
			fail:  false,
		},
		{
			input: watch.Event{Object: &api.BoundPods{}},
			pods:  []api.BoundPod{},
			fail:  false,
		},
		{
			input: watch.Event{
				Object: &api.BoundPods{
					Items: []api.BoundPod{
						{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}},
						{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}},
					},
				},
			},
			pods: []api.BoundPod{
				{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}, Spec: api.PodSpec{}},
				{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}, Spec: api.PodSpec{}},
			},
			fail: false,
		},
		{
			input: watch.Event{
				Object: &api.BoundPods{
					Items: []api.BoundPod{
						{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo"}},
					},
				},
			},
			pods: []api.BoundPod{
				{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}},
			},
			fail: false,
		},
	}

	for i, tt := range tests {
		pods, err := eventToPods(tt.input)
		if !reflect.DeepEqual(tt.pods, pods) {
			t.Errorf("case %d: expected output %#v, got %#v", i, tt.pods, pods)
		}
		if tt.fail != (err != nil) {
			t.Errorf("case %d: got fail=%t but err=%v", i, tt.fail, err)
		}
	}
}
<commit_msg>Increase timeout for TestEtcdSourceExistingBoundPods test<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package config

import (
	"reflect"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

func TestEtcdSourceExistingBoundPods(t *testing.T) {
	// Arrange
	key := "/registry/nodes/machine/boundpods"
	fakeEtcdClient := tools.NewFakeEtcdClient(t)
	updates := make(chan interface{})

	fakeEtcdClient.Set(
		key,
		runtime.EncodeOrDie(latest.Codec, &api.BoundPods{
			Items: []api.BoundPod{
				{
					ObjectMeta: api.ObjectMeta{
						Name:      "foo",
						Namespace: "default"},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Image: "foo:v1",
							}}}},
				{
					ObjectMeta: api.ObjectMeta{
						Name:      "bar",
						Namespace: "default"},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Image: "foo:v1",
							}}}}}}),
		0)

	// Act
	NewSourceEtcd(key, fakeEtcdClient, updates)

	// Assert
	select {
	case got := <-updates:
		update := got.(kubelet.PodUpdate)
		if len(update.Pods) != 2 ||
			update.Pods[0].ObjectMeta.Name != "foo" ||
			update.Pods[1].ObjectMeta.Name != "bar" {
			t.Errorf("Unexpected update response: %#v", update)
		}
	case <-time.After(200 * time.Millisecond):
		t.Errorf("Expected update, timeout instead")
	}
}

func TestEventToPods(t *testing.T) {
	tests := []struct {
		input watch.Event
		pods  []api.BoundPod
		fail  bool
	}{
		{
			input: watch.Event{Object: nil},
			pods:  []api.BoundPod{},
			fail:  false,
		},
		{
			input: watch.Event{Object: &api.BoundPods{}},
			pods:  []api.BoundPod{},
			fail:  false,
		},
		{
			input: watch.Event{
				Object: &api.BoundPods{
					Items: []api.BoundPod{
						{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}},
						{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}},
					},
				},
			},
			pods: []api.BoundPod{
				{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}, Spec: api.PodSpec{}},
				{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}, Spec: api.PodSpec{}},
			},
			fail: false,
		},
		{
			input: watch.Event{
				Object: &api.BoundPods{
					Items: []api.BoundPod{
						{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo"}},
					},
				},
			},
			pods: []api.BoundPod{
				{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}},
			},
			fail: false,
		},
	}

	for i, tt := range tests {
		pods, err := eventToPods(tt.input)
		if !reflect.DeepEqual(tt.pods, pods) {
			t.Errorf("case %d: expected output %#v, got %#v", i, tt.pods, pods)
		}
		if tt.fail != (err != nil) {
			t.Errorf("case %d: got fail=%t but err=%v", i, tt.fail, err)
		}
	}
}
<|endoftext|>


<commit_before>// +build windows

/*
Copyright 2017 The Kubernetes 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 winstats

import (
	"fmt"
	"golang.org/x/sys/windows/registry"
)

//OSInfo is a convenience class for retrieving Windows OS information
type OSInfo struct {
	BuildNumber, ProductName        string
	MajorVersion, MinorVersion, UBR uint64
}

// GetOSInfo reads Windows version information from the registry
func GetOSInfo() (*OSInfo, error) {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
	if err != nil {
		return nil, err
	}
	defer k.Close()

	buildNumber, _, err := k.GetStringValue("CurrentBuildNumber")
	if err != nil {
		return nil, err
	}

	majorVersionNumber, _, err := k.GetIntegerValue("CurrentMajorVersionNumber")
	if err != nil {
		return nil, err
	}

	minorVersionNumber, _, err := k.GetIntegerValue("CurrentMinorVersionNumber")
	if err != nil {
		return nil, err
	}

	revision, _, err := k.GetIntegerValue("UBR")
	if err != nil {
		return nil, err
	}

	productName, _, err := k.GetStringValue("ProductName")
	if err != nil {
		return nil, nil
	}

	return &OSInfo{
		BuildNumber:  buildNumber,
		ProductName:  productName,
		MajorVersion: majorVersionNumber,
		MinorVersion: minorVersionNumber,
		UBR:          revision,
	}, nil
}

//GetPatchVersion returns full OS version with patch
func (o *OSInfo) GetPatchVersion() string {
	return fmt.Sprintf("%d.%d.%s.%d", o.MajorVersion, o.MinorVersion, o.BuildNumber, o.UBR)
}

//GetBuild returns OS version upto build number
func (o *OSInfo) GetBuild() string {
	return fmt.Sprintf("%d.%d.%s", o.MajorVersion, o.MinorVersion, o.BuildNumber)
}
<commit_msg>Add getOSInfo err info<commit_after>// +build windows

/*
Copyright 2017 The Kubernetes 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 winstats

import (
	"fmt"
	"golang.org/x/sys/windows/registry"
)

//OSInfo is a convenience class for retrieving Windows OS information
type OSInfo struct {
	BuildNumber, ProductName        string
	MajorVersion, MinorVersion, UBR uint64
}

// GetOSInfo reads Windows version information from the registry
func GetOSInfo() (*OSInfo, error) {
	// for log detail
	var keyPrefix string = `regedit:LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion`

	k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, open Windows %s failed: %w", keyPrefix, err)
	}
	defer k.Close()

	buildNumber, _, err := k.GetStringValue("CurrentBuildNumber")
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, get %s\\CurrentBuildNumber failed: %w", keyPrefix, err)
	}

	majorVersionNumber, _, err := k.GetIntegerValue("CurrentMajorVersionNumber")
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, get %s\\CurrentMajorVersionNumber failed: %w", keyPrefix, err)
	}

	minorVersionNumber, _, err := k.GetIntegerValue("CurrentMinorVersionNumber")
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, get %s\\CurrentMinorVersionNumber failed: %w", keyPrefix, err)
	}

	revision, _, err := k.GetIntegerValue("UBR")
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, get %s\\UBR failed: %w", keyPrefix, err)
	}

	productName, _, err := k.GetStringValue("ProductName")
	if err != nil {
		return nil, fmt.Errorf("getOSInfo, get %s\\ProductName failed: %w", keyPrefix, err)
	}

	return &OSInfo{
		BuildNumber:  buildNumber,
		ProductName:  productName,
		MajorVersion: majorVersionNumber,
		MinorVersion: minorVersionNumber,
		UBR:          revision,
	}, nil
}

//GetPatchVersion returns full OS version with patch
func (o *OSInfo) GetPatchVersion() string {
	return fmt.Sprintf("%d.%d.%s.%d", o.MajorVersion, o.MinorVersion, o.BuildNumber, o.UBR)
}

//GetBuild returns OS version upto build number
func (o *OSInfo) GetBuild() string {
	return fmt.Sprintf("%d.%d.%s", o.MajorVersion, o.MinorVersion, o.BuildNumber)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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 components

import (
	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/loader"
)

// KubeDnsOptionsBuilder adds options for kube-dns
type KubeDnsOptionsBuilder struct {
	Context *OptionsContext
}

var _ loader.OptionsBuilder = &KubeDnsOptionsBuilder{}

// BuildOptions fills in the kubedns model
func (b *KubeDnsOptionsBuilder) BuildOptions(o interface{}) error {
	clusterSpec := o.(*kops.ClusterSpec)

	if clusterSpec.KubeDNS == nil {
		clusterSpec.KubeDNS = &kops.KubeDNSConfig{}
	}

	clusterSpec.KubeDNS.Replicas = 2

	if clusterSpec.KubeDNS.CacheMaxSize == 0 {
		clusterSpec.KubeDNS.CacheMaxSize = 1000
	}

	if clusterSpec.KubeDNS.CacheMaxConcurrent == 0 {
		clusterSpec.KubeDNS.CacheMaxConcurrent = 150
	}

	if clusterSpec.KubeDNS.ServerIP == "" {
		ip, err := WellKnownServiceIP(clusterSpec, 10)
		if err != nil {
			return err
		}
		clusterSpec.KubeDNS.ServerIP = ip.String()
	}

	if clusterSpec.KubeDNS.Domain == "" {
		clusterSpec.KubeDNS.Domain = clusterSpec.ClusterDNSDomain
	}

	if clusterSpec.KubeDNS.MemoryRequest == nil || clusterSpec.KubeDNS.MemoryRequest.IsZero() {
		defaultMemoryRequest := resource.MustParse("70Mi")
		clusterSpec.KubeDNS.MemoryRequest = &defaultMemoryRequest
	}

	if clusterSpec.KubeDNS.CPURequest == nil || clusterSpec.KubeDNS.CPURequest.IsZero() {
		defaultCPURequest := resource.MustParse("100m")
		clusterSpec.KubeDNS.CPURequest = &defaultCPURequest
	}

	if clusterSpec.KubeDNS.MemoryLimit == nil || clusterSpec.KubeDNS.MemoryLimit.IsZero() {
		defaultMemoryLimit := resource.MustParse("170Mi")
		clusterSpec.KubeDNS.MemoryLimit = &defaultMemoryLimit
	}

	NodeLocalDNS := clusterSpec.KubeDNS.NodeLocalDNS
	if NodeLocalDNS == nil {
		NodeLocalDNS = &kops.NodeLocalDNSConfig{}
		NodeLocalDNS.Enabled = fi.Bool(false)
	} else if fi.BoolValue(NodeLocalDNS.Enabled) && NodeLocalDNS.LocalIP == "" {
		NodeLocalDNS.LocalIP = "169.254.20.10"
	}

	return nil
}
<commit_msg>NodeLocalDNS config population: small tweaks<commit_after>/*
Copyright 2019 The Kubernetes 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 components

import (
	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/loader"
)

// KubeDnsOptionsBuilder adds options for kube-dns
type KubeDnsOptionsBuilder struct {
	Context *OptionsContext
}

var _ loader.OptionsBuilder = &KubeDnsOptionsBuilder{}

// BuildOptions fills in the kubedns model
func (b *KubeDnsOptionsBuilder) BuildOptions(o interface{}) error {
	clusterSpec := o.(*kops.ClusterSpec)

	if clusterSpec.KubeDNS == nil {
		clusterSpec.KubeDNS = &kops.KubeDNSConfig{}
	}

	clusterSpec.KubeDNS.Replicas = 2

	if clusterSpec.KubeDNS.CacheMaxSize == 0 {
		clusterSpec.KubeDNS.CacheMaxSize = 1000
	}

	if clusterSpec.KubeDNS.CacheMaxConcurrent == 0 {
		clusterSpec.KubeDNS.CacheMaxConcurrent = 150
	}

	if clusterSpec.KubeDNS.ServerIP == "" {
		ip, err := WellKnownServiceIP(clusterSpec, 10)
		if err != nil {
			return err
		}
		clusterSpec.KubeDNS.ServerIP = ip.String()
	}

	if clusterSpec.KubeDNS.Domain == "" {
		clusterSpec.KubeDNS.Domain = clusterSpec.ClusterDNSDomain
	}

	if clusterSpec.KubeDNS.MemoryRequest == nil || clusterSpec.KubeDNS.MemoryRequest.IsZero() {
		defaultMemoryRequest := resource.MustParse("70Mi")
		clusterSpec.KubeDNS.MemoryRequest = &defaultMemoryRequest
	}

	if clusterSpec.KubeDNS.CPURequest == nil || clusterSpec.KubeDNS.CPURequest.IsZero() {
		defaultCPURequest := resource.MustParse("100m")
		clusterSpec.KubeDNS.CPURequest = &defaultCPURequest
	}

	if clusterSpec.KubeDNS.MemoryLimit == nil || clusterSpec.KubeDNS.MemoryLimit.IsZero() {
		defaultMemoryLimit := resource.MustParse("170Mi")
		clusterSpec.KubeDNS.MemoryLimit = &defaultMemoryLimit
	}

	nodeLocalDNS := clusterSpec.KubeDNS.NodeLocalDNS
	if nodeLocalDNS == nil {
		nodeLocalDNS = &kops.NodeLocalDNSConfig{}
		clusterSpec.KubeDNS.NodeLocalDNS = nodeLocalDNS
	}
	if nodeLocalDNS.Enabled == nil {
		nodeLocalDNS.Enabled = fi.Bool(false)
	}
	if fi.BoolValue(nodeLocalDNS.Enabled) && nodeLocalDNS.LocalIP == "" {
		nodeLocalDNS.LocalIP = "169.254.20.10"
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"time"
)

type Line struct {
	Moves []Move
}

const INFINITY int = int(math.MaxInt32) // I win!
const MATE int = INFINITY - 10          // Value of a checkmate in 1

var nodecount uint64
var abort bool

func Evaluate(board *Board) int {
	phase := calcphase(board)
	opening := MaterialCount(board, false)
	endgame := MaterialCount(board, true)
	score := ((opening * (256 - phase)) + (endgame * phase)) / 256
	if board.ToMove == BLACK {
		score = -score
	}
	return score
}

func calcphase(board *Board) int {
	TotalPhase := 24 // PawnPhase*16 + KnightPhase*4 + BishopPhase*4 + RookPhase*4 + QueenPhase*2
	phase := TotalPhase
	for _, i := range board.PieceList {
		phase -= PValue[GetPiece(board.Data[i])]
	}
	return (phase*256 + (TotalPhase / 2)) / TotalPhase
}

func MaterialCount(b *Board, endgame bool) int {
	var retval int
	for _, i := range b.PieceList {
		if OnBoard(i) && GetPiece(b.Data[i]) != EMPTY {
			if GetSide(b.Data[i]) == WHITE {
				retval += Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), WHITE, i, endgame)
			} else {
				retval -= (Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), BLACK, i, endgame))
			}
		}
	}
	return retval
}

func Pst(piece, side, index byte, endgame bool) int {
	switch piece {
	case PAWN:
		return GetPst(index, side, pstPawnMg[:], pstPawnEg[:], endgame)
	case KNIGHT:
		return GetPst(index, side, pstKnightMg[:], pstKnightEg[:], endgame)
	case BISHOP:
		return GetPst(index, side, pstBishopMg[:], pstBishopEg[:], endgame)
	case ROOK:
		return GetPst(index, side, pstRookMg[:], pstRookEg[:], endgame)
	case QUEEN:
		return GetPst(index, side, pstQueenMg[:], pstQueenEg[:], endgame)
	case KING:
		return GetPst(index, side, pstKingMg[:], pstKingEg[:], endgame)
	default:
		return 0
	}
}

func GetPst(index, side byte, tableMg []int, tableEg []int, endgame bool) int {
	var table []int
	if endgame {
		table = tableEg[:]
	} else {
		table = tableMg[:]
	}
	file, rank := IndexToCartesian(index)
	var tableindex byte
	if side == BLACK {
		tableindex = (8 * (7 - rank)) + file
	} else {
		tableindex = (8 * rank) + file
	}
	return table[tableindex]
}

func Quies(board *Board, alpha, beta int) int {
	nodecount++
	if abort {
		return 0
	}
	eval := Evaluate(board)
	if eval >= beta {
		return beta
	}
	if eval > alpha {
		alpha = eval
	}
	moves := FilterCaptures(MoveGen(board))
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -Quies(board, -beta, -alpha)
		UnmakeMove(board, &move, undo)
		if abort {
			return 0
		}
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
		}
	}
	return alpha
}

func AlphaBeta(board *Board, depth, alpha, beta, mate int, pline *Line) int {
	nodecount++
	if abort {
		return 0
	}
	legal := 0
	if depth <= 0 {
		return Quies(board, alpha, beta)
	}
	line := new(Line)
	moves := MoveGen(board)
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -AlphaBeta(board, depth-1, -beta, -alpha, mate-1, line)
		UnmakeMove(board, &move, undo)
		if abort {
			return 0
		}
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
			pline.Moves = append([]Move{move}, pline.Moves...)
			line.Moves = append(pline.Moves, move)
		}
		legal++
	}
	if legal == 0 {
		if !InCheck(board) {
			return 0
		}
		return -mate
	}
	return alpha
}

func AllotTime(board *Board) time.Duration {
	repeat := TimeRepeat
	if repeat <= 0 {
		repeat = 40
	}
	moves := repeat - board.Moves
	for moves <= 0 {
		moves += repeat
	}
	return (Clock/time.Duration(moves+1) - 20*time.Millisecond)
}

func ThinkingOutput(depth, score int, start time.Time, pv *Line) {
	fmt.Println(depth, score, int64(time.Since(start)/time.Millisecond)/10, nodecount, pv)
}

func SleepThread(board *Board, start time.Time) {
	bedoneby := AllotTime(board)
	fmt.Println("# ", Clock, ": allocated ", bedoneby)
	time.Sleep(bedoneby)
	abort = true
}

func FindMove(board *Board) *Move {
	start := time.Now()
	abort = false
	nodecount = 0
	retval := new(Move)
	for depth := 1; ; depth++ {
		line := new(Line)
		score := AlphaBeta(board, depth, -INFINITY, INFINITY, MATE, line)
		ThinkingOutput(depth, score, start, line)
		if !abort {
			retval = &line.Moves[0]
		} else {
			break
		}

		if depth == 1 {
			Clock -= time.Since(start)
			go SleepThread(board, start)
		}
	}
	return retval
}
<commit_msg>Fix PV handling<commit_after>package main

import (
	"fmt"
	"math"
	"time"
)

const INFINITY int = int(math.MaxInt32) // I win!
const MATE int = INFINITY - 10          // Value of a checkmate in 1

var nodecount uint64
var abort bool

func Evaluate(board *Board) int {
	phase := calcphase(board)
	opening := MaterialCount(board, false)
	endgame := MaterialCount(board, true)
	score := ((opening * (256 - phase)) + (endgame * phase)) / 256
	if board.ToMove == BLACK {
		score = -score
	}
	return score
}

func calcphase(board *Board) int {
	TotalPhase := 24 // PawnPhase*16 + KnightPhase*4 + BishopPhase*4 + RookPhase*4 + QueenPhase*2
	phase := TotalPhase
	for _, i := range board.PieceList {
		phase -= PValue[GetPiece(board.Data[i])]
	}
	return (phase*256 + (TotalPhase / 2)) / TotalPhase
}

func MaterialCount(b *Board, endgame bool) int {
	var retval int
	for _, i := range b.PieceList {
		if OnBoard(i) && GetPiece(b.Data[i]) != EMPTY {
			if GetSide(b.Data[i]) == WHITE {
				retval += Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), WHITE, i, endgame)
			} else {
				retval -= (Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), BLACK, i, endgame))
			}
		}
	}
	return retval
}

func Pst(piece, side, index byte, endgame bool) int {
	switch piece {
	case PAWN:
		return GetPst(index, side, pstPawnMg[:], pstPawnEg[:], endgame)
	case KNIGHT:
		return GetPst(index, side, pstKnightMg[:], pstKnightEg[:], endgame)
	case BISHOP:
		return GetPst(index, side, pstBishopMg[:], pstBishopEg[:], endgame)
	case ROOK:
		return GetPst(index, side, pstRookMg[:], pstRookEg[:], endgame)
	case QUEEN:
		return GetPst(index, side, pstQueenMg[:], pstQueenEg[:], endgame)
	case KING:
		return GetPst(index, side, pstKingMg[:], pstKingEg[:], endgame)
	default:
		return 0
	}
}

func GetPst(index, side byte, tableMg []int, tableEg []int, endgame bool) int {
	var table []int
	if endgame {
		table = tableEg[:]
	} else {
		table = tableMg[:]
	}
	file, rank := IndexToCartesian(index)
	var tableindex byte
	if side == BLACK {
		tableindex = (8 * (7 - rank)) + file
	} else {
		tableindex = (8 * rank) + file
	}
	return table[tableindex]
}

func Quies(board *Board, alpha, beta int) int {
	nodecount++
	if abort {
		return 0
	}
	eval := Evaluate(board)
	if eval >= beta {
		return beta
	}
	if eval > alpha {
		alpha = eval
	}
	moves := FilterCaptures(MoveGen(board))
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -Quies(board, -beta, -alpha)
		UnmakeMove(board, &move, undo)
		if abort {
			return 0
		}
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
		}
	}
	return alpha
}

func AlphaBeta(board *Board, depth, alpha, beta, mate int, pline *[]Move) int {
	nodecount++

	if abort {
		return 0
	}

	legal := 0

	if depth <= 0 {
		*pline = nil
		return Quies(board, alpha, beta)
	}

	var line []Move

	moves := MoveGen(board)

	for _, move := range moves {

		undo := MakeMove(board, &move)

		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}

		line = nil

		val := -AlphaBeta(board, depth-1, -beta, -alpha, mate-1, &line)

		UnmakeMove(board, &move, undo)

		if abort {
			return 0
		}

		if val >= beta {
			return beta
		}

		if val > alpha {
			alpha = val
			*pline = append([]Move{move}, line...)
		}

		legal++
	}

	if legal == 0 {

		if !InCheck(board) {
			return 0
		}

		return -mate
	}

	return alpha
}

func AllotTime(board *Board) time.Duration {
	repeat := TimeRepeat
	if repeat <= 0 {
		repeat = 40
	}
	moves := repeat - board.Moves
	for moves <= 0 {
		moves += repeat
	}
	return (Clock/time.Duration(moves+1) - 20*time.Millisecond)
}

func ThinkingOutput(depth, score int, start time.Time, pv []Move) {
	fmt.Println(depth, score, int64(time.Since(start)/time.Millisecond)/10, nodecount, pv)
}

func SleepThread(board *Board, start time.Time) {
	bedoneby := AllotTime(board)
	fmt.Println("# ", Clock, ": allocated ", bedoneby)
	time.Sleep(bedoneby)
	abort = true
}

func FindMove(board *Board) *Move {
	start := time.Now()
	abort = false
	nodecount = 0
	retval := new(Move)
	for depth := 1; ; depth++ {
		var line []Move
		score := AlphaBeta(board, depth, -INFINITY, INFINITY, MATE, &line)
		ThinkingOutput(depth, score, start, line)
		if !abort {
			retval = &line[0]
		} else {
			break
		}

		if depth == 1 {
			Clock -= time.Since(start)
			go SleepThread(board, start)
		}
	}
	return retval
}
<|endoftext|>