<commit_before>package middleware

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/docker/distribution/context"
	storagedriver "github.com/docker/distribution/registry/storage/driver"
	storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware"

	"github.com/denverdino/aliyungo/cdn/auth"
)

// aliCdnStorageMiddleware provides a simple implementation of layerHandler that
// constructs temporary signed AliCDN URLs from the storagedriver layer URL,
// then issues HTTP Temporary Redirects to this AliCDN content URL.
type aliCdnStorageMiddleware struct {
	storagedriver.StorageDriver
	baseURL   string
	urlSigner *auth.URLSigner
	duration  time.Duration
}

var _ storagedriver.StorageDriver = &aliCdnStorageMiddleware{}

// newAliCdnLayerHandler constructs and returns a new AliCDN
// LayerHandler implementation.
// Required options: baseurl, authtype, privatekey
// Optional options: duration
func newAliCdnStorageMiddleware(storageDriver storagedriver.StorageDriver, options map[string]interface{}) (storagedriver.StorageDriver, error) {
	// parse baseurl
	base, ok := options["baseurl"]
	if !ok {
		return nil, fmt.Errorf("no baseurl provided")
	}
	baseURL, ok := base.(string)
	if !ok {
		return nil, fmt.Errorf("baseurl must be a string")
	}
	if !strings.Contains(baseURL, "://") {
		baseURL = "https://" + baseURL
	}
	if _, err := url.Parse(baseURL); err != nil {
		return nil, fmt.Errorf("invalid baseurl: %v", err)
	}

	// parse authtype
	at, ok := options["authtype"]
	if !ok {
		return nil, fmt.Errorf("no authtype provided")
	}
	authType, ok := at.(string)
	if !ok {
		return nil, fmt.Errorf("authtype must be a string")
	}
	if authType != "a" && authType != "b" && authType != "c" {
		return nil, fmt.Errorf("invalid authentication type")
	}

	// parse privatekey
	pk, ok := options["privatekey"]
	if !ok {
		return nil, fmt.Errorf("no privatekey provided")
	}
	privateKey, ok := pk.(string)
	if !ok {
		return nil, fmt.Errorf("privatekey must be a string")
	}

	urlSigner := auth.NewURLSigner(authType, privateKey)

	// parse duration
	duration := 60 * time.Minute
	d, ok := options["duration"]
	if ok {
		switch d := d.(type) {
		case time.Duration:
			duration = d
		case string:
			dur, err := time.ParseDuration(d)
			if err != nil {
				return nil, fmt.Errorf("invalid duration: %s", err)
			}
			duration = dur
		}
	}

	return &aliCdnStorageMiddleware{
		StorageDriver: storageDriver,
		baseURL:       baseURL,
		urlSigner:     urlSigner,
		duration:      duration,
	}, nil
}

// URLFor attempts to find a url which may be used to retrieve the file at the given path.
// Returns an error if the file cannot be found.
func (ac *aliCdnStorageMiddleware) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) {

	if ac.StorageDriver.Name() != "oss" {
		context.GetLogger(ctx).Warn("the AliCdn middleware does not support this backend storage driver")
		return ac.StorageDriver.URLFor(ctx, path, options)
	}
	acURL, err := ac.urlSigner.Sign(ac.baseURL+path, time.Now().Add(ac.duration))
	if err != nil {
		return "", err
	}
	return acURL, nil
}

// init registers the alicdn layerHandler backend.
func init() {
	storagemiddleware.Register("alicdn", storagemiddleware.InitFunc(newAliCdnStorageMiddleware))
}
<commit_msg>fix func name<commit_after>package middleware

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/docker/distribution/context"
	storagedriver "github.com/docker/distribution/registry/storage/driver"
	storagemiddleware "github.com/docker/distribution/registry/storage/driver/middleware"

	"github.com/denverdino/aliyungo/cdn/auth"
)

// aliCDNStorageMiddleware provides a simple implementation of layerHandler that
// constructs temporary signed AliCDN URLs from the storagedriver layer URL,
// then issues HTTP Temporary Redirects to this AliCDN content URL.
type aliCDNStorageMiddleware struct {
	storagedriver.StorageDriver
	baseURL   string
	urlSigner *auth.URLSigner
	duration  time.Duration
}

var _ storagedriver.StorageDriver = &aliCDNStorageMiddleware{}

// newAliCDNStorageMiddleware constructs and returns a new AliCDN
// layerHandler implementation.
// Required options: baseurl, authtype, privatekey
// Optional options: duration
func newAliCDNStorageMiddleware(storageDriver storagedriver.StorageDriver, options map[string]interface{}) (storagedriver.StorageDriver, error) {
	// parse baseurl
	base, ok := options["baseurl"]
	if !ok {
		return nil, fmt.Errorf("no baseurl provided")
	}
	baseURL, ok := base.(string)
	if !ok {
		return nil, fmt.Errorf("baseurl must be a string")
	}
	if !strings.Contains(baseURL, "://") {
		baseURL = "https://" + baseURL
	}
	if _, err := url.Parse(baseURL); err != nil {
		return nil, fmt.Errorf("invalid baseurl: %v", err)
	}

	// parse authtype
	at, ok := options["authtype"]
	if !ok {
		return nil, fmt.Errorf("no authtype provided")
	}
	authType, ok := at.(string)
	if !ok {
		return nil, fmt.Errorf("authtype must be a string")
	}
	if authType != "a" && authType != "b" && authType != "c" {
		return nil, fmt.Errorf("invalid authentication type")
	}

	// parse privatekey
	pk, ok := options["privatekey"]
	if !ok {
		return nil, fmt.Errorf("no privatekey provided")
	}
	privateKey, ok := pk.(string)
	if !ok {
		return nil, fmt.Errorf("privatekey must be a string")
	}

	urlSigner := auth.NewURLSigner(authType, privateKey)

	// parse duration
	duration := 60 * time.Minute
	d, ok := options["duration"]
	if ok {
		switch d := d.(type) {
		case time.Duration:
			duration = d
		case string:
			dur, err := time.ParseDuration(d)
			if err != nil {
				return nil, fmt.Errorf("invalid duration: %s", err)
			}
			duration = dur
		}
	}

	return &aliCDNStorageMiddleware{
		StorageDriver: storageDriver,
		baseURL:       baseURL,
		urlSigner:     urlSigner,
		duration:      duration,
	}, nil
}

// URLFor attempts to find a url which may be used to retrieve the file at the given path.
func (ac *aliCDNStorageMiddleware) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) {

	if ac.StorageDriver.Name() != "oss" {
		context.GetLogger(ctx).Warn("the AliCDN middleware does not support this backend storage driver")
		return ac.StorageDriver.URLFor(ctx, path, options)
	}
	acURL, err := ac.urlSigner.Sign(ac.baseURL+path, time.Now().Add(ac.duration))
	if err != nil {
		return "", err
	}
	return acURL, nil
}

// init registers the alicdn layerHandler backend.
func init() {
	storagemiddleware.Register("alicdn", storagemiddleware.InitFunc(newAliCDNStorageMiddleware))
}
<|endoftext|>


<commit_before>package emil

import (
	"errors"
	"fmt"
	"time"
)

var errNowNewAnalysis = errors.New("errNowNewAnalysis")

type Analysis struct {
	dtm int // Depth to mate

	board *Board
	move  *Move
}

func (a *Analysis) Move() *Move {
	return a.move
}
func (a *Analysis) Board() *Board {
	return a.board
}

// EndGameDb to query for mate in 1,2, etc.
type EndGameDb struct {
	positionDb map[string]*Analysis

	dtmDb []map[string]bool

	searchedPositions int
}

func (db *EndGameDb) Find(board *Board) (bestMove *Move) {
	if DEBUG {
		fmt.Printf("Find:\n%s\n", board.String())
	}
	a := db.positionDb[board.String()]
	if DEBUG {
		fmt.Printf("Found: positionDb with dtm %d\n", a.dtm)
	}
	return a.move
}
func (db *EndGameDb) FindMatesIn(dtm int) (as []*Analysis) {
	if dtm == -1 {
		for _, a := range db.positionDb {
			if a.dtm == -1 {
				as = append(as, a)
			}
		}
	} else {
		for str := range db.dtmDb[dtm] {
			as = append(as, db.positionDb[str])
		}
	}
	return as
}

func (db *EndGameDb) FindMates() (as []*Analysis) {
	return db.FindMatesIn(0)
}

func (db *EndGameDb) FindMate(piece, square int) (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		if a.board.squares[square] == piece {
			boards = append(boards, a.board)
		}
	}
	return boards
}

func (db *EndGameDb) addPosition(board *Board) {
	db.addAnalysis(board, -1, nil)
}

func (db *EndGameDb) addAnalysis(board *Board, dtm int, move *Move) {
	a := &Analysis{
		dtm:   dtm,
		board: board}
	if move != nil {
		a.move = move.reverse()
	}
	if dtm >= 0 {
		if move != nil {
			playerForStep := playerForStepN(dtm)
			if playerForStep != move.player {
				panic("playerForStep != move.player")
			}
		}

		db.dtmDb[dtm][a.board.String()] = true
	}

	db.positionDb[a.board.String()] = a
}

func (db *EndGameDb) positions() int {
	return len(db.positionDb)
}

// find positions where black is checkmate
func (db *EndGameDb) retrogradeAnalysisStep1() {
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	start := time.Now()

	player := BLACK
	for boardStr, a := range db.positionDb {
		// mate only on border square
		blackKingSquare := BoardSquares[a.board.blackKing]
		if !blackKingSquare.isBorder {
			continue
		}
		// mate only with help from king
		if squaresDistances[a.board.blackKing][a.board.whiteKing] > 2 {
			continue
		}

		p := NewPosition(a.board, player)

		move := Search(p)
		db.searchedPositions++
		if move == nil {
			if isKingInCheck(p) {
				a.dtm = 0
				db.addAnalysis(a.board, 0, nil)
				if DEBUG {
					fmt.Printf("mate:\n%s\n", boardStr)
				}
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("searchedPositions %d\n", db.searchedPositions)
		fmt.Printf("db.dtmDb[0] %d\n", len(db.dtmDb[0]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}
}
func playerForStepN(dtm int) (player int) {
	if dtm%2 == 0 {
		return BLACK
	}
	return WHITE
}

func (db *EndGameDb) retrogradeAnalysisStepN(dtm int) (noError error) {
	start := time.Now()
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	player := playerForStepN(dtm)

	positions := 0
	if player == WHITE {
		for _, a := range db.positionDb {
			if db.isMateIn1357(a.board, dtm) >= 0 {
				positions++
			}
		}
		if DEBUG {
			fmt.Printf("WHITE Start positions %d\n", len(db.positionDb)-positions)
		}
		for _, a := range db.positionDb {
			if db.isMateIn1357(a.board, dtm) >= 0 {
				continue
			}
			p := NewPosition(a.board, player)
			if IsTheKingInCheck(p) {
				continue
			}
			moves := generateMoves(p)

			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newDtm := db.isMateIn0246(newBoard, dtm)
				if newDtm == dtm-1 {
					db.addAnalysis(a.board, dtm, m)
				}
			}
		}
	} else {
		for _, a := range db.positionDb {
			if db.isMateIn0246(a.board, dtm) >= 0 {
				positions++
			}
		}
		if DEBUG {
			fmt.Printf("BLACK Start positions %d\n", len(db.positionDb)-positions)
		}
		for _, a := range db.positionDb {
			if db.isMateIn0246(a.board, dtm) >= 0 {
				continue
			}
			p := NewPosition(a.board, player)
			moves := GenerateMoves(p)

			found := 0
			maxDTM := -1
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newDtm := db.isMateIn1357(newBoard, dtm)
				if newDtm > maxDTM {
					maxDTM = newDtm
				}
				if db.isMateIn1357(newBoard, dtm) >= 0 {
					found++
				}
			}

			if found == len(moves) {
				for _, m := range moves {
					db.addAnalysis(a.board, maxDTM+1, m)
				}
			}
		}
	}
	end := time.Now()

	if DEBUG {
		fmt.Printf("db.dtmDb[%d] %d\n", dtm, len(db.dtmDb[dtm]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}

	if len(db.dtmDb[dtm]) == 0 {
		return errNowNewAnalysis
	}
	return noError
}
func (db *EndGameDb) isMateIn0246(board *Board, maxDtm int) int {
	for dtm := 0; dtm < maxDtm; dtm += 2 {
		_, ok := db.dtmDb[dtm][board.String()]
		if ok {
			return dtm
		}
	}
	return -1
}
func (db *EndGameDb) isMateIn1357(board *Board, maxDtm int) int {
	for dtm := 1; dtm < maxDtm; dtm += 2 {
		_, ok := db.dtmDb[dtm][board.String()]
		if ok {
			return dtm
		}
	}
	return -1
}

func (db *EndGameDb) MaxDtm() int {
	return len(db.dtmDb)
}

func (db *EndGameDb) retrogradeAnalysis() {
	// find positions where black is checkmate
	db.retrogradeAnalysisStep1()
	dtm := 1
	for {
		err := db.retrogradeAnalysisStepN(dtm)
		if err != nil {
			break
		}
		dtm++
	}
}
func GenerateMoves(p *position) (list []*Move) {
	for _, m := range generateMoves(p) {
		b := p.board.DoMove(m)
		if !IsTheKingInCheck(NewPosition(b, WHITE)) {
			list = append(list, m)
		}
	}
	return list
}
func generateMoves(p *position) (list []*Move) {
	for src, piece := range p.board.squares {
		if isOwnPiece(p.player, piece) {
			switch abs(piece) {
			case kingValue:
				for _, dst := range kingDestinationsFrom(src) {
					capture := p.board.squares[dst]
					if isOtherKing(p.player, capture) {
						continue
					}
					if capture == Empty {
						list = append(list, newSilentMove(p.player, piece, src, dst))
					} else if !isOwnPiece(p.player, capture) {
						list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
					}
				}
			case rockValue:
				for _, dsts := range rockDestinationsFrom(src) {
					for _, dst := range dsts {
						capture := p.board.squares[dst]
						if isOtherKing(p.player, capture) {
							break
						}
						if capture == Empty {
							list = append(list, newSilentMove(p.player, piece, src, dst))
						} else if !isOwnPiece(p.player, capture) {
							list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
							break
						} else {
							break // onOwnPiece
						}
					}
				}
			}
		}
	}
	return list
}

// NewEndGameDb generates an end game DB for KRK
func NewEndGameDb() *EndGameDb {
	var err error
	start := time.Now()

	endGames := &EndGameDb{
		positionDb: make(map[string]*Analysis),
		dtmDb:      make([]map[string]bool, 0)}

	for wk := A1; wk <= H8; wk++ {
		//for wk := E3; wk <= E3; wk++ {
		if DEBUG {
			fmt.Printf("White king on %s\n", BoardSquares[wk])
		}
		for wr := A1; wr <= H8; wr++ {
			for bk := A1; bk <= H8; bk++ {

				board := NewBoard()

				err = board.Setup(WhiteKing, wk)
				if err != nil {
					continue
				}

				err = board.Setup(WhiteRock, wr)
				if err != nil {
					continue
				}

				err = board.Setup(BlackKing, bk)
				if err != nil {
					continue
				}

				err = board.kingsToClose()
				if err != nil {
					continue
				}

				endGames.addPosition(board)
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("all positions %d\n", 64*63*62)
		fmt.Printf("endGames.positions() %d\n", endGames.positions())
		fmt.Printf("difference %d\n", 64*63*62-endGames.positions())
		fmt.Printf("duration %v\n", end.Sub(start))
	}
	endGames.retrogradeAnalysis()

	return endGames
}
<commit_msg>no new analyses<commit_after>package emil

import (
	"errors"
	"fmt"
	"time"
)

var errNowNewAnalysis = errors.New("errNowNewAnalysis")

type Analysis struct {
	dtm int // Depth to mate

	board *Board
	move  *Move
}

func (a *Analysis) Move() *Move {
	return a.move
}
func (a *Analysis) Board() *Board {
	return a.board
}

// EndGameDb to query for mate in 1,2, etc.
type EndGameDb struct {
	positionDb map[string]*Analysis

	dtmDb []map[string]bool

	searchedPositions int
}

func (db *EndGameDb) Find(board *Board) (bestMove *Move) {
	if DEBUG {
		fmt.Printf("Find:\n%s\n", board.String())
	}
	a := db.positionDb[board.String()]
	if DEBUG {
		fmt.Printf("Found: positionDb with dtm %d\n", a.dtm)
	}
	return a.move
}
func (db *EndGameDb) FindMatesIn(dtm int) (as []*Analysis) {
	if dtm == -1 {
		for _, a := range db.positionDb {
			if a.dtm == -1 {
				as = append(as, a)
			}
		}
	} else {
		for str := range db.dtmDb[dtm] {
			as = append(as, db.positionDb[str])
		}
	}
	return as
}

func (db *EndGameDb) FindMates() (as []*Analysis) {
	return db.FindMatesIn(0)
}

func (db *EndGameDb) FindMate(piece, square int) (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		if a.board.squares[square] == piece {
			boards = append(boards, a.board)
		}
	}
	return boards
}

func (db *EndGameDb) addPosition(board *Board) {
	a := &Analysis{
		dtm:   -1,
		board: board}
	db.positionDb[a.board.String()] = a
}

func (db *EndGameDb) addAnalysis(board *Board, dtm int, move *Move) {
	a := db.positionDb[board.String()]
	if move != nil {
		a.move = move.reverse()
	}
	if dtm >= 0 {
		if move != nil {
			playerForStep := playerForStepN(dtm)
			if playerForStep != move.player {
				panic("playerForStep != move.player")
			}
		}

		db.dtmDb[dtm][board.String()] = true
	}

}

func (db *EndGameDb) positions() int {
	return len(db.positionDb)
}

// find positions where black is checkmate
func (db *EndGameDb) retrogradeAnalysisStep1() {
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	start := time.Now()

	player := BLACK
	for boardStr, a := range db.positionDb {
		// mate only on border square
		blackKingSquare := BoardSquares[a.board.blackKing]
		if !blackKingSquare.isBorder {
			continue
		}
		// mate only with help from king
		if squaresDistances[a.board.blackKing][a.board.whiteKing] > 2 {
			continue
		}

		p := NewPosition(a.board, player)

		move := Search(p)
		db.searchedPositions++
		if move == nil {
			if isKingInCheck(p) {
				a.dtm = 0
				db.addAnalysis(a.board, 0, nil)
				if DEBUG {
					fmt.Printf("mate:\n%s\n", boardStr)
				}
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("searchedPositions %d\n", db.searchedPositions)
		fmt.Printf("db.dtmDb[0] %d\n", len(db.dtmDb[0]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}
}
func playerForStepN(dtm int) (player int) {
	if dtm%2 == 0 {
		return BLACK
	}
	return WHITE
}

func (db *EndGameDb) retrogradeAnalysisStepN(dtm int) (noError error) {
	start := time.Now()
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	player := playerForStepN(dtm)

	positions := 0
	if player == WHITE {
		for _, a := range db.positionDb {
			if db.isMateIn1357(a.board, dtm) >= 0 {
				positions++
			}
		}
		if DEBUG {
			fmt.Printf("WHITE Start positions %d\n", len(db.positionDb)-positions)
		}
		for _, a := range db.positionDb {
			if db.isMateIn1357(a.board, dtm) >= 0 {
				continue
			}
			p := NewPosition(a.board, player)
			if IsTheKingInCheck(p) {
				continue
			}
			moves := generateMoves(p)

			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newDtm := db.isMateIn0246(newBoard, dtm)
				if newDtm == dtm-1 {
					db.addAnalysis(a.board, dtm, m)
				}
			}
		}
	} else {
		for _, a := range db.positionDb {
			if db.isMateIn0246(a.board, dtm) >= 0 {
				positions++
			}
		}
		if DEBUG {
			fmt.Printf("BLACK Start positions %d\n", len(db.positionDb)-positions)
		}
		for _, a := range db.positionDb {
			if db.isMateIn0246(a.board, dtm) >= 0 {
				continue
			}
			p := NewPosition(a.board, player)
			moves := GenerateMoves(p)

			found := 0
			maxDTM := -1
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newDtm := db.isMateIn1357(newBoard, dtm)
				if newDtm > maxDTM {
					maxDTM = newDtm
				}
				if db.isMateIn1357(newBoard, dtm) >= 0 {
					found++
				}
			}

			if found == len(moves) {
				for _, m := range moves {
					db.addAnalysis(a.board, maxDTM+1, m)
				}
			}
		}
	}
	end := time.Now()

	if DEBUG {
		fmt.Printf("db.dtmDb[%d] %d\n", dtm, len(db.dtmDb[dtm]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}

	if len(db.dtmDb[dtm]) == 0 {
		return errNowNewAnalysis
	}
	return noError
}
func (db *EndGameDb) isMateIn0246(board *Board, maxDtm int) int {
	for dtm := 0; dtm < maxDtm; dtm += 2 {
		_, ok := db.dtmDb[dtm][board.String()]
		if ok {
			return dtm
		}
	}
	return -1
}
func (db *EndGameDb) isMateIn1357(board *Board, maxDtm int) int {
	for dtm := 1; dtm < maxDtm; dtm += 2 {
		_, ok := db.dtmDb[dtm][board.String()]
		if ok {
			return dtm
		}
	}
	return -1
}

func (db *EndGameDb) MaxDtm() int {
	return len(db.dtmDb)
}

func (db *EndGameDb) retrogradeAnalysis() {
	// find positions where black is checkmate
	db.retrogradeAnalysisStep1()
	dtm := 1
	for {
		err := db.retrogradeAnalysisStepN(dtm)
		if err != nil {
			break
		}
		dtm++
	}
}
func GenerateMoves(p *position) (list []*Move) {
	for _, m := range generateMoves(p) {
		b := p.board.DoMove(m)
		if !IsTheKingInCheck(NewPosition(b, WHITE)) {
			list = append(list, m)
		}
	}
	return list
}
func generateMoves(p *position) (list []*Move) {
	for src, piece := range p.board.squares {
		if isOwnPiece(p.player, piece) {
			switch abs(piece) {
			case kingValue:
				for _, dst := range kingDestinationsFrom(src) {
					capture := p.board.squares[dst]
					if isOtherKing(p.player, capture) {
						continue
					}
					if capture == Empty {
						list = append(list, newSilentMove(p.player, piece, src, dst))
					} else if !isOwnPiece(p.player, capture) {
						list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
					}
				}
			case rockValue:
				for _, dsts := range rockDestinationsFrom(src) {
					for _, dst := range dsts {
						capture := p.board.squares[dst]
						if isOtherKing(p.player, capture) {
							break
						}
						if capture == Empty {
							list = append(list, newSilentMove(p.player, piece, src, dst))
						} else if !isOwnPiece(p.player, capture) {
							list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
							break
						} else {
							break // onOwnPiece
						}
					}
				}
			}
		}
	}
	return list
}

// NewEndGameDb generates an end game DB for KRK
func NewEndGameDb() *EndGameDb {
	var err error
	start := time.Now()

	endGames := &EndGameDb{
		positionDb: make(map[string]*Analysis),
		dtmDb:      make([]map[string]bool, 0)}

	for wk := A1; wk <= H8; wk++ {
		//for wk := E3; wk <= E3; wk++ {
		if DEBUG {
			fmt.Printf("White king on %s\n", BoardSquares[wk])
		}
		for wr := A1; wr <= H8; wr++ {
			for bk := A1; bk <= H8; bk++ {

				board := NewBoard()

				err = board.Setup(WhiteKing, wk)
				if err != nil {
					continue
				}

				err = board.Setup(WhiteRock, wr)
				if err != nil {
					continue
				}

				err = board.Setup(BlackKing, bk)
				if err != nil {
					continue
				}

				err = board.kingsToClose()
				if err != nil {
					continue
				}

				endGames.addPosition(board)
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("all positions %d\n", 64*63*62)
		fmt.Printf("endGames.positions() %d\n", endGames.positions())
		fmt.Printf("difference %d\n", 64*63*62-endGames.positions())
		fmt.Printf("duration %v\n", end.Sub(start))
	}
	endGames.retrogradeAnalysis()

	return endGames
}
<|endoftext|>


<commit_before>package agent

import (
	"errors"
	"fmt"
	"log"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/ChrisMcKenzie/dropship/dropship"
)

// Dispatcher is responsible for managing a given services state and
// sending work to the Runner pool
type Dispatcher struct {
	config     dropship.Config
	task       *Runner
	hash       string
	duration   time.Duration
	wg         *sync.WaitGroup
	shutdownCh <-chan struct{}
}

func NewDispatcher(cfg dropship.Config, t *Runner, wg *sync.WaitGroup, shutdownCh <-chan struct{}) (*Dispatcher, error) {
	w := Dispatcher{
		config:     cfg,
		task:       t,
		shutdownCh: shutdownCh,
		wg:         wg,
	}

	var err error
	w.duration, err = time.ParseDuration(cfg.CheckInterval)
	if err != nil {
		return nil, fmt.Errorf("Dispatcher: Failed to start %s", err)
	}

	go w.start()

	return &w, nil
}

func (w *Dispatcher) start() {
	for {
		select {
		case _, ok := <-w.shutdownCh:
			if !ok {
				log.Printf("Shutting down dispatcher for %s", w.config.Name)
				w.wg.Done()
				return
			}
		case <-time.After(w.duration):
			w.task.Do(w)
		}
	}
}

func (w *Dispatcher) Work() {
	log.Printf("[INF]: Starting Update check for %s...", w.config.Name)

	u := w.config.Updater

	isOutOfDate, err := u.IsOutdated(w.config.Hash, w.config.Artifact)
	if err != nil {
		log.Printf("[ERR]: Unable to check updates for %s %v", w.config.Name, err)
		return
	}

	if isOutOfDate {
		if w.config.Sequential {
			log.Printf("[INF]: Acquiring lock for %s", w.config.Name)
			l := w.config.Locker
			if err != nil {
				log.Printf("[ERR]: Unable to retreive update lock. %v", err)
				return
			}
			_, err = l.Acquire(w.shutdownCh)
			if err != nil {
				log.Printf("[ERR]: Unable to retreive update lock. %v", err)
				return
			}
			defer l.Release()
		}

		log.Printf("[INF]: Downloading update for %s...", w.config.Name)
		fr, meta, err := u.Download(w.config.Artifact)
		if err != nil {
			log.Printf("[ERR]: Unable to download update for %s %v", w.config.Name, err)
			return
		}

		// Deprecated
		if w.config.PreCommand != "" {
			log.Printf("[WARN]: preCommand has been deprecated.")
			res, err := executeCommand(w.config.PreCommand)
			if err != nil {
				log.Printf("[ERR]: Unable to execute preCommand. %v", err)
			} else {
				log.Printf("[INF]: preCommand executed successfully. %v", res)
			}
		}

		err = runHooks(w.config.BeforeHooks, w.config)
		if err != nil {
			log.Printf("[ERR]: Unable to execute beforeHooks. %v", err)
		}

		contentType := meta.ContentType
		if ct, ok := w.config.Artifact["content-type"]; ok {
			contentType = ct
		}

		i, err := getInstaller(contentType)
		if err != nil {
			log.Printf("[ERR]: %s for %s", w.config.Name, err)
			return
		}

		filesWritten, err := i.Install(w.config.Artifact["destination"], fr)
		if err != nil {
			log.Printf("[ERR]: Unable to install update for %s %s", w.config.Name, err)
		}

		// Deprecated
		if w.config.PostCommand != "" {
			log.Printf("[WARN]: postCommand has been deprecated.")
			defer func() {
				res, err := executeCommand(w.config.PostCommand)
				if err != nil {
					log.Printf("[ERR]: Unable to execute postCommand. %v", err)
				} else {
					log.Printf("[INF]: postCommand executed successfully. %v", res)
				}
			}()
		}

		log.Printf("[INF]: Update for %s installed successfully. [hash: %s] [files written: %d]", w.config.Name, meta.Hash, filesWritten)
		// TODO(ChrisMcKenzie): hashes should be stored somewhere more
		// permanent.
		w.config.Hash = meta.Hash

		err = runHooks(w.config.AfterHooks, w.config)
		if err != nil {
			log.Printf("[ERR]: Unable to execute beforeHooks. %v", err)
		}

		if w.config.UpdateTTL != "" {
			log.Printf("[INF]: Waiting %s before releasing lock and allowing next deployment.", w.config.UpdateTTL)
			ttl, err := time.ParseDuration(w.config.UpdateTTL)
			if err != nil {
				log.Printf("[ERR]: Failed to parse updateTTL make sure it is a valid duration in seconds")
			}
			<-time.After(ttl)
		}
	} else {
		log.Printf("[INF]: %s is up to date", w.config.Name)
	}
}

// Deprecated
func executeCommand(c string) (string, error) {
	cmd := strings.Fields(c)
	out, err := exec.Command(cmd[0], cmd[1:]...).Output()
	return string(out), err
}

func getInstaller(contentType string) (dropship.Installer, error) {
	switch contentType {
	case "application/x-gzip", "application/octet-stream":
		var installer dropship.TarInstaller
		return installer, nil
	default:
		var installer dropship.FileInstaller
		return installer, nil
	}

	return nil, errors.New("Unable to determine installation method from file type")
}

func runHooks(hooks []dropship.HookDefinition, service dropship.Config) error {
	for _, h := range hooks {
		for hookName, config := range h {
			hook := dropship.GetHookByName(hookName)
			if hook != nil {
				log.Printf("[INF]: Executing \"%s\" hook with %+v", hookName, config)
				err := hook.Execute(config, service)
				if err != nil {
					log.Printf("[ERR]: Unable to execute \"%s\" hook %v", hookName, err)
				}
			}
		}
	}
	return nil
}
<commit_msg>quick fix for tar installer<commit_after>package agent

import (
	"errors"
	"fmt"
	"log"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/ChrisMcKenzie/dropship/dropship"
)

// Dispatcher is responsible for managing a given services state and
// sending work to the Runner pool
type Dispatcher struct {
	config     dropship.Config
	task       *Runner
	hash       string
	duration   time.Duration
	wg         *sync.WaitGroup
	shutdownCh <-chan struct{}
}

func NewDispatcher(cfg dropship.Config, t *Runner, wg *sync.WaitGroup, shutdownCh <-chan struct{}) (*Dispatcher, error) {
	w := Dispatcher{
		config:     cfg,
		task:       t,
		shutdownCh: shutdownCh,
		wg:         wg,
	}

	var err error
	w.duration, err = time.ParseDuration(cfg.CheckInterval)
	if err != nil {
		return nil, fmt.Errorf("Dispatcher: Failed to start %s", err)
	}

	go w.start()

	return &w, nil
}

func (w *Dispatcher) start() {
	for {
		select {
		case _, ok := <-w.shutdownCh:
			if !ok {
				log.Printf("Shutting down dispatcher for %s", w.config.Name)
				w.wg.Done()
				return
			}
		case <-time.After(w.duration):
			w.task.Do(w)
		}
	}
}

func (w *Dispatcher) Work() {
	log.Printf("[INF]: Starting Update check for %s...", w.config.Name)

	u := w.config.Updater

	isOutOfDate, err := u.IsOutdated(w.config.Hash, w.config.Artifact)
	if err != nil {
		log.Printf("[ERR]: Unable to check updates for %s %v", w.config.Name, err)
		return
	}

	if isOutOfDate {
		if w.config.Sequential {
			log.Printf("[INF]: Acquiring lock for %s", w.config.Name)
			l := w.config.Locker
			if err != nil {
				log.Printf("[ERR]: Unable to retreive update lock. %v", err)
				return
			}
			_, err = l.Acquire(w.shutdownCh)
			if err != nil {
				log.Printf("[ERR]: Unable to retreive update lock. %v", err)
				return
			}
			defer l.Release()
		}

		log.Printf("[INF]: Downloading update for %s...", w.config.Name)
		fr, meta, err := u.Download(w.config.Artifact)
		if err != nil {
			log.Printf("[ERR]: Unable to download update for %s %v", w.config.Name, err)
			return
		}

		// Deprecated
		if w.config.PreCommand != "" {
			log.Printf("[WARN]: preCommand has been deprecated.")
			res, err := executeCommand(w.config.PreCommand)
			if err != nil {
				log.Printf("[ERR]: Unable to execute preCommand. %v", err)
			} else {
				log.Printf("[INF]: preCommand executed successfully. %v", res)
			}
		}

		err = runHooks(w.config.BeforeHooks, w.config)
		if err != nil {
			log.Printf("[ERR]: Unable to execute beforeHooks. %v", err)
		}

		contentType := meta.ContentType
		if ct, ok := w.config.Artifact["content-type"]; ok {
			contentType = ct
		}

		i, err := getInstaller(contentType)
		if err != nil {
			log.Printf("[ERR]: %s for %s", w.config.Name, err)
			return
		}

		filesWritten, err := i.Install(w.config.Artifact["destination"], fr)
		if err != nil {
			log.Printf("[ERR]: Unable to install update for %s %s", w.config.Name, err)
		}

		// Deprecated
		if w.config.PostCommand != "" {
			log.Printf("[WARN]: postCommand has been deprecated.")
			defer func() {
				res, err := executeCommand(w.config.PostCommand)
				if err != nil {
					log.Printf("[ERR]: Unable to execute postCommand. %v", err)
				} else {
					log.Printf("[INF]: postCommand executed successfully. %v", res)
				}
			}()
		}

		log.Printf("[INF]: Update for %s installed successfully. [hash: %s] [files written: %d]", w.config.Name, meta.Hash, filesWritten)
		// TODO(ChrisMcKenzie): hashes should be stored somewhere more
		// permanent.
		w.config.Hash = meta.Hash

		err = runHooks(w.config.AfterHooks, w.config)
		if err != nil {
			log.Printf("[ERR]: Unable to execute beforeHooks. %v", err)
		}

		if w.config.UpdateTTL != "" {
			log.Printf("[INF]: Waiting %s before releasing lock and allowing next deployment.", w.config.UpdateTTL)
			ttl, err := time.ParseDuration(w.config.UpdateTTL)
			if err != nil {
				log.Printf("[ERR]: Failed to parse updateTTL make sure it is a valid duration in seconds")
			}
			<-time.After(ttl)
		}
	} else {
		log.Printf("[INF]: %s is up to date", w.config.Name)
	}
}

// Deprecated
func executeCommand(c string) (string, error) {
	cmd := strings.Fields(c)
	out, err := exec.Command(cmd[0], cmd[1:]...).Output()
	return string(out), err
}

func getInstaller(contentType string) (dropship.Installer, error) {
	switch contentType {
	case "application/x-gzip", "application/octet-stream", "application/gzip":
		var installer dropship.TarInstaller
		return installer, nil
	default:
		var installer dropship.FileInstaller
		return installer, nil
	}

	return nil, errors.New("Unable to determine installation method from file type")
}

func runHooks(hooks []dropship.HookDefinition, service dropship.Config) error {
	for _, h := range hooks {
		for hookName, config := range h {
			hook := dropship.GetHookByName(hookName)
			if hook != nil {
				log.Printf("[INF]: Executing \"%s\" hook with %+v", hookName, config)
				err := hook.Execute(config, service)
				if err != nil {
					log.Printf("[ERR]: Unable to execute \"%s\" hook %v", hookName, err)
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package commands

import (
	"bufio"
	"os"
	"strings"

	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	prePushCmd = &cobra.Command{
		Use:   "pre-push",
		Short: "Implements the Git pre-push hook",
		Run:   prePushCommand,
	}
	prePushDryRun        = false
	prePushDeleteBranch  = "(delete)"
	prePushMissingErrMsg = "%s is an LFS pointer to %s, which does not exist in .git/lfs/objects.\n\nRun 'git lfs fsck' to verify Git LFS objects."
)

// prePushCommand is run through Git's pre-push hook. The pre-push hook passes
// two arguments on the command line:
//
//   1. Name of the remote to which the push is being done
//   2. URL to which the push is being done
//
// The hook receives commit information on stdin in the form:
//   <local ref> <local sha1> <remote ref> <remote sha1>
//
// In the typical case, prePushCommand will get a list of git objects being
// pushed by using the following:
//
//    git rev-list --objects <local sha1> ^<remote sha1>
//
// If any of those git objects are associated with Git LFS objects, those
// objects will be pushed to the Git LFS API.
//
// In the case of pushing a new branch, the list of git objects will be all of
// the git objects in this branch.
//
// In the case of deleting a branch, no attempts to push Git LFS objects will be
// made.
func prePushCommand(cmd *cobra.Command, args []string) {

	if len(args) == 0 {
		Print("This should be run through Git's pre-push hook.  Run `git lfs update` to install it.")
		os.Exit(1)
	}

	lfs.Config.CurrentRemote = args[0]

	// We can be passed multiple lines of refs
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if len(line) == 0 {
			continue
		}

		left, right := decodeRefs(line)
		if left == prePushDeleteBranch {
			continue
		}

		prePushRef(left, right)

	}
}

func prePushRef(left, right string) {
	// Just use scanner here
	scanOpt := &lfs.ScanRefsOptions{ScanMode: lfs.ScanLeftToRemoteMode, RemoteName: lfs.Config.CurrentRemote}
	pointers, err := lfs.ScanRefs(left, right, scanOpt)
	if err != nil {
		Panic(err, "Error scanning for Git LFS files")
	}

	totalSize := int64(0)
	for _, p := range pointers {
		totalSize += p.Size
	}

	// Objects to skip because they're missing locally but on server
	var skipObjects map[string]struct{}

	if !prePushDryRun {
		// Do this as a pre-flight check since upload queue starts immediately
		skipObjects = prePushCheckForMissingObjects(pointers)
	}

	uploadQueue := lfs.NewUploadQueue(len(pointers), totalSize, prePushDryRun)

	for _, pointer := range pointers {
		if prePushDryRun {
			Print("push %s => %s", pointer.Oid, pointer.Name)
			continue
		}

		if _, skip := skipObjects[pointer.Oid]; skip {
			// object missing locally but on server, don't bother
			continue
		}

		u, err := lfs.NewUploadable(pointer.Oid, pointer.Name)
		if err != nil {
			if lfs.IsCleanPointerError(err) {
				Exit(prePushMissingErrMsg, pointer.Name, lfs.ErrorGetContext(err, "pointer").(*lfs.Pointer).Oid)
			} else if Debugging || lfs.IsFatalError(err) {
				Panic(err, err.Error())
			} else {
				Exit(err.Error())
			}
		}

		uploadQueue.Add(u)
	}

	if !prePushDryRun {
		uploadQueue.Wait()
		for _, err := range uploadQueue.Errors() {
			if Debugging || lfs.IsFatalError(err) {
				LoggedError(err, err.Error())
			} else {
				Error(err.Error())
			}
		}

		if len(uploadQueue.Errors()) > 0 {
			os.Exit(2)
		}
	}

}

func prePushCheckForMissingObjects(pointers []*lfs.WrappedPointer) (objectsOnServer map[string]struct{}) {
	var missingLocalObjects []*lfs.WrappedPointer
	var missingSize int64
	var skipObjects = make(map[string]struct{}, len(pointers))
	for _, pointer := range pointers {
		if !lfs.ObjectExistsOfSize(pointer.Oid, pointer.Size) {
			// We think we need to push this but we don't have it
			// Store for server checking later
			missingLocalObjects = append(missingLocalObjects, pointer)
			missingSize += pointer.Size
		}
	}
	if len(missingLocalObjects) == 0 {
		return nil
	}

	checkQueue := lfs.NewDownloadCheckQueue(len(missingLocalObjects), missingSize, false)
	for _, p := range missingLocalObjects {
		checkQueue.Add(lfs.NewDownloadCheckable(p))
	}
	// this channel is filled with oids for which Check() succeeded & Transfer() was called
	transferc := checkQueue.Watch()
	done := make(chan int)
	go func() {
		for oid := range transferc {
			skipObjects[oid] = struct{}{}
		}
		done <- 1
	}()
	// Currently this is needed to flush the batch but is not enough to sync transferc completely
	checkQueue.Wait()
	<-done
	return skipObjects
}

// decodeRefs pulls the sha1s out of the line read from the pre-push
// hook's stdin.
func decodeRefs(input string) (string, string) {
	refs := strings.Split(strings.TrimSpace(input), " ")
	var left, right string

	if len(refs) > 1 {
		left = refs[1]
	}

	if len(refs) > 3 {
		right = "^" + refs[3]
	}

	return left, right
}

func init() {
	prePushCmd.Flags().BoolVarP(&prePushDryRun, "dry-run", "d", false, "Do everything except actually send the updates")
	RootCmd.AddCommand(prePushCmd)
}
<commit_msg>hide the download check queue.<commit_after>package commands

import (
	"bufio"
	"os"
	"strings"

	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	prePushCmd = &cobra.Command{
		Use:   "pre-push",
		Short: "Implements the Git pre-push hook",
		Run:   prePushCommand,
	}
	prePushDryRun        = false
	prePushDeleteBranch  = "(delete)"
	prePushMissingErrMsg = "%s is an LFS pointer to %s, which does not exist in .git/lfs/objects.\n\nRun 'git lfs fsck' to verify Git LFS objects."
)

// prePushCommand is run through Git's pre-push hook. The pre-push hook passes
// two arguments on the command line:
//
//   1. Name of the remote to which the push is being done
//   2. URL to which the push is being done
//
// The hook receives commit information on stdin in the form:
//   <local ref> <local sha1> <remote ref> <remote sha1>
//
// In the typical case, prePushCommand will get a list of git objects being
// pushed by using the following:
//
//    git rev-list --objects <local sha1> ^<remote sha1>
//
// If any of those git objects are associated with Git LFS objects, those
// objects will be pushed to the Git LFS API.
//
// In the case of pushing a new branch, the list of git objects will be all of
// the git objects in this branch.
//
// In the case of deleting a branch, no attempts to push Git LFS objects will be
// made.
func prePushCommand(cmd *cobra.Command, args []string) {

	if len(args) == 0 {
		Print("This should be run through Git's pre-push hook.  Run `git lfs update` to install it.")
		os.Exit(1)
	}

	lfs.Config.CurrentRemote = args[0]

	// We can be passed multiple lines of refs
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		if len(line) == 0 {
			continue
		}

		left, right := decodeRefs(line)
		if left == prePushDeleteBranch {
			continue
		}

		prePushRef(left, right)

	}
}

func prePushRef(left, right string) {
	// Just use scanner here
	scanOpt := &lfs.ScanRefsOptions{ScanMode: lfs.ScanLeftToRemoteMode, RemoteName: lfs.Config.CurrentRemote}
	pointers, err := lfs.ScanRefs(left, right, scanOpt)
	if err != nil {
		Panic(err, "Error scanning for Git LFS files")
	}

	totalSize := int64(0)
	for _, p := range pointers {
		totalSize += p.Size
	}

	// Objects to skip because they're missing locally but on server
	var skipObjects map[string]struct{}

	if !prePushDryRun {
		// Do this as a pre-flight check since upload queue starts immediately
		skipObjects = prePushCheckForMissingObjects(pointers)
	}

	uploadQueue := lfs.NewUploadQueue(len(pointers), totalSize, prePushDryRun)

	for _, pointer := range pointers {
		if prePushDryRun {
			Print("push %s => %s", pointer.Oid, pointer.Name)
			continue
		}

		if _, skip := skipObjects[pointer.Oid]; skip {
			// object missing locally but on server, don't bother
			continue
		}

		u, err := lfs.NewUploadable(pointer.Oid, pointer.Name)
		if err != nil {
			if lfs.IsCleanPointerError(err) {
				Exit(prePushMissingErrMsg, pointer.Name, lfs.ErrorGetContext(err, "pointer").(*lfs.Pointer).Oid)
			} else if Debugging || lfs.IsFatalError(err) {
				Panic(err, err.Error())
			} else {
				Exit(err.Error())
			}
		}

		uploadQueue.Add(u)
	}

	if !prePushDryRun {
		uploadQueue.Wait()
		for _, err := range uploadQueue.Errors() {
			if Debugging || lfs.IsFatalError(err) {
				LoggedError(err, err.Error())
			} else {
				Error(err.Error())
			}
		}

		if len(uploadQueue.Errors()) > 0 {
			os.Exit(2)
		}
	}

}

func prePushCheckForMissingObjects(pointers []*lfs.WrappedPointer) (objectsOnServer map[string]struct{}) {
	var missingLocalObjects []*lfs.WrappedPointer
	var missingSize int64
	var skipObjects = make(map[string]struct{}, len(pointers))
	for _, pointer := range pointers {
		if !lfs.ObjectExistsOfSize(pointer.Oid, pointer.Size) {
			// We think we need to push this but we don't have it
			// Store for server checking later
			missingLocalObjects = append(missingLocalObjects, pointer)
			missingSize += pointer.Size
		}
	}
	if len(missingLocalObjects) == 0 {
		return nil
	}

	checkQueue := lfs.NewDownloadCheckQueue(len(missingLocalObjects), missingSize, true)
	for _, p := range missingLocalObjects {
		checkQueue.Add(lfs.NewDownloadCheckable(p))
	}
	// this channel is filled with oids for which Check() succeeded & Transfer() was called
	transferc := checkQueue.Watch()
	done := make(chan int)
	go func() {
		for oid := range transferc {
			skipObjects[oid] = struct{}{}
		}
		done <- 1
	}()
	// Currently this is needed to flush the batch but is not enough to sync transferc completely
	checkQueue.Wait()
	<-done
	return skipObjects
}

// decodeRefs pulls the sha1s out of the line read from the pre-push
// hook's stdin.
func decodeRefs(input string) (string, string) {
	refs := strings.Split(strings.TrimSpace(input), " ")
	var left, right string

	if len(refs) > 1 {
		left = refs[1]
	}

	if len(refs) > 3 {
		right = "^" + refs[3]
	}

	return left, right
}

func init() {
	prePushCmd.Flags().BoolVarP(&prePushDryRun, "dry-run", "d", false, "Do everything except actually send the updates")
	RootCmd.AddCommand(prePushCmd)
}
<|endoftext|>


<commit_before>package mackerel

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestFindDashboards(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/api/v0/dashboards" {
			t.Error("request URL should be /api/v0/dashboards but: ", req.URL.Path)
		}

		respJSON, _ := json.Marshal(map[string][]map[string]interface{}{
			"dashboards": {
				{
					"id":           "2c5bLca8d",
					"title":        "My Dashboard(Legacy)",
					"bodyMarkDown": "# A test Legacy dashboard",
					"urlPath":      "2u4PP3TJqbu",
					"createdAt":    1439346145003,
					"updatedAt":    1439346145003,
					"isLegacy":     true,
				},
				{
					"id":        "2c5bLca8e",
					"title":     "My Custom Dashboard(Current)",
					"urlPath":   "2u4PP3TJqbv",
					"createdAt": 1552909732,
					"updatedAt": 1552992837,
					"memo":      "A test Current Dashboard",
				},
			},
		})
		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)
	dashboards, err := client.FindDashboards()

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboards[0].ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboards[0])
	}

	if dashboards[0].Title != "My Dashboard(Legacy)" {
		t.Error("request sends json including title but: ", dashboards[0])
	}

	if dashboards[0].BodyMarkDown != "# A test Legacy dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboards[0])
	}

	if dashboards[0].URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboards[0])
	}

	if dashboards[0].CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboards[0])
	}

	if dashboards[0].UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboards[0])
	}

	if dashboards[0].IsLegacy != true {
		t.Error("request sends json including IsLegacy but: ", dashboards[0])
	}
}

func TestFindDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		respJSON, _ := json.Marshal(
			map[string]interface{}{
				"id":           "2c5bLca8d",
				"title":        "My Dashboard",
				"bodyMarkDown": "# A test dashboard",
				"urlPath":      "2u4PP3TJqbu",
				"createdAt":    1439346145003,
				"updatedAt":    1439346145003,
			},
		)

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)
	dashboard, err := client.FindDashboard(testID)

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestCreateDashboard(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/api/v0/dashboards" {
			t.Error("request URL should be /api/v0/dashboards but: ", req.URL.Path)
		}

		if req.Method != "POST" {
			t.Error("request method should be POST but: ", req.Method)
		}

		body, _ := ioutil.ReadAll(req.Body)

		var data struct {
			ID           string `json:"id"`
			Title        string `json:"title"`
			BodyMarkDown string `json:"bodyMarkdown"`
			URLPath      string `json:"urlPath"`
			CreatedAt    int64  `json:"createdAt"`
			UpdatedAt    int64  `json:"updatedAt"`
		}

		err := json.Unmarshal(body, &data)
		if err != nil {
			t.Fatal("request body should be decoded as json", string(body))
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.CreateDashboard(&Dashboard{
		Title:        "My Dashboard",
		BodyMarkDown: "# A test dashboard",
		URLPath:      "2u4PP3TJqbu",
	})

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestUpdateDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		if req.Method != "PUT" {
			t.Error("request method should be PUT but: ", req.Method)
		}

		body, _ := ioutil.ReadAll(req.Body)

		var data struct {
			ID           string `json:"id"`
			Title        string `json:"title"`
			BodyMarkDown string `json:"bodyMarkdown"`
			URLPath      string `json:"urlPath"`
			CreatedAt    int64  `json:"createdAt"`
			UpdatedAt    int64  `json:"updatedAt"`
		}

		err := json.Unmarshal(body, &data)
		if err != nil {
			t.Fatal("request body should be decoded as json", string(body))
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.UpdateDashboard(testID, &Dashboard{
		Title:        "My Dashboard",
		BodyMarkDown: "# A test dashboard",
		URLPath:      "2u4PP3TJqbu",
	})

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestDeleteDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		if req.Method != "DELETE" {
			t.Error("request method should be DELETE but: ", req.Method)
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.DeleteDashboard(testID)

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}
<commit_msg>add new dashboards test<commit_after>package mackerel

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestFindDashboards(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/api/v0/dashboards" {
			t.Error("request URL should be /api/v0/dashboards but: ", req.URL.Path)
		}

		respJSON, _ := json.Marshal(map[string][]map[string]interface{}{
			"dashboards": {
				{
					"id":           "2c5bLca8d",
					"title":        "My Dashboard(Legacy)",
					"bodyMarkDown": "# A test Legacy dashboard",
					"urlPath":      "2u4PP3TJqbu",
					"createdAt":    1439346145003,
					"updatedAt":    1439346145003,
					"isLegacy":     true,
				},
				{
					"id":        "2c5bLca8e",
					"title":     "My Custom Dashboard(Current)",
					"urlPath":   "2u4PP3TJqbv",
					"createdAt": 1552909732,
					"updatedAt": 1552992837,
					"memo":      "A test Current Dashboard",
				},
			},
		})
		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)
	dashboards, err := client.FindDashboards()

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboards[0].ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboards[0])
	}

	if dashboards[0].Title != "My Dashboard(Legacy)" {
		t.Error("request sends json including title but: ", dashboards[0])
	}

	if dashboards[0].BodyMarkDown != "# A test Legacy dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboards[0])
	}

	if dashboards[0].URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboards[0])
	}

	if dashboards[0].CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboards[0])
	}

	if dashboards[0].UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboards[0])
	}

	if dashboards[0].IsLegacy != true {
		t.Error("request sends json including isLegacy but: ", dashboards[0])
	}

	if dashboards[1].Memo != "A test Current Dashboard" {
		t.Error("request sends json including memo but: ", dashboards[1])
	}
}

func TestFindDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		respJSON, _ := json.Marshal(
			map[string]interface{}{
				"id":           "2c5bLca8d",
				"title":        "My Dashboard",
				"bodyMarkDown": "# A test dashboard",
				"urlPath":      "2u4PP3TJqbu",
				"createdAt":    1439346145003,
				"updatedAt":    1439346145003,
			},
		)

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)
	dashboard, err := client.FindDashboard(testID)

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestCreateDashboard(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/api/v0/dashboards" {
			t.Error("request URL should be /api/v0/dashboards but: ", req.URL.Path)
		}

		if req.Method != "POST" {
			t.Error("request method should be POST but: ", req.Method)
		}

		body, _ := ioutil.ReadAll(req.Body)

		var data struct {
			ID           string `json:"id"`
			Title        string `json:"title"`
			BodyMarkDown string `json:"bodyMarkdown"`
			URLPath      string `json:"urlPath"`
			CreatedAt    int64  `json:"createdAt"`
			UpdatedAt    int64  `json:"updatedAt"`
		}

		err := json.Unmarshal(body, &data)
		if err != nil {
			t.Fatal("request body should be decoded as json", string(body))
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.CreateDashboard(&Dashboard{
		Title:        "My Dashboard",
		BodyMarkDown: "# A test dashboard",
		URLPath:      "2u4PP3TJqbu",
	})

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestUpdateDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		if req.Method != "PUT" {
			t.Error("request method should be PUT but: ", req.Method)
		}

		body, _ := ioutil.ReadAll(req.Body)

		var data struct {
			ID           string `json:"id"`
			Title        string `json:"title"`
			BodyMarkDown string `json:"bodyMarkdown"`
			URLPath      string `json:"urlPath"`
			CreatedAt    int64  `json:"createdAt"`
			UpdatedAt    int64  `json:"updatedAt"`
		}

		err := json.Unmarshal(body, &data)
		if err != nil {
			t.Fatal("request body should be decoded as json", string(body))
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.UpdateDashboard(testID, &Dashboard{
		Title:        "My Dashboard",
		BodyMarkDown: "# A test dashboard",
		URLPath:      "2u4PP3TJqbu",
	})

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}

func TestDeleteDashboard(t *testing.T) {

	testID := "2c5bLca8d"

	ts := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		if req.URL.Path != fmt.Sprintf("/api/v0/dashboards/%s", testID) {
			t.Error("request URL should be /api/v0/dashboards/<ID> but: ", req.URL.Path)
		}

		if req.Method != "DELETE" {
			t.Error("request method should be DELETE but: ", req.Method)
		}

		respJSON, _ := json.Marshal(map[string]interface{}{
			"id":           "2c5bLca8d",
			"title":        "My Dashboard",
			"bodyMarkDown": "# A test dashboard",
			"urlPath":      "2u4PP3TJqbu",
			"createdAt":    1439346145003,
			"updatedAt":    1439346145003,
		})

		res.Header()["Content-Type"] = []string{"application/json"}
		fmt.Fprint(res, string(respJSON))
	}))
	defer ts.Close()

	client, _ := NewClientWithOptions("dummy-key", ts.URL, false)

	dashboard, err := client.DeleteDashboard(testID)

	if err != nil {
		t.Error("err should be nil but: ", err)
	}

	if dashboard.ID != "2c5bLca8d" {
		t.Error("request sends json including id but: ", dashboard)
	}

	if dashboard.Title != "My Dashboard" {
		t.Error("request sends json including title but: ", dashboard)
	}

	if dashboard.BodyMarkDown != "# A test dashboard" {
		t.Error("request sends json including bodyMarkDown but: ", dashboard)
	}

	if dashboard.URLPath != "2u4PP3TJqbu" {
		t.Error("request sends json including urlpath but: ", dashboard)
	}

	if dashboard.CreatedAt != 1439346145003 {
		t.Error("request sends json including createdAt but: ", dashboard)
	}

	if dashboard.UpdatedAt != 1439346145003 {
		t.Error("request sends json including updatedAt but: ", dashboard)
	}
}
<|endoftext|>


<commit_before>// +build prod

package terago

/*
#cgo LDFLAGS: -ltera_c
#include "c/kvstore.h"
*/
import "C"
import (
	"errors"
	"fmt"
	"unsafe"
)

type KvStore struct {
	Name   string
	CTable *C.tera_table_t
}

func (p KvStore) Close() {
	fmt.Println("close table: " + p.Name)
	if p.CTable != nil {
		C.tera_table_close(p.CTable)
	}
}

// ttl(time-to-live)
// Key-value will expired after <ttl> seconds. -1 means never expired.
func (p KvStore) Put(key, value string, ttl int) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	ret := C.table_put_kv_sync(p.CTable, C.CString(key), C.int(len(key)),
		C.CString(value), C.int(len(value)), C.int(ttl))
	if !ret {
		err = errors.New("put kv error")
	}
	return
}

// Async put key-value into tera. Return success immediately and run put operation at background.
// Caution: If put failed, specify kv would be dump to error log.
func (p KvStore) PutAsync(key, value string, ttl int) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	C.table_put_kv_async(p.CTable, C.CString(key), C.int(len(key)),
		C.CString(value), C.int(len(value)), C.int(ttl))
	return
}

func (p KvStore) Get(key string) (value string, err error) {
	if p.CTable == nil {
		err = errors.New("table not open: " + p.Name)
		return
	}
	var vallen C.int
	vc := C.table_get_kv_sync(p.CTable, C.CString(key), C.int(len(key)), (*C.int)(&vallen))
	if vallen >= 0 {
		value = C.GoStringN(vc, vallen)
		C.free(unsafe.Pointer(vc))
	} else {
		err = errors.New("key not found")
		value = ""
	}
	return
}

func (p KvStore) BatchPut(kvs []KeyValue) (err error) {
	return nil
}

func (p KvStore) BatchGet(keys []string) (result []KeyValue, err error) {
	return
}

func (p KvStore) RangeGet(start, end string, maxNum int) (result []KeyValue, err error) {
	return
}

func (p KvStore) Delete(key string) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	ret := C.table_delete_kv_sync(p.CTable, C.CString(key), C.int(len(key)))
	if !ret {
		err = errors.New("put kv error")
	}
	return
}
<commit_msg>support BatchGet and BatchPut<commit_after>// +build prod

package terago

/*
#cgo LDFLAGS: -ltera_c
#include "c/kvstore.h"
*/
import "C"
import (
	"errors"
	"fmt"
	"sync"
	"unsafe"
)

type KvStore struct {
	Name   string
	CTable *C.tera_table_t
}

func (p KvStore) Close() {
	fmt.Println("close table: " + p.Name)
	if p.CTable != nil {
		C.tera_table_close(p.CTable)
	}
}

// ttl(time-to-live)
// Key-value will expired after <ttl> seconds. -1 means never expired.
func (p KvStore) Put(key, value string, ttl int) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	ret := C.table_put_kv_sync(p.CTable, C.CString(key), C.int(len(key)),
		C.CString(value), C.int(len(value)), C.int(ttl))
	if !ret {
		err = errors.New("put kv error")
	}
	return
}

// Async put key-value into tera. Return success immediately and run put operation at background.
// Caution: If put failed, specify kv would be dump to error log.
func (p KvStore) PutAsync(key, value string, ttl int) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	C.table_put_kv_async(p.CTable, C.CString(key), C.int(len(key)),
		C.CString(value), C.int(len(value)), C.int(ttl))
	return
}

func (p KvStore) Get(key string) (value string, err error) {
	if p.CTable == nil {
		err = errors.New("table not open: " + p.Name)
		return
	}
	var vallen C.int
	vc := C.table_get_kv_sync(p.CTable, C.CString(key), C.int(len(key)), (*C.int)(&vallen))
	if vallen >= 0 {
		value = C.GoStringN(vc, vallen)
		C.free(unsafe.Pointer(vc))
	} else {
		err = errors.New("key not found")
		value = ""
	}
	return
}

func (p KvStore) BatchPut(kvs []KeyValue) (err error) {
	wg := sync.WaitGroup{}
	wg.Add(len(kvs))
	succ := true
	for _, kvt := range kvs {
		kv := kvt
		go func() {
			if kv.TTL == 0 {
				kv.TTL = -1
			}
			kv.Err = p.Put(kv.Key, kv.Value, kv.TTL)
			if kv.Err != nil {
				succ = false
			}
			fmt.Printf("BatchPut: put %s successfully\n", kv.Key)
			wg.Done()
		}()
	}
	wg.Wait()
	if succ {
		return nil
	} else {
		return errors.New("error")
	}
}

func (p KvStore) BatchGet(keys []string) (result []KeyValue, err error) {
	wg := sync.WaitGroup{}
	wg.Add(len(keys))
	succ := true
	c := make(chan *KeyValue, len(keys))
	for _, kt := range keys {
		k := kt
		go func() {
			value, e := p.Get(k)
			if err != nil {
				c <- &KeyValue{Key: k, Err: e}
				succ = false
			} else {
				c <- &KeyValue{Key: k, Value: value}
			}
			fmt.Printf("BatchGet: get %s successfully\n", k)
			wg.Done()
		}()
	}
	wg.Wait()
	close(c)
	m := make(map[string]*KeyValue)
	for kv := range c {
		m[kv.Key] = kv
	}
	if len(m) != len(keys) {
		panic(m)
	}
	for _, k := range keys {
		result = append(result, *m[k])
	}
	if succ {
		return result, nil
	} else {
		return result, errors.New("error")
	}
	return
}

func (p KvStore) RangeGet(start, end string, maxNum int) (result []KeyValue, err error) {
	return
}

func (p KvStore) Delete(key string) (err error) {
	if p.CTable == nil {
		return errors.New("table not open: " + p.Name)
	}
	ret := C.table_delete_kv_sync(p.CTable, C.CString(key), C.int(len(key)))
	if !ret {
		err = errors.New("put kv error")
	}
	return
}
<|endoftext|>


<commit_before>/* https://leetcode.com/problems/merge-k-sorted-lists/#/description
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
*/

package leetcode

func mergeKLists(lists []*ListNode) *ListNode {
	return lists[0]
}
<commit_msg>add mergeKLists<commit_after>/* https://leetcode.com/problems/merge-k-sorted-lists/#/description
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
*/

package leetcode

import "math"

func mergeKLists(lists []*ListNode) *ListNode {
	var (
		res, tmp      *ListNode
		minIndex, min int
	)

	for cur := res; ; lists[minIndex] = lists[minIndex].Next {
		minIndex, min = -1, math.MaxInt32
		for i, list := range lists {
			if list != nil && list.Val < min {
				min = list.Val
				minIndex = i
			}
		}

		if minIndex == -1 {
			break
		}

		tmp = &ListNode{Val: min}
		if res == nil {
			res = tmp
		} else {
			cur.Next = tmp
		}
		cur = tmp
	}
	return res
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/boltdb/bolt"
	"github.com/gin-gonic/gin"
	"github.com/golang/glog"
	"github.com/joakim666/wip_alerts/auth"
	"github.com/joakim666/wip_alerts/model"
)

type NewRenewalDTO struct {
	RefreshToken string `json:"refresh_token" binding:"required"`
	DeviceType   string `json:"device_type" binding:"required"`
	DeviceInfo   string `json:"device_info" binding:"required"` // json as a string TODO validate that it's proper json
}

type RenewalDTO struct {
	ID             string    `json:"id"`               // uuid
	AccountID      string    `json:"account_id"`       // account uuid
	RefreshTokenID string    `json:"refresh_token_id"` // uuid of refresh token
	CreatedAt      time.Time `json:"created_at"`
}

func ListRenewals(db *bolt.DB) gin.HandlerFunc {
	glog.Infof("listRenewals")

	var renewalDTOs []RenewalDTO

	return func(c *gin.Context) {
		accounts, err := model.ListAccounts(db)
		if err != nil {
			glog.Errorf("ListRenewals failed: %s", err)
			c.Status(500)
		} else {
			for _, v := range *accounts {
				renewals, err := model.ListRenewals(db, v.ID)
				if err != nil {
					glog.Errorf("Failed to get renewals for account %s: %s", v.ID, err)
				} else {
					dtos := makeRenewalDTOs(db, v.ID, renewals)
					renewalDTOs = append(renewalDTOs, *dtos...)
				}
			}

			c.JSON(200, renewalDTOs)
		}
	}
}

func PostRenewals(db *bolt.DB, privateKey interface{}) gin.HandlerFunc {
	return func(c *gin.Context) {
		var json NewRenewalDTO

		if c.BindJSON(&json) == nil {
			token, err := auth.DecryptRefreshToken(json.RefreshToken, privateKey)
			if err != nil {
				glog.Errorf("Failed to decrypt refresh token: %s", err)
				c.Status(500)
				return
			}

			renewal := model.NewRenewal()
			renewal.RefreshTokenID = token.ID

			// get existing renewals
			renewals, err := model.ListRenewals(db, token.AccountID)
			if err != nil {
				glog.Errorf("Failed to get renewals: %s", err)
				c.Status(500)
				return
			}

			// add new renewal
			(*renewals)[renewal.ID] = *renewal

			// save the renewals
			err a= model.SaveRenewals(db, token.ID, renewals)
			if err != nil {
				glog.Errorf("Failed to save renewal in db: %s", err)
				c.Status(500)
				return
			}

			c.JSON(201, gin.H{
				"renewal_id": renewal.ID,
			})
		}
	}
}

func makeRenewalDTOs(db *bolt.DB, accountId string, renewals *map[string]model.Renewal) *[]RenewalDTO {
	glog.Infof("makeRenewalDTOs. Size=%d", len(*renewals))
	dtos := make([]RenewalDTO, 0)

	if len(*renewals) > 0 {
		for _, v := range *renewals {
			dtos = append(dtos, makeRenewalDTO(accountId, v))
		}
	} else {
	}

	return &dtos
}

func makeRenewalDTO(accountId string, renewal model.Renewal) RenewalDTO { // TODO pointers?
	glog.Infof("makeRenewalDTO")
	var dto RenewalDTO

	dto.ID = renewal.ID
	dto.AccountID = accountId
	dto.RefreshTokenID = "TODO"
	dto.CreatedAt = renewal.CreatedAt

	return dto
}
<commit_msg>Fixed typo<commit_after>package main

import (
	"time"

	"github.com/boltdb/bolt"
	"github.com/gin-gonic/gin"
	"github.com/golang/glog"
	"github.com/joakim666/wip_alerts/auth"
	"github.com/joakim666/wip_alerts/model"
)

type NewRenewalDTO struct {
	RefreshToken string `json:"refresh_token" binding:"required"`
	DeviceType   string `json:"device_type" binding:"required"`
	DeviceInfo   string `json:"device_info" binding:"required"` // json as a string TODO validate that it's proper json
}

type RenewalDTO struct {
	ID             string    `json:"id"`               // uuid
	AccountID      string    `json:"account_id"`       // account uuid
	RefreshTokenID string    `json:"refresh_token_id"` // uuid of refresh token
	CreatedAt      time.Time `json:"created_at"`
}

func ListRenewals(db *bolt.DB) gin.HandlerFunc {
	glog.Infof("listRenewals")

	var renewalDTOs []RenewalDTO

	return func(c *gin.Context) {
		accounts, err := model.ListAccounts(db)
		if err != nil {
			glog.Errorf("ListRenewals failed: %s", err)
			c.Status(500)
		} else {
			for _, v := range *accounts {
				renewals, err := model.ListRenewals(db, v.ID)
				if err != nil {
					glog.Errorf("Failed to get renewals for account %s: %s", v.ID, err)
				} else {
					dtos := makeRenewalDTOs(db, v.ID, renewals)
					renewalDTOs = append(renewalDTOs, *dtos...)
				}
			}

			c.JSON(200, renewalDTOs)
		}
	}
}

func PostRenewals(db *bolt.DB, privateKey interface{}) gin.HandlerFunc {
	return func(c *gin.Context) {
		var json NewRenewalDTO

		if c.BindJSON(&json) == nil {
			token, err := auth.DecryptRefreshToken(json.RefreshToken, privateKey)
			if err != nil {
				glog.Errorf("Failed to decrypt refresh token: %s", err)
				c.Status(500)
				return
			}

			renewal := model.NewRenewal()
			renewal.RefreshTokenID = token.ID

			// get existing renewals
			renewals, err := model.ListRenewals(db, token.AccountID)
			if err != nil {
				glog.Errorf("Failed to get renewals: %s", err)
				c.Status(500)
				return
			}

			// add new renewal
			(*renewals)[renewal.ID] = *renewal

			// save the renewals
			err = model.SaveRenewals(db, token.ID, renewals)
			if err != nil {
				glog.Errorf("Failed to save renewal in db: %s", err)
				c.Status(500)
				return
			}

			c.JSON(201, gin.H{
				"renewal_id": renewal.ID,
			})
		}
	}
}

func makeRenewalDTOs(db *bolt.DB, accountId string, renewals *map[string]model.Renewal) *[]RenewalDTO {
	glog.Infof("makeRenewalDTOs. Size=%d", len(*renewals))
	dtos := make([]RenewalDTO, 0)

	if len(*renewals) > 0 {
		for _, v := range *renewals {
			dtos = append(dtos, makeRenewalDTO(accountId, v))
		}
	} else {
	}

	return &dtos
}

func makeRenewalDTO(accountId string, renewal model.Renewal) RenewalDTO { // TODO pointers?
	glog.Infof("makeRenewalDTO")
	var dto RenewalDTO

	dto.ID = renewal.ID
	dto.AccountID = accountId
	dto.RefreshTokenID = "TODO"
	dto.CreatedAt = renewal.CreatedAt

	return dto
}
<|endoftext|>


<commit_before>package reporting

// TODO: get this under unit test.

import (
	"bytes"
	"encoding/json"
	"github.com/smartystreets/goconvey/printing"
	"strconv"
	"strings"
)

func (self *jsonReporter) BeginStory(story *StoryReport) {}

func (self *jsonReporter) Enter(scope *ScopeReport) {
	if _, found := self.titlesById[scope.ID]; !found {
		self.registerScope(scope)
	}
	self.depth++
}
func (self *jsonReporter) registerScope(scope *ScopeReport) {
	self.titlesById[scope.ID] = scope.ID
	next := newScopeResult(scope.Title, self.depth, scope.File, scope.Line)
	self.scopes = append(self.scopes, next)
	self.stack = append(self.stack, next)
}

func (self *jsonReporter) Report(report *AssertionReport) {
	current := self.stack[len(self.stack)-1]
	current.Assertions = append(current.Assertions, newAssertionResult(report))
}

func (self *jsonReporter) Exit() {
	self.depth--
	if len(self.stack) > 0 {
		self.stack = self.stack[:len(self.stack)-1]
	}
}

func (self *jsonReporter) EndStory() {
	self.report()
	self.reset()
}
func (self *jsonReporter) report() {
	self.out.Print(OpenJson + "\n")
	scopes := []string{}
	for _, scope := range self.scopes {
		serialized, err := json.Marshal(scope)
		if err != nil {
			self.out.Println(jsonMarshalFailure)
			panic(err)
		}
		var buffer bytes.Buffer
		json.Indent(&buffer, serialized, "", "  ")
		scopes = append(scopes, buffer.String())
	}
	self.out.Print(strings.Join(scopes, ",") + ",\n")
	self.out.Print(CloseJson + "\n")
}
func (self *jsonReporter) reset() {
	self.titlesById = make(map[string]string)
	self.scopes = []*ScopeResult{}
	self.stack = []*ScopeResult{}
	self.depth = 0
}

func NewJsonReporter(out *printing.Printer) *jsonReporter {
	self := &jsonReporter{}
	self.out = out
	self.reset()
	return self
}

type jsonReporter struct {
	out        *printing.Printer
	titlesById map[string]string
	scopes     []*ScopeResult
	stack      []*ScopeResult
	depth      int
}

type ScopeResult struct {
	Title      string
	File       string
	Line       int
	Depth      int
	Assertions []AssertionResult
}

func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
	self := &ScopeResult{}
	self.Title = title
	self.Depth = depth
	self.File = file
	self.Line = line
	self.Assertions = []AssertionResult{}
	return self
}

type AssertionResult struct {
	File       string
	Line       int
	Failure    string
	Error      interface{}
	Skipped    bool
	StackTrace string
}

func newAssertionResult(report *AssertionReport) AssertionResult {
	self := AssertionResult{}
	self.File = report.File
	self.Line = report.Line
	quotedFailure := strconv.Quote(report.Failure)
	if quotedFailure != report.Failure {
		// TODO: test
		self.Failure = quotedFailure + " (NOTE: GoConvey used strconv.Quote on the assertion failure string so it could be safely parsed.)"
	}
	self.Error = report.Error
	self.StackTrace = report.stackTrace
	self.Skipped = report.Skipped
	return self
}

const OpenJson = ">>>>>"  // "⌦"
const CloseJson = "<<<<<" // "⌫"
const jsonMarshalFailure = `

There was an error when attempting to convert test results to JSON.
Please file a bug report and reference the code that caused this failure if possible.

Here's the panic:

`
<commit_msg>Correct mishandling of quoted ("<value") result from strconv.Quote.<commit_after>package reporting

// TODO: get this under unit test.

import (
	"bytes"
	"encoding/json"
	"github.com/smartystreets/goconvey/printing"
	"strconv"
	"strings"
)

func (self *jsonReporter) BeginStory(story *StoryReport) {}

func (self *jsonReporter) Enter(scope *ScopeReport) {
	if _, found := self.titlesById[scope.ID]; !found {
		self.registerScope(scope)
	}
	self.depth++
}
func (self *jsonReporter) registerScope(scope *ScopeReport) {
	self.titlesById[scope.ID] = scope.ID
	next := newScopeResult(scope.Title, self.depth, scope.File, scope.Line)
	self.scopes = append(self.scopes, next)
	self.stack = append(self.stack, next)
}

func (self *jsonReporter) Report(report *AssertionReport) {
	current := self.stack[len(self.stack)-1]
	current.Assertions = append(current.Assertions, newAssertionResult(report))
}

func (self *jsonReporter) Exit() {
	self.depth--
	if len(self.stack) > 0 {
		self.stack = self.stack[:len(self.stack)-1]
	}
}

func (self *jsonReporter) EndStory() {
	self.report()
	self.reset()
}
func (self *jsonReporter) report() {
	self.out.Print(OpenJson + "\n")
	scopes := []string{}
	for _, scope := range self.scopes {
		serialized, err := json.Marshal(scope)
		if err != nil {
			self.out.Println(jsonMarshalFailure)
			panic(err)
		}
		var buffer bytes.Buffer
		json.Indent(&buffer, serialized, "", "  ")
		scopes = append(scopes, buffer.String())
	}
	self.out.Print(strings.Join(scopes, ",") + ",\n")
	self.out.Print(CloseJson + "\n")
}
func (self *jsonReporter) reset() {
	self.titlesById = make(map[string]string)
	self.scopes = []*ScopeResult{}
	self.stack = []*ScopeResult{}
	self.depth = 0
}

func NewJsonReporter(out *printing.Printer) *jsonReporter {
	self := &jsonReporter{}
	self.out = out
	self.reset()
	return self
}

type jsonReporter struct {
	out        *printing.Printer
	titlesById map[string]string
	scopes     []*ScopeResult
	stack      []*ScopeResult
	depth      int
}

type ScopeResult struct {
	Title      string
	File       string
	Line       int
	Depth      int
	Assertions []AssertionResult
}

func newScopeResult(title string, depth int, file string, line int) *ScopeResult {
	self := &ScopeResult{}
	self.Title = title
	self.Depth = depth
	self.File = file
	self.Line = line
	self.Assertions = []AssertionResult{}
	return self
}

type AssertionResult struct {
	File       string
	Line       int
	Failure    string
	Error      interface{}
	Skipped    bool
	StackTrace string
}

func newAssertionResult(report *AssertionReport) AssertionResult {
	self := AssertionResult{}
	self.File = report.File
	self.Line = report.Line
	quotedFailure := strconv.Quote(report.Failure)
	if quotedFailure[1:len(quotedFailure)-1] != report.Failure {
		// TODO: test
		self.Failure = quotedFailure + " (NOTE: GoConvey used strconv.Quote on the assertion failure string so it could be safely parsed.)"
	}
	self.Error = report.Error
	self.StackTrace = report.stackTrace
	self.Skipped = report.Skipped
	return self
}

const OpenJson = ">>>>>"  // "⌦"
const CloseJson = "<<<<<" // "⌫"
const jsonMarshalFailure = `

There was an error when attempting to convert test results to JSON.
Please file a bug report and reference the code that caused this failure if possible.

Here's the panic:

`
<|endoftext|>