<commit_before>/*
Copyright IBM Corp. 2016 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 committer

import (
	"sync/atomic"
	"testing"

	"github.com/hyperledger/fabric/common/configtx/test"
	"github.com/hyperledger/fabric/common/ledger/testutil"
	"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
	"github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
	"github.com/hyperledger/fabric/common/util"
	ledger2 "github.com/hyperledger/fabric/core/ledger"
	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
	"github.com/hyperledger/fabric/protos/common"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
)

func TestKVLedgerBlockStorage(t *testing.T) {
	viper.Set("peer.fileSystemPath", "/tmp/fabric/committertest")
	ledgermgmt.InitializeTestEnv()
	defer ledgermgmt.CleanupTestEnv()
	gb, _ := test.MakeGenesisBlock("TestLedger")
	gbHash := gb.Header.Hash()
	ledger, err := ledgermgmt.CreateLedger(gb)
	assert.NoError(t, err, "Error while creating ledger: %s", err)
	defer ledger.Close()

	committer := NewLedgerCommitter(ledger)
	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

	bcInfo, _ := ledger.GetBlockchainInfo()
	testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{
		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil})

	txid := util.GenerateUUID()
	simulator, _ := ledger.NewTxSimulator(txid)
	simulator.SetState("ns1", "key1", []byte("value1"))
	simulator.SetState("ns1", "key2", []byte("value2"))
	simulator.SetState("ns1", "key3", []byte("value3"))
	simulator.Done()

	simRes, _ := simulator.GetTxSimulationResults()
	simResBytes, _ := simRes.GetPubSimulationBytes()
	block1 := testutil.ConstructBlock(t, 1, gbHash, [][]byte{simResBytes}, true)

	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block1,
	})
	assert.NoError(t, err)

	height, err = committer.LedgerHeight()
	assert.Equal(t, uint64(2), height)
	assert.NoError(t, err)

	blocks := committer.GetBlocks([]uint64{0})
	assert.Equal(t, 1, len(blocks))
	assert.NoError(t, err)

	bcInfo, _ = ledger.GetBlockchainInfo()
	block1Hash := block1.Header.Hash()
	testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{
		Height: 2, CurrentBlockHash: block1Hash, PreviousBlockHash: gbHash})
}

func TestNewLedgerCommitterReactive(t *testing.T) {
	viper.Set("peer.fileSystemPath", "/tmp/fabric/committertest")
	chainID := "TestLedger"

	ledgermgmt.InitializeTestEnv()
	defer ledgermgmt.CleanupTestEnv()
	gb, _ := test.MakeGenesisBlock(chainID)

	ledger, err := ledgermgmt.CreateLedger(gb)
	assert.NoError(t, err, "Error while creating ledger: %s", err)
	defer ledger.Close()

	var configArrived int32
	committer := NewLedgerCommitterReactive(ledger, func(_ *common.Block) error {
		atomic.AddInt32(&configArrived, 1)
		return nil
	})

	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

	profile := localconfig.Load(localconfig.SampleSingleMSPSoloProfile)
	block := encoder.New(profile).GenesisBlockForChannel(chainID)

	committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block,
	})
	assert.Equal(t, int32(1), atomic.LoadInt32(&configArrived))
}
<commit_msg>[FAB-8361]: Remove ledger dep. for committer UT<commit_after>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package committer

import (
	"errors"
	"sync/atomic"
	"testing"

	"github.com/hyperledger/fabric/common/configtx/test"
	"github.com/hyperledger/fabric/common/ledger"
	"github.com/hyperledger/fabric/common/ledger/testutil"
	"github.com/hyperledger/fabric/common/tools/configtxgen/encoder"
	"github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
	ledger2 "github.com/hyperledger/fabric/core/ledger"
	"github.com/hyperledger/fabric/protos/common"
	"github.com/hyperledger/fabric/protos/peer"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
)

type mockLedger struct {
	height       uint64
	currentHash  []byte
	previousHash []byte
	mock.Mock
}

func (m *mockLedger) GetBlockchainInfo() (*common.BlockchainInfo, error) {
	info := &common.BlockchainInfo{
		Height:            m.height,
		CurrentBlockHash:  m.currentHash,
		PreviousBlockHash: m.previousHash,
	}
	return info, nil
}

func (m *mockLedger) GetBlockByNumber(blockNumber uint64) (*common.Block, error) {
	args := m.Called(blockNumber)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetBlocksIterator(startBlockNumber uint64) (ledger.ResultsIterator, error) {
	args := m.Called(startBlockNumber)
	return args.Get(0).(ledger.ResultsIterator), args.Error(1)
}

func (m *mockLedger) Close() {

}

func (m *mockLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) {
	args := m.Called(txID)
	return args.Get(0).(*peer.ProcessedTransaction), args.Error(1)
}

func (m *mockLedger) GetBlockByHash(blockHash []byte) (*common.Block, error) {
	args := m.Called(blockHash)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetBlockByTxID(txID string) (*common.Block, error) {
	args := m.Called(txID)
	return args.Get(0).(*common.Block), args.Error(1)
}

func (m *mockLedger) GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
	args := m.Called(txID)
	return args.Get(0).(peer.TxValidationCode), args.Error(1)
}

func (m *mockLedger) NewTxSimulator(txid string) (ledger2.TxSimulator, error) {
	args := m.Called(txid)
	return args.Get(0).(ledger2.TxSimulator), args.Error(1)
}

func (m *mockLedger) NewQueryExecutor() (ledger2.QueryExecutor, error) {
	args := m.Called()
	return args.Get(0).(ledger2.QueryExecutor), args.Error(1)
}

func (m *mockLedger) NewHistoryQueryExecutor() (ledger2.HistoryQueryExecutor, error) {
	args := m.Called()
	return args.Get(0).(ledger2.HistoryQueryExecutor), args.Error(1)
}

func (m *mockLedger) GetPvtDataAndBlockByNum(blockNum uint64, filter ledger2.PvtNsCollFilter) (*ledger2.BlockAndPvtData, error) {
	args := m.Called(blockNum, filter)
	return args.Get(0).(*ledger2.BlockAndPvtData), args.Error(1)
}

func (m *mockLedger) GetPvtDataByNum(blockNum uint64, filter ledger2.PvtNsCollFilter) ([]*ledger2.TxPvtData, error) {
	args := m.Called(blockNum, filter)
	return args.Get(0).([]*ledger2.TxPvtData), args.Error(1)
}

func (m *mockLedger) CommitWithPvtData(blockAndPvtdata *ledger2.BlockAndPvtData) error {
	m.height += 1
	m.previousHash = m.currentHash
	m.currentHash = blockAndPvtdata.Block.Header.DataHash
	args := m.Called(blockAndPvtdata)
	return args.Error(0)
}

func (m *mockLedger) PurgePrivateData(maxBlockNumToRetain uint64) error {
	args := m.Called(maxBlockNumToRetain)
	return args.Error(0)
}

func (m *mockLedger) PrivateDataMinBlockNum() (uint64, error) {
	args := m.Called()
	return args.Get(0).(uint64), args.Error(1)
}

func (m *mockLedger) Prune(policy ledger.PrunePolicy) error {
	args := m.Called(policy)
	return args.Error(0)
}

func createLedger(channelID string) (*common.Block, *mockLedger) {
	gb, _ := test.MakeGenesisBlock(channelID)
	ledger := &mockLedger{
		height:       1,
		previousHash: []byte{},
		currentHash:  gb.Header.DataHash,
	}
	return gb, ledger
}

func TestKVLedgerBlockStorage(t *testing.T) {
	t.Parallel()
	gb, ledger := createLedger("TestLedger")
	block1 := testutil.ConstructBlock(t, 1, gb.Header.DataHash, [][]byte{{1, 2, 3, 4}, {5, 6, 7, 8}}, true)

	ledger.On("CommitWithPvtData", mock.Anything).Run(func(args mock.Arguments) {
		b := args.Get(0).(*ledger2.BlockAndPvtData)
		assert.Equal(t, uint64(1), b.Block.Header.GetNumber())
		assert.Equal(t, gb.Header.DataHash, b.Block.Header.PreviousHash)
		assert.Equal(t, block1.Header.DataHash, b.Block.Header.DataHash)
	}).Return(nil)

	ledger.On("GetBlockByNumber", uint64(0)).Return(gb, nil)

	committer := NewLedgerCommitter(ledger)
	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block1,
	})
	assert.NoError(t, err)

	height, err = committer.LedgerHeight()
	assert.Equal(t, uint64(2), height)
	assert.NoError(t, err)

	blocks := committer.GetBlocks([]uint64{0})
	assert.Equal(t, 1, len(blocks))
	assert.NoError(t, err)
}

func TestNewLedgerCommitterReactive(t *testing.T) {
	t.Parallel()
	chainID := "TestLedger"
	_, ledger := createLedger(chainID)
	ledger.On("CommitWithPvtData", mock.Anything).Return(nil)
	var configArrived int32
	committer := NewLedgerCommitterReactive(ledger, func(_ *common.Block) error {
		atomic.AddInt32(&configArrived, 1)
		return nil
	})

	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

	profile := localconfig.Load(localconfig.SampleSingleMSPSoloProfile)
	block := encoder.New(profile).GenesisBlockForChannel(chainID)

	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block,
	})
	assert.NoError(t, err)
	assert.Equal(t, int32(1), atomic.LoadInt32(&configArrived))
}

func TestNewLedgerCommitterReactiveFailedConfigUpdate(t *testing.T) {
	t.Parallel()
	chainID := "TestLedger"
	_, ledger := createLedger(chainID)
	ledger.On("CommitWithPvtData", mock.Anything).Return(nil)
	var configArrived int32
	committer := NewLedgerCommitterReactive(ledger, func(_ *common.Block) error {
		return errors.New("failed update config")
	})

	height, err := committer.LedgerHeight()
	assert.Equal(t, uint64(1), height)
	assert.NoError(t, err)

	profile := localconfig.Load(localconfig.SampleSingleMSPSoloProfile)
	block := encoder.New(profile).GenesisBlockForChannel(chainID)

	err = committer.CommitWithPvtData(&ledger2.BlockAndPvtData{
		Block: block,
	})

	assert.Error(t, err)
	assert.Equal(t, int32(0), atomic.LoadInt32(&configArrived))
}
<|endoftext|>


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

// +build linux
// +build power64 power64le

package syscall

//sys	Chown(path string, uid int, gid int) (err error)
//sys	Fchown(fd int, uid int, gid int) (err error)
//sys	Fstat(fd int, stat *Stat_t) (err error)
//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
//sys	Ftruncate(fd int, length int64) (err error)
//sysnb	Getegid() (egid int)
//sysnb	Geteuid() (euid int)
//sysnb	Getgid() (gid int)
//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT
//sysnb	Getuid() (uid int)
//sys	Ioperm(from int, num int, on int) (err error)
//sys	Iopl(level int) (err error)
//sys	Lchown(path string, uid int, gid int) (err error)
//sys	Listen(s int, n int) (err error)
//sys	Lstat(path string, stat *Stat_t) (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys	Setfsgid(gid int) (err error)
//sys	Setfsuid(uid int) (err error)
//sysnb	Setregid(rgid int, egid int) (err error)
//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb	Setreuid(ruid int, euid int) (err error)
//sys	Shutdown(fd int, how int) (err error)
//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys	Stat(path string, stat *Stat_t) (err error)
//sys	Statfs(path string, buf *Statfs_t) (err error)
//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE2
//sys	Truncate(path string, length int64) (err error)
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb	setgroups(n int, list *_Gid_t) (err error)
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)

func Getpagesize() int { return 4096 }

//sysnb	Gettimeofday(tv *Timeval) (err error)
//sysnb	Time(t *Time_t) (tt Time_t, err error)

func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }

func NsecToTimespec(nsec int64) (ts Timespec) {
	ts.Sec = nsec / 1e9
	ts.Nsec = nsec % 1e9
	return
}

func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }

func NsecToTimeval(nsec int64) (tv Timeval) {
	nsec += 999 // round up to microsecond
	tv.Sec = nsec / 1e9
	tv.Usec = nsec % 1e9 / 1e3
	return
}

func (r *PtraceRegs) PC() uint64 { return r.Nip }

func (r *PtraceRegs) SetPC(pc uint64) { r.Nip = pc }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint64(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint64(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint64(length)
}
<commit_msg>[dev.power64] syscall: fix power64 page size<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux
// +build power64 power64le

package syscall

//sys	Chown(path string, uid int, gid int) (err error)
//sys	Fchown(fd int, uid int, gid int) (err error)
//sys	Fstat(fd int, stat *Stat_t) (err error)
//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
//sys	Ftruncate(fd int, length int64) (err error)
//sysnb	Getegid() (egid int)
//sysnb	Geteuid() (euid int)
//sysnb	Getgid() (gid int)
//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT
//sysnb	Getuid() (uid int)
//sys	Ioperm(from int, num int, on int) (err error)
//sys	Iopl(level int) (err error)
//sys	Lchown(path string, uid int, gid int) (err error)
//sys	Listen(s int, n int) (err error)
//sys	Lstat(path string, stat *Stat_t) (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys	Setfsgid(gid int) (err error)
//sys	Setfsuid(uid int) (err error)
//sysnb	Setregid(rgid int, egid int) (err error)
//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb	Setreuid(ruid int, euid int) (err error)
//sys	Shutdown(fd int, how int) (err error)
//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys	Stat(path string, stat *Stat_t) (err error)
//sys	Statfs(path string, buf *Statfs_t) (err error)
//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE2
//sys	Truncate(path string, length int64) (err error)
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb	setgroups(n int, list *_Gid_t) (err error)
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)

func Getpagesize() int { return 65536 }

//sysnb	Gettimeofday(tv *Timeval) (err error)
//sysnb	Time(t *Time_t) (tt Time_t, err error)

func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }

func NsecToTimespec(nsec int64) (ts Timespec) {
	ts.Sec = nsec / 1e9
	ts.Nsec = nsec % 1e9
	return
}

func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }

func NsecToTimeval(nsec int64) (tv Timeval) {
	nsec += 999 // round up to microsecond
	tv.Sec = nsec / 1e9
	tv.Usec = nsec % 1e9 / 1e3
	return
}

func (r *PtraceRegs) PC() uint64 { return r.Nip }

func (r *PtraceRegs) SetPC(pc uint64) { r.Nip = pc }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint64(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint64(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint64(length)
}
<|endoftext|>


<commit_before>package handlers

import (
	"strconv"

	log "github.com/Sirupsen/logrus"
	"github.com/jrzimmerman/bestrida-server-go/models"
	strava "github.com/strava/go.strava"
	"gopkg.in/gin-gonic/gin.v1"
)

// GetAthleteByIDFromStrava returns the strava athlete with the specified ID
func GetAthleteByIDFromStrava(c *gin.Context) {
	id := c.Param("id")

	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete info...\n")
	athlete, err := strava.NewCurrentAthleteService(client).Get().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete info")
		return
	}

	c.JSON(200, athlete)
}

// GetFriendsByUserIDFromStrava returns a list of friends for a specific user by ID from strava
func GetFriendsByUserIDFromStrava(c *gin.Context) {
	id := c.Param("id")

	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete friends info...\n")
	friends, err := strava.NewCurrentAthleteService(client).ListFriends().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete friends")
		return
	}

	c.JSON(200, friends)
}

// GetSegmentsByUserIDFromStrava returns a list of segments for a specific user by ID from strava
func GetSegmentsByUserIDFromStrava(c *gin.Context) {
	id := c.Param("id")
	var segments []*strava.SegmentDetailed

	// convert id string to number
	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	// find user by numID to retrieve strava token
	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	// create new strava client with user token
	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete activity summary info...\n")
	activities, err := strava.NewCurrentAthleteService(client).ListActivities().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete activities summary")
		return
	}

	// range over activity summary to get activity details
	// the activity summary does not have segment efforts to view recent segments
	for _, activitySummary := range activities {
		log.WithFields(map[string]interface{}{
			"NAME": activitySummary.Name,
			"ID":   activitySummary.Id,
		}).Info("activity summary")

		// request activity detail from strava to obtain segments
		activityDetail, err := strava.NewActivitiesService(client).Get(activitySummary.Id).Do()
		if err != nil {
			log.WithFields(map[string]interface{}{
				"NAME": activityDetail.Name,
				"ID":   activityDetail.Id,
			}).Error("unable to retrieve activity detail")
			c.JSON(500, map[string]interface{}{
				"error":    "Unable to retrieve activity detail",
				"activity": activityDetail,
			})
			return
		}

		// range over segment efforts from the activity detail
		// to obtain segment details to cache
		for _, effort := range activityDetail.SegmentEfforts {
			log.WithField("SEGMENT", effort.Name).Info("segment effort from activity detail")
			segmentDetail, err := strava.NewSegmentsService(client).Get(effort.Segment.Id).Do()
			if err != nil {
				log.WithFields(map[string]interface{}{
					"NAME": effort.Name,
					"ID":   effort.Id,
				}).Error("unable to retrieve activity detail")
				c.JSON(500, map[string]interface{}{
					"error":   "Unable to retrieve activity detail",
					"segment": effort,
				})
				return
			}
			log.WithField("SEGMENT DETAIL", segmentDetail).Info("retrieved segment detail from strava")
			segments = append(segments, segmentDetail)
		}
	}
	c.JSON(200, segments)
}
<commit_msg>add comments<commit_after>package handlers

import (
	"strconv"

	log "github.com/Sirupsen/logrus"
	"github.com/jrzimmerman/bestrida-server-go/models"
	strava "github.com/strava/go.strava"
	"gopkg.in/gin-gonic/gin.v1"
)

// GetAthleteByIDFromStrava returns the strava athlete with the specified ID
func GetAthleteByIDFromStrava(c *gin.Context) {
	id := c.Param("id")

	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete info...\n")
	// retrieve a list of users segments from Strava API
	athlete, err := strava.NewCurrentAthleteService(client).Get().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete info")
		return
	}

	c.JSON(200, athlete)
}

// GetFriendsByUserIDFromStrava returns a list of friends for a specific user by ID from strava
func GetFriendsByUserIDFromStrava(c *gin.Context) {
	id := c.Param("id")

	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete friends info...\n")
	// retrieve a list of users friends from Strava API
	friends, err := strava.NewCurrentAthleteService(client).ListFriends().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete friends")
		return
	}

	c.JSON(200, friends)
}

// GetSegmentsByUserIDFromStrava returns a list of segments for a specific user by ID from strava
func GetSegmentsByUserIDFromStrava(c *gin.Context) {
	id := c.Param("id")
	var segments []*strava.SegmentDetailed

	// convert id string to number
	numID, err := strconv.Atoi(id)
	if err != nil {
		log.WithField("ID", numID).Error("unable to convert ID param")
		c.JSON(500, "unable to convert ID param")
		return
	}

	// find user by numID to retrieve strava token
	user, err := models.GetUserByID(numID)
	if err != nil {
		log.WithField("ID", numID).Error("unable to retrieve user from database")
		c.JSON(500, "unable to retrieve user from database")
		return
	}

	// create new strava client with user token
	client := strava.NewClient(user.Token)

	log.Info("Fetching athlete activity summary info...\n")
	activities, err := strava.NewCurrentAthleteService(client).ListActivities().Do()
	if err != nil {
		c.JSON(500, "Unable to retrieve athlete activities summary")
		return
	}

	// range over activity summary to get activity details
	// the activity summary does not have segment efforts to view recent segments
	for _, activitySummary := range activities {
		log.WithFields(map[string]interface{}{
			"NAME": activitySummary.Name,
			"ID":   activitySummary.Id,
		}).Info("activity summary")

		// request activity detail from strava to obtain segments
		activityDetail, err := strava.NewActivitiesService(client).Get(activitySummary.Id).Do()
		if err != nil {
			log.WithFields(map[string]interface{}{
				"NAME": activityDetail.Name,
				"ID":   activityDetail.Id,
			}).Error("unable to retrieve activity detail")
			c.JSON(500, map[string]interface{}{
				"error":    "Unable to retrieve activity detail",
				"activity": activityDetail,
			})
			return
		}

		// range over segment efforts from the activity detail
		// to obtain segment details to cache
		for _, effort := range activityDetail.SegmentEfforts {
			log.WithField("SEGMENT", effort.Name).Info("segment effort from activity detail")
			segmentDetail, err := strava.NewSegmentsService(client).Get(effort.Segment.Id).Do()
			if err != nil {
				log.WithFields(map[string]interface{}{
					"NAME": effort.Name,
					"ID":   effort.Id,
				}).Error("unable to retrieve activity detail")
				c.JSON(500, map[string]interface{}{
					"error":   "Unable to retrieve activity detail",
					"segment": effort,
				})
				return
			}
			log.WithField("SEGMENT DETAIL", segmentDetail).Info("retrieved segment detail from strava")
			segments = append(segments, segmentDetail)
		}
	}
	c.JSON(200, segments)
}
<|endoftext|>


<commit_before>//go:generate protoc api.proto --go_out=.
package handlers

import (
	"compress/gzip"
	"crypto/rsa"
	"database/sql"
	"io"
	"log"
	"net/http"
	"strings"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"

	"pixur.org/pixur/status"
)

type registerFunc func(mux *http.ServeMux, c *ServerConfig)

var (
	handlerFuncs []registerFunc
)

type ServerConfig struct {
	DB          *sql.DB
	PixPath     string
	TokenSecret []byte
	PrivateKey  *rsa.PrivateKey
	PublicKey   *rsa.PublicKey
}

func register(rf registerFunc) {
	handlerFuncs = append(handlerFuncs, rf)
}

func AddAllHandlers(mux *http.ServeMux, c *ServerConfig) {
	for _, rf := range handlerFuncs {
		rf(mux, c)
	}
}

func returnTaskError(w http.ResponseWriter, sts status.S) {
	log.Println("Error in task: ", sts)
	w.Header().Set("Content-Type", "text/plain")
	code := sts.Code()
	http.Error(w, code.String()+": "+sts.Message(), code.HttpStatus())
}

var protoJSONMarshaller = &jsonpb.Marshaler{}

func returnProtoJSON(w http.ResponseWriter, r *http.Request, pb proto.Message) {
	var writer io.Writer = w

	if encs := r.Header.Get("Accept-Encoding"); encs != "" {
		for _, enc := range strings.Split(encs, ",") {
			if strings.TrimSpace(enc) == "gzip" {
				if gw, err := gzip.NewWriterLevel(writer, gzip.BestSpeed); err != nil {
					panic(err)
				} else {
					defer gw.Close()
					// TODO: log this

					writer = gw
				}
				w.Header().Set("Content-Encoding", "gzip")
				break
			}
		}
	}

	w.Header().Set("Content-Type", "application/json")
	if err := protoJSONMarshaller.Marshal(writer, pb); err != nil {
		log.Println("Error writing JSON", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<commit_msg>handlers: add support for raw proto output<commit_after>//go:generate protoc api.proto --go_out=.
package handlers

import (
	"compress/gzip"
	"crypto/rsa"
	"database/sql"
	"io"
	"log"
	"net/http"
	"strings"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"

	"pixur.org/pixur/status"
)

type registerFunc func(mux *http.ServeMux, c *ServerConfig)

var (
	handlerFuncs []registerFunc
)

type ServerConfig struct {
	DB          *sql.DB
	PixPath     string
	TokenSecret []byte
	PrivateKey  *rsa.PrivateKey
	PublicKey   *rsa.PublicKey
}

func register(rf registerFunc) {
	handlerFuncs = append(handlerFuncs, rf)
}

func AddAllHandlers(mux *http.ServeMux, c *ServerConfig) {
	for _, rf := range handlerFuncs {
		rf(mux, c)
	}
}

func returnTaskError(w http.ResponseWriter, sts status.S) {
	log.Println("Error in task: ", sts)
	w.Header().Set("Content-Type", "text/plain")
	code := sts.Code()
	http.Error(w, code.String()+": "+sts.Message(), code.HttpStatus())
}

var protoJSONMarshaller = &jsonpb.Marshaler{}

func returnProtoJSON(w http.ResponseWriter, r *http.Request, pb proto.Message) {
	var writer io.Writer = w

	if encs := r.Header.Get("Accept-Encoding"); encs != "" {
		for _, enc := range strings.Split(encs, ",") {
			if strings.TrimSpace(enc) == "gzip" {
				if gw, err := gzip.NewWriterLevel(writer, gzip.BestSpeed); err != nil {
					panic(err)
				} else {
					defer gw.Close()
					// TODO: log this

					writer = gw
				}
				w.Header().Set("Content-Encoding", "gzip")
				break
			}
		}
	}
	if accept := r.Header.Get("Accept"); accept != "" {
		for _, acc := range strings.Split(accept, ",") {
			switch strings.TrimSpace(acc) {
			case "application/json":
				w.Header().Set("Content-Type", "application/json")
				if err := protoJSONMarshaller.Marshal(writer, pb); err != nil {
					log.Println("Error writing JSON", err)
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				return
			case "application/proto":
				w.Header().Set("Content-Type", "application/proto")
				raw, err := proto.Marshal(pb)
				if err != nil {
					log.Println("Error building Proto", err)
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				if _, err := writer.Write(raw); err != nil {
					log.Println("Error writing Proto", err)
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				return
			}
		}
	}
	// default
	w.Header().Set("Content-Type", "application/json")
	if err := protoJSONMarshaller.Marshal(writer, pb); err != nil {
		log.Println("Error writing JSON", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"

	"github.com/cloudfoundry-incubator/cf_http"
	"github.com/cloudfoundry-incubator/volman/delegate"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/rata"
)

var Routes = rata.Routes{
	{Path: "/v1/drivers", Method: "GET", Name: "drivers"},
}

func New(logger lager.Logger) (http.Handler, error) {

	var handlers = rata.Handlers{
		"drivers": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			client := delegate.NewLocalClient()
			drivers, _ := client.ListDrivers(logger)
			cf_http.WriteJSONResponse(w, http.StatusOK, drivers)
		}),
	}

	return rata.NewRouter(Routes, handlers)
}
<commit_msg>Adjusted for CF_HTTP Pull Request comments.<commit_after>package handlers

import (
	"net/http"

	cf_http_handlers "github.com/cloudfoundry-incubator/cf_http/handlers"
	"github.com/cloudfoundry-incubator/volman/delegate"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/rata"
)

var Routes = rata.Routes{
	{Path: "/v1/drivers", Method: "GET", Name: "drivers"},
}

func New(logger lager.Logger) (http.Handler, error) {

	var handlers = rata.Handlers{
		"drivers": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			client := delegate.NewLocalClient()
			drivers, _ := client.ListDrivers(logger)
			cf_http_handlers.WriteJSONResponse(w, http.StatusOK, drivers)
		}),
	}

	return rata.NewRouter(Routes, handlers)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/flosch/pongo2"
	"github.com/gorilla/mux"
	"github.com/sendgrid/sendgrid-go/helpers/mail"
	"net/http"
)

func (app *Application) SubmissionsCreateHandler(w http.ResponseWriter, r *http.Request) {
	uuid := mux.Vars(r)["uuid"]
	r.ParseForm()

	form, err := NewFormsRepository(app.db).FindByUuid(uuid)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	json, err := json.MarshalIndent(r.Form, "", " ")
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	_, err = NewSubmissionsRepository(app.db).Create(form.id, string(json))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// TODO Send email
	user, _ := NewUsersRepository(app.db).FindById(form.userId)

	plainTextTemplate := `
Plaintext New Form Submission

{{ json }}
	`

	htmlTemplate := `

New Form Submission

{{ json }}

	`

	c := pongo2.Context{
		"json": string(json),
	}

	htmlContent, _ := pongo2.FromString(htmlTemplate)
	plainTextContent, _ := pongo2.FromString(plainTextTemplate)

	plainText, _ := plainTextContent.Execute(c)
	html, _ := htmlContent.Execute(c)

	message := mail.NewSingleEmail(
		mail.NewEmail("Letterdrop Team", "team@letterdrop.herokuapp.com"),
		"New Form Submission",
		mail.NewEmail(user.name, user.email),
		plainText,
		html,
	)

	app.emailClient.Send(message)
	http.Redirect(w, r, "/", 302)
}
<commit_msg>Refactor SubmissionsCreateHandler<commit_after>package main

import (
	"encoding/json"
	"github.com/flosch/pongo2"
	"github.com/gorilla/mux"
	"github.com/sendgrid/sendgrid-go/helpers/mail"
	"net/http"
)

const (
	plainTextTemplate = `
Plaintext New Form Submission

{{ json }}`

	htmlTemplate = `

New Form Submission

{{ json }}
`
)

func (app *Application) SubmissionsCreateHandler(w http.ResponseWriter, r *http.Request) {
	uuid := mux.Vars(r)["uuid"]
	r.ParseForm()

	form, err := NewFormsRepository(app.db).FindByUuid(uuid)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	json, err := json.MarshalIndent(r.Form, "", " ")
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	_, err = NewSubmissionsRepository(app.db).Create(form.id, string(json))
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	err = app.SendNotification(form, json)
	http.Redirect(w, r, "/", 302)
}

func (app *Application) SendNotification(form *Form, json []byte) error {
	user, _ := NewUsersRepository(app.db).FindById(form.userId)

	c := pongo2.Context{
		"json": string(json),
	}

	htmlContent, _ := pongo2.FromString(htmlTemplate)
	html, _ := htmlContent.Execute(c)

	plainTextContent, _ := pongo2.FromString(plainTextTemplate)
	plainText, _ := plainTextContent.Execute(c)

	message := mail.NewSingleEmail(
		mail.NewEmail("Letterdrop Team", "team@letterdrop.herokuapp.com"),
		"New Form Submission",
		mail.NewEmail(user.name, user.email),
		plainText,
		html,
	)

	_, err := app.emailClient.Send(message)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/docker/docker/utils"
	"github.com/go-check/check"
)

// ensure docker info succeeds
func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
	out, _ := dockerCmd(c, "info")

	// always shown fields
	stringsToCheck := []string{
		"ID:",
		"Containers:",
		"Images:",
		"Execution Driver:",
		"Logging Driver:",
		"Operating System:",
		"CPUs:",
		"Total Memory:",
		"Kernel Version:",
		"Storage Driver:",
	}

	if utils.ExperimentalBuild() {
		stringsToCheck = append(stringsToCheck, "Experimental: true")
	}

	for _, linePrefix := range stringsToCheck {
		if !strings.Contains(out, linePrefix) {
			c.Errorf("couldn't find string %v in output", linePrefix)
		}
	}
}

// TestInfoDiscoveryBackend verifies that a daemon run with `--cluster-advertise` and
// `--cluster-store` properly show the backend's endpoint in info output.
func (s *DockerSuite) TestInfoDiscoveryBackend(c *check.C) {
	testRequires(c, SameHostDaemon)

	d := NewDaemon(c)
	discoveryBackend := "consul://consuladdr:consulport/some/path"
	if err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), "--cluster-advertise=foo"); err != nil {
		c.Fatal(err)
	}
	defer d.Stop()

	out, err := d.Cmd("info")
	c.Assert(err, checker.IsNil)
	c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: %s\n", discoveryBackend))
}
<commit_msg>Use of checkers on docker_cli_info_test.go.<commit_after>package main

import (
	"fmt"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/docker/docker/utils"
	"github.com/go-check/check"
)

// ensure docker info succeeds
func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
	out, _ := dockerCmd(c, "info")

	// always shown fields
	stringsToCheck := []string{
		"ID:",
		"Containers:",
		"Images:",
		"Execution Driver:",
		"Logging Driver:",
		"Operating System:",
		"CPUs:",
		"Total Memory:",
		"Kernel Version:",
		"Storage Driver:",
	}

	if utils.ExperimentalBuild() {
		stringsToCheck = append(stringsToCheck, "Experimental: true")
	}

	for _, linePrefix := range stringsToCheck {
		c.Assert(out, checker.Contains, linePrefix, check.Commentf("couldn't find string %v in output", linePrefix))
	}
}

// TestInfoDiscoveryBackend verifies that a daemon run with `--cluster-advertise` and
// `--cluster-store` properly show the backend's endpoint in info output.
func (s *DockerSuite) TestInfoDiscoveryBackend(c *check.C) {
	testRequires(c, SameHostDaemon)

	d := NewDaemon(c)
	discoveryBackend := "consul://consuladdr:consulport/some/path"
	err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend), "--cluster-advertise=foo")
	c.Assert(err, checker.IsNil)
	defer d.Stop()

	out, err := d.Cmd("info")
	c.Assert(err, checker.IsNil)
	c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: %s\n", discoveryBackend))
}
<|endoftext|>


<commit_before>package bcsgo

import (
	// "fmt"
	"testing"
	"time"
)

var bucketForSuperfileTest *Bucket

func TestSuperfileInit(t *testing.T) {
	bucket := createBucketTempForTest(t)
	bucketForSuperfileTest = bucket

	createTestFile(_TEST_NAME, 1*1024*1024)
}

func TestSuperfilePutAndDelete(t *testing.T) {
	DEBUG = true
	bucket := bucketForSuperfileTest
	// todo file name with blank char
	putFile := func(path, localFile string) *Object {
		testObj := bucket.Object(path)
		testObj, err := testObj.PutFile(localFile, ACL_PUBLIC_READ)
		if err != nil {
			t.Error(err)
		}
		if testObj.AbsolutePath != path {
			t.Error("testObj.AbsolutePath != path", testObj.AbsolutePath, path)
		}
		return testObj
	}
	deleteFile := func(testObj *Object) {
		deleteErr := testObj.Delete()
		if deleteErr != nil {
			t.Error(deleteErr)
		}
	}
	dupFileTimes := func(absPath string, obj *Object, times int) *Superfile {
		repeats := make([]*Object, 0)
		for i := 0; i < times; i++ {
			repeats = append(repeats, obj)
		}
		s := bucket.Superfile(absPath, repeats)
		err := s.Put()
		if err != nil {
			t.Error(err)
		}
		return s
	}
	obj := putFile("/testDir/test.txt", _TEST_NAME)
	// DEBUG_REQUEST_BODY = true
	s := dupFileTimes("/testDir/test.txt", obj, 1024)

	deleteFile(&s.Object)
}

func TestSuperfileFinalize(t *testing.T) {
	time.Sleep(time.Second)
	deleteBucketForTest(t, bucketForSuperfileTest)
	bucketForSuperfileTest = nil
	deleteTestFile(_TEST_NAME)
}
<commit_msg>DEBUG<commit_after>package bcsgo

import (
	// "fmt"
	"testing"
	"time"
)

var bucketForSuperfileTest *Bucket

func TestSuperfileInit(t *testing.T) {
	bucket := createBucketTempForTest(t)
	bucketForSuperfileTest = bucket

	createTestFile(_TEST_NAME, 1*1024*1024)
}

func TestSuperfilePutAndDelete(t *testing.T) {
	bucket := bucketForSuperfileTest
	// todo file name with blank char
	putFile := func(path, localFile string) *Object {
		testObj := bucket.Object(path)
		testObj, err := testObj.PutFile(localFile, ACL_PUBLIC_READ)
		if err != nil {
			t.Error(err)
		}
		if testObj.AbsolutePath != path {
			t.Error("testObj.AbsolutePath != path", testObj.AbsolutePath, path)
		}
		return testObj
	}
	deleteFile := func(testObj *Object) {
		deleteErr := testObj.Delete()
		if deleteErr != nil {
			t.Error(deleteErr)
		}
	}
	dupFileTimes := func(absPath string, obj *Object, times int) *Superfile {
		repeats := make([]*Object, 0)
		for i := 0; i < times; i++ {
			repeats = append(repeats, obj)
		}
		s := bucket.Superfile(absPath, repeats)
		err := s.Put()
		if err != nil {
			t.Error(err)
		}
		return s
	}
	obj := putFile("/testDir/test.txt", _TEST_NAME)
	// DEBUG_REQUEST_BODY = true
	s := dupFileTimes("/testDir/test.txt", obj, 1024)

	deleteFile(&s.Object)
}

func TestSuperfileFinalize(t *testing.T) {
	time.Sleep(time.Second)
	deleteBucketForTest(t, bucketForSuperfileTest)
	bucketForSuperfileTest = nil
	deleteTestFile(_TEST_NAME)
}
<|endoftext|>


<commit_before>package argon2_test

import (
	"testing"

	conv "github.com/pzduniak/argon2"
	bind "github.com/tvdburgt/go-argon2"
)

var (
	password = []byte("test123")
	salt     = []byte("test123456")
)

func BenchmarkBConversion(b *testing.B) {
	b.ReportAllocs()

	for n := 0; n < b.N; n++ {
		conv.Key(password, salt, 3, 4, 4096, 32, conv.Argon2i)
	}
}

func BenchmarkBBindings(b *testing.B) {
	b.ReportAllocs()

	for n := 0; n < b.N; n++ {
		bc := bind.Context{
			Iterations:  3,
			Parallelism: 4,
			Memory:      4096,
			HashLen:     32,
			Mode:        bind.ModeArgon2i,
		}
		bc.Hash(password, salt)
	}
}
<commit_msg>fix build error<commit_after>package argon2_test

import (
	"testing"

	conv "github.com/pzduniak/argon2"
	bind "github.com/tvdburgt/go-argon2"
)

var (
	password = []byte("test123")
	salt     = []byte("test123456")
)

func BenchmarkBConversion(b *testing.B) {
	b.ReportAllocs()

	for n := 0; n < b.N; n++ {
		conv.Key(password, salt, 3, 4, 4096, 32, conv.Argon2i)
	}
}

func BenchmarkBBindings(b *testing.B) {
	b.ReportAllocs()

	for n := 0; n < b.N; n++ {
		ctx := &bind.Context{
			Iterations:  3,
			Parallelism: 4,
			Memory:      4096,
			HashLen:     32,
			Mode:        bind.ModeArgon2i,
		}
		bind.Hash(ctx, password, salt)
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package wasm

import (
	"bytes"
	"context"
	"fmt"
	"sync"

	"github.com/open-policy-agent/opa/internal/wasm/sdk/opa/errors"
	"github.com/open-policy-agent/opa/metrics"
)

// Pool maintains a pool of WebAssemly VM instances.
type Pool struct {
	available      chan struct{}
	mutex          sync.Mutex
	dataMtx        sync.Mutex
	initialized    bool
	closed         bool
	policy         []byte
	parsedData     []byte // Parsed parsedData memory segment, used to seed new VM's
	parsedDataAddr int32  // Address for parsedData value root, used to seed new VM's
	memoryMinPages uint32
	memoryMaxPages uint32
	vms            []*VM // All current VM instances, acquired or not.
	acquired       []bool
	pendingReinit  *VM
	blockedReinit  chan struct{}
}

// NewPool constructs a new pool with the pool and VM configuration provided.
func NewPool(poolSize, memoryMinPages, memoryMaxPages uint32) *Pool {
	available := make(chan struct{}, poolSize)
	for i := uint32(0); i < poolSize; i++ {
		available <- struct{}{}
	}

	return &Pool{
		memoryMinPages: memoryMinPages,
		memoryMaxPages: memoryMaxPages,
		available:      available,
		vms:            make([]*VM, 0),
		acquired:       make([]bool, 0),
	}
}

// ParsedData returns a reference to the pools parsed external data used to
// initialize new VM's.
func (p *Pool) ParsedData() (int32, []byte) {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	return p.parsedDataAddr, p.parsedData
}

// Policy returns the raw policy Wasm module used by VM's in the pool
func (p *Pool) Policy() []byte {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	return p.policy
}

// Size returns the current number of VM's in the pool
func (p *Pool) Size() int {
	return len(p.vms)
}

// Acquire obtains a VM from the pool, waiting if all VMms are in use
// and building one as necessary. Returns either ErrNotReady or
// ErrInternal if an error.
func (p *Pool) Acquire(ctx context.Context, metrics metrics.Metrics) (*VM, error) {
	metrics.Timer("wasm_pool_acquire").Start()
	defer metrics.Timer("wasm_pool_acquire").Stop()

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-p.available:
	}

	p.mutex.Lock()
	defer p.mutex.Unlock()

	if !p.initialized || p.closed {
		return nil, errors.ErrNotReady
	}

	for i, vm := range p.vms {
		if !p.acquired[i] {
			p.acquired[i] = true
			return vm, nil
		}
	}

	policy, parsedData, parsedDataAddr := p.policy, p.parsedData, p.parsedDataAddr

	p.mutex.Unlock()
	vm, err := newVM(vmOpts{
		policy:         policy,
		data:           nil,
		parsedData:     parsedData,
		parsedDataAddr: parsedDataAddr,
		memoryMin:      p.memoryMinPages,
		memoryMax:      p.memoryMaxPages,
	})
	p.mutex.Lock()

	if err != nil {
		p.available <- struct{}{}
		return nil, fmt.Errorf("%v: %w", err, errors.ErrInternal)
	}

	p.acquired = append(p.acquired, true)
	p.vms = append(p.vms, vm)
	return vm, nil
}

// Release releases the VM back to the pool.
func (p *Pool) Release(vm *VM, metrics metrics.Metrics) {
	metrics.Timer("wasm_pool_release").Start()
	defer metrics.Timer("wasm_pool_release").Stop()

	p.mutex.Lock()

	// If the policy data setting is waiting for this one, don't release it back to the general consumption.
	// Note the reinit is responsible for pushing to available channel once done with the VM.
	if vm == p.pendingReinit {
		p.mutex.Unlock()
		p.blockedReinit <- struct{}{}
		return
	}

	for i := range p.vms {
		if p.vms[i] == vm {
			p.acquired[i] = false
			p.mutex.Unlock()
			p.available <- struct{}{}
			return
		}
	}

	// VM instance not found anymore, hence pool reconfigured and can release the VM.

	p.mutex.Unlock()
	p.available <- struct{}{}

	vm.Close()
}

// SetPolicyData re-initializes the vms within the pool with the new policy
// and data. The re-initialization takes place atomically: all new vms
// are constructed in advance before touching the pool.  Returns
// either ErrNotReady, ErrInvalidPolicy or ErrInternal if an error
// occurs.
func (p *Pool) SetPolicyData(policy []byte, data []byte) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	p.mutex.Lock()

	if !p.initialized {
		vm, err := newVM(vmOpts{
			policy:         policy,
			data:           data,
			parsedData:     nil,
			parsedDataAddr: 0,
			memoryMin:      p.memoryMinPages,
			memoryMax:      p.memoryMaxPages,
		})

		if err == nil {
			parsedDataAddr, parsedData := vm.cloneDataSegment()
			p.memoryMinPages = Pages(vm.memory.Length())
			p.vms = append(p.vms, vm)
			p.acquired = append(p.acquired, false)
			p.initialized = true
			p.policy, p.parsedData, p.parsedDataAddr = policy, parsedData, parsedDataAddr
		} else {
			err = fmt.Errorf("%v: %w", err, errors.ErrInvalidPolicyOrData)
		}

		p.mutex.Unlock()
		return err
	}

	if p.closed {
		p.mutex.Unlock()
		return errors.ErrNotReady
	}

	currentPolicy, currentData := p.policy, p.parsedData
	p.mutex.Unlock()

	if bytes.Equal(policy, currentPolicy) && bytes.Equal(data, currentData) {
		return nil

	}

	err := p.setPolicyData(policy, data)
	if err != nil {
		return fmt.Errorf("%v: %w", err, errors.ErrInternal)
	}

	return nil
}

// SetDataPath will update the current data on the VMs by setting the value at the
// specified path. If an error occurs the instance is still in a valid state, however
// the data will not have been modified.
func (p *Pool) SetDataPath(path []string, value interface{}) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	var patchedData []byte
	var patchedDataAddr int32
	var seedMemorySize uint32
	for i, activations := 0, 0; true; i++ {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		if err := vm.SetDataPath(path, value); err != nil {
			p.remove(i)
			p.Release(vm, metrics.New())
			if activations == 0 {
				return err
			}
		} else {
			// Before releasing our first succesfully patched VM get a
			// copy of its data memory segment to more quickly seed fresh
			// vm's.
			if patchedData == nil {
				patchedDataAddr, patchedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}
			p.Release(vm, metrics.New())
		}

		// Activate the policy and data, now that a single VM has been patched without errors.
		if activations == 0 {
			p.activate(p.policy, patchedData, patchedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// RemoveDataPath will update the current data on the VMs by removing the value at the
// specified path. If an error occurs the instance is still in a valid state, however
// the data will not have been modified.
func (p *Pool) RemoveDataPath(path []string) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	var patchedData []byte
	var patchedDataAddr int32
	var seedMemorySize uint32
	for i, activations := 0, 0; true; i++ {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		if err := vm.RemoveDataPath(path); err != nil {
			p.remove(i)
			p.Release(vm, metrics.New())
			if activations == 0 {
				return err
			}
		} else {
			// Before releasing our first succesfully patched VM get a
			// copy of its data memory segment to more quickly seed fresh
			// vm's.
			if patchedData == nil {
				patchedDataAddr, patchedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}
			p.Release(vm, metrics.New())
		}

		// Activate the policy and data, now that a single VM has been patched without errors.
		if activations == 0 {
			p.activate(p.policy, patchedData, patchedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// setPolicyData reinitializes the VMs one at a time.
func (p *Pool) setPolicyData(policy []byte, data []byte) error {
	var parsedData []byte
	var parsedDataAddr int32
	seedMemorySize := wasmPageSize * p.memoryMinPages
	for i, activations := 0, 0; true; i++ {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		err := vm.SetPolicyData(vmOpts{
			policy:         policy,
			data:           data,
			parsedData:     parsedData,
			parsedDataAddr: parsedDataAddr,
			memoryMin:      Pages(seedMemorySize),
			memoryMax:      p.memoryMaxPages,
		})

		if err != nil {
			// No guarantee about the VM state after an error; hence, remove.
			p.remove(i)
			p.Release(vm, metrics.New())

			// After the first successful activation, proceed through all the VMs, ignoring the remaining errors.
			if activations == 0 {
				return err
			}
		} else {
			if parsedData == nil {
				parsedDataAddr, parsedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}

			p.Release(vm, metrics.New())
		}

		// Activate the policy and data, now that a single VM has been reset without errors.

		if activations == 0 {
			p.activate(policy, parsedData, parsedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// Close waits for all the evaluations to finish and then releases the VMs.
func (p *Pool) Close() {
	for range p.vms {
		<-p.available
	}

	p.mutex.Lock()
	defer p.mutex.Unlock()

	for _, vm := range p.vms {
		if vm != nil {
			vm.Close()
		}
	}

	p.closed = true
	p.vms = nil
}

// Wait steals the i'th VM instance. The VM has to be released afterwards.
func (p *Pool) Wait(i int) *VM {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	if i == len(p.vms) {
		return nil
	}

	vm := p.vms[i]
	isActive := p.acquired[i]
	p.acquired[i] = true

	if isActive {
		p.blockedReinit = make(chan struct{}, 1)
		p.pendingReinit = vm
	}

	p.mutex.Unlock()

	if isActive {
		<-p.blockedReinit
	} else {
		<-p.available
	}

	p.mutex.Lock()
	p.pendingReinit = nil
	return vm
}

// remove removes the i'th vm.
func (p *Pool) remove(i int) {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	n := len(p.vms)
	if n > 1 {
		p.vms[i] = p.vms[n-1]
	}

	p.vms = p.vms[0 : n-1]
	p.acquired = p.acquired[0 : n-1]
}

func (p *Pool) activate(policy []byte, data []byte, dataAddr int32, minMemorySize uint32) {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	p.policy, p.parsedData, p.parsedDataAddr, p.memoryMinPages = policy, data, dataAddr, Pages(minMemorySize)
}
<commit_msg>internal/wasm/sdk: Correct vm update behavior on error<commit_after>// Copyright 2020 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package wasm

import (
	"bytes"
	"context"
	"fmt"
	"sync"

	"github.com/open-policy-agent/opa/internal/wasm/sdk/opa/errors"
	"github.com/open-policy-agent/opa/metrics"
)

// Pool maintains a pool of WebAssemly VM instances.
type Pool struct {
	available      chan struct{}
	mutex          sync.Mutex
	dataMtx        sync.Mutex
	initialized    bool
	closed         bool
	policy         []byte
	parsedData     []byte // Parsed parsedData memory segment, used to seed new VM's
	parsedDataAddr int32  // Address for parsedData value root, used to seed new VM's
	memoryMinPages uint32
	memoryMaxPages uint32
	vms            []*VM // All current VM instances, acquired or not.
	acquired       []bool
	pendingReinit  *VM
	blockedReinit  chan struct{}
}

// NewPool constructs a new pool with the pool and VM configuration provided.
func NewPool(poolSize, memoryMinPages, memoryMaxPages uint32) *Pool {
	available := make(chan struct{}, poolSize)
	for i := uint32(0); i < poolSize; i++ {
		available <- struct{}{}
	}

	return &Pool{
		memoryMinPages: memoryMinPages,
		memoryMaxPages: memoryMaxPages,
		available:      available,
		vms:            make([]*VM, 0),
		acquired:       make([]bool, 0),
	}
}

// ParsedData returns a reference to the pools parsed external data used to
// initialize new VM's.
func (p *Pool) ParsedData() (int32, []byte) {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	return p.parsedDataAddr, p.parsedData
}

// Policy returns the raw policy Wasm module used by VM's in the pool
func (p *Pool) Policy() []byte {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	return p.policy
}

// Size returns the current number of VM's in the pool
func (p *Pool) Size() int {
	return len(p.vms)
}

// Acquire obtains a VM from the pool, waiting if all VMms are in use
// and building one as necessary. Returns either ErrNotReady or
// ErrInternal if an error.
func (p *Pool) Acquire(ctx context.Context, metrics metrics.Metrics) (*VM, error) {
	metrics.Timer("wasm_pool_acquire").Start()
	defer metrics.Timer("wasm_pool_acquire").Stop()

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-p.available:
	}

	p.mutex.Lock()
	defer p.mutex.Unlock()

	if !p.initialized || p.closed {
		return nil, errors.ErrNotReady
	}

	for i, vm := range p.vms {
		if !p.acquired[i] {
			p.acquired[i] = true
			return vm, nil
		}
	}

	policy, parsedData, parsedDataAddr := p.policy, p.parsedData, p.parsedDataAddr

	p.mutex.Unlock()
	vm, err := newVM(vmOpts{
		policy:         policy,
		data:           nil,
		parsedData:     parsedData,
		parsedDataAddr: parsedDataAddr,
		memoryMin:      p.memoryMinPages,
		memoryMax:      p.memoryMaxPages,
	})
	p.mutex.Lock()

	if err != nil {
		p.available <- struct{}{}
		return nil, fmt.Errorf("%v: %w", err, errors.ErrInternal)
	}

	p.acquired = append(p.acquired, true)
	p.vms = append(p.vms, vm)
	return vm, nil
}

// Release releases the VM back to the pool.
func (p *Pool) Release(vm *VM, metrics metrics.Metrics) {
	metrics.Timer("wasm_pool_release").Start()
	defer metrics.Timer("wasm_pool_release").Stop()

	p.mutex.Lock()

	// If the policy data setting is waiting for this one, don't release it back to the general consumption.
	// Note the reinit is responsible for pushing to available channel once done with the VM.
	if vm == p.pendingReinit {
		p.mutex.Unlock()
		p.blockedReinit <- struct{}{}
		return
	}

	for i := range p.vms {
		if p.vms[i] == vm {
			p.acquired[i] = false
			p.mutex.Unlock()
			p.available <- struct{}{}
			return
		}
	}

	// VM instance not found anymore, hence pool reconfigured and can release the VM.

	p.mutex.Unlock()
	p.available <- struct{}{}

	vm.Close()
}

// SetPolicyData re-initializes the vms within the pool with the new policy
// and data. The re-initialization takes place atomically: all new vms
// are constructed in advance before touching the pool.  Returns
// either ErrNotReady, ErrInvalidPolicy or ErrInternal if an error
// occurs.
func (p *Pool) SetPolicyData(policy []byte, data []byte) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	p.mutex.Lock()

	if !p.initialized {
		vm, err := newVM(vmOpts{
			policy:         policy,
			data:           data,
			parsedData:     nil,
			parsedDataAddr: 0,
			memoryMin:      p.memoryMinPages,
			memoryMax:      p.memoryMaxPages,
		})

		if err == nil {
			parsedDataAddr, parsedData := vm.cloneDataSegment()
			p.memoryMinPages = Pages(vm.memory.Length())
			p.vms = append(p.vms, vm)
			p.acquired = append(p.acquired, false)
			p.initialized = true
			p.policy, p.parsedData, p.parsedDataAddr = policy, parsedData, parsedDataAddr
		} else {
			err = fmt.Errorf("%v: %w", err, errors.ErrInvalidPolicyOrData)
		}

		p.mutex.Unlock()
		return err
	}

	if p.closed {
		p.mutex.Unlock()
		return errors.ErrNotReady
	}

	currentPolicy, currentData := p.policy, p.parsedData
	p.mutex.Unlock()

	if bytes.Equal(policy, currentPolicy) && bytes.Equal(data, currentData) {
		return nil

	}

	err := p.setPolicyData(policy, data)
	if err != nil {
		return fmt.Errorf("%v: %w", err, errors.ErrInternal)
	}

	return nil
}

// SetDataPath will update the current data on the VMs by setting the value at the
// specified path. If an error occurs the instance is still in a valid state, however
// the data will not have been modified.
func (p *Pool) SetDataPath(path []string, value interface{}) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	var patchedData []byte
	var patchedDataAddr int32
	var seedMemorySize uint32
	for i, activations := 0, 0; true; {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		if err := vm.SetDataPath(path, value); err != nil {
			p.remove(i)
			p.Release(vm, metrics.New())
			if activations == 0 {
				return err
			}
			// Note: Do not increment i when it has been removed! That index is
			// replaced by the last VM in the list so we must re-run with the
			// same index.
		} else {
			// Before releasing our first succesfully patched VM get a
			// copy of its data memory segment to more quickly seed fresh
			// vm's.
			if patchedData == nil {
				patchedDataAddr, patchedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}
			p.Release(vm, metrics.New())

			// Only increment on success
			i++
		}

		// Activate the policy and data, now that a single VM has been patched without errors.
		if activations == 0 {
			p.activate(p.policy, patchedData, patchedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// RemoveDataPath will update the current data on the VMs by removing the value at the
// specified path. If an error occurs the instance is still in a valid state, however
// the data will not have been modified.
func (p *Pool) RemoveDataPath(path []string) error {
	p.dataMtx.Lock()
	defer p.dataMtx.Unlock()

	var patchedData []byte
	var patchedDataAddr int32
	var seedMemorySize uint32
	for i, activations := 0, 0; true; {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		if err := vm.RemoveDataPath(path); err != nil {
			p.remove(i)
			p.Release(vm, metrics.New())
			if activations == 0 {
				return err
			}
			// Note: Do not increment i when it has been removed! That index is
			// replaced by the last VM in the list so we must re-run with the
			// same index.
		} else {
			// Before releasing our first succesfully patched VM get a
			// copy of its data memory segment to more quickly seed fresh
			// vm's.
			if patchedData == nil {
				patchedDataAddr, patchedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}
			p.Release(vm, metrics.New())

			// Only increment on success
			i++
		}

		// Activate the policy and data, now that a single VM has been patched without errors.
		if activations == 0 {
			p.activate(p.policy, patchedData, patchedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// setPolicyData reinitializes the VMs one at a time.
func (p *Pool) setPolicyData(policy []byte, data []byte) error {
	var parsedData []byte
	var parsedDataAddr int32
	seedMemorySize := wasmPageSize * p.memoryMinPages
	for i, activations := 0, 0; true; {
		vm := p.Wait(i)
		if vm == nil {
			// All have been converted.
			return nil
		}

		err := vm.SetPolicyData(vmOpts{
			policy:         policy,
			data:           data,
			parsedData:     parsedData,
			parsedDataAddr: parsedDataAddr,
			memoryMin:      Pages(seedMemorySize),
			memoryMax:      p.memoryMaxPages,
		})

		if err != nil {
			// No guarantee about the VM state after an error; hence, remove.
			p.remove(i)
			p.Release(vm, metrics.New())

			// After the first successful activation, proceed through all the VMs, ignoring the remaining errors.
			if activations == 0 {
				return err
			}
			// Note: Do not increment i when it has been removed! That index is
			// replaced by the last VM in the list so we must re-run with the
			// same index.
		} else {
			if parsedData == nil {
				parsedDataAddr, parsedData = vm.cloneDataSegment()
				seedMemorySize = vm.memory.Length()
			}

			p.Release(vm, metrics.New())

			// Only increment on success
			i++
		}

		// Activate the policy and data, now that a single VM has been reset without errors.

		if activations == 0 {
			p.activate(policy, parsedData, parsedDataAddr, seedMemorySize)
		}

		activations++
	}

	return nil
}

// Close waits for all the evaluations to finish and then releases the VMs.
func (p *Pool) Close() {
	for range p.vms {
		<-p.available
	}

	p.mutex.Lock()
	defer p.mutex.Unlock()

	for _, vm := range p.vms {
		if vm != nil {
			vm.Close()
		}
	}

	p.closed = true
	p.vms = nil
}

// Wait steals the i'th VM instance. The VM has to be released afterwards.
func (p *Pool) Wait(i int) *VM {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	if i == len(p.vms) {
		return nil
	}

	vm := p.vms[i]
	isActive := p.acquired[i]
	p.acquired[i] = true

	if isActive {
		p.blockedReinit = make(chan struct{}, 1)
		p.pendingReinit = vm
	}

	p.mutex.Unlock()

	if isActive {
		<-p.blockedReinit
	} else {
		<-p.available
	}

	p.mutex.Lock()
	p.pendingReinit = nil
	return vm
}

// remove removes the i'th vm.
func (p *Pool) remove(i int) {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	n := len(p.vms)
	if n > 1 {
		p.vms[i] = p.vms[n-1]
		p.acquired[i] = p.acquired[n-1]
	}

	p.vms = p.vms[0 : n-1]
	p.acquired = p.acquired[0 : n-1]
}

func (p *Pool) activate(policy []byte, data []byte, dataAddr int32, minMemorySize uint32) {
	p.mutex.Lock()
	defer p.mutex.Unlock()

	p.policy, p.parsedData, p.parsedDataAddr, p.memoryMinPages = policy, data, dataAddr, Pages(minMemorySize)
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/google-api-go-client/drive/v2"
	"fmt"
	// "github.com/google/google-api-go-client/drive/v2"
	"net/http"
)

func NewDownloader(assets map[string]struct{}, outputDir string) (*Downloader, error) {
	// client, err := auth.GetOauth2Client(config.ClientId, config.ClientSecret, tokenPath, promptUser)

	client := http.Client{}

	drive, err := drive.New(&client)
	if err != nil {
		return nil, err
	}

	// Return a new authorized Drive client.
	return &Downloader{
		assets,
		outputDir,
		&Drive{
			drive,
			&client,
		},
	}, nil
	// return &Drive{drive, &client}, nil
}

type DFile struct {
	DownloadUrl   string `json:"downloadUrl,omitempty"`
	FileExtension string `json:"fileExtension,omitempty"`
	Title         string `json:"title,omitempty"`
	// EmbedLink string `json:"embedLink,omitempty"`
	// ModifiedDate string `json:"modifiedDate,omitempty"`
}

type Drive struct {
	*drive.Service
	client *http.Client
}

type Downloader struct {
	Assets    map[string]struct{}
	OutputDir string
	*Drive
}

func (d *Downloader) GetInfoAll() error {
	// map["http://gdrive.com/traffic.jpg":{}]
	for i, v := range d.Assets {
		v, err := d.GetInfo(i)
	}
	return err
}

// /home/andy/go/src/code.google.com/p/google-api-go-client/drive/v2/drive-gen.go
// line 3536
func (d *Downloader) GetInfo(url string) (*DFile, error) {
	return d.Service.Files.Get(url).Do()
}
<commit_msg>fix downloader tests<commit_after>package main

import (
	"code.google.com/p/google-api-go-client/drive/v2"
	// "fmt"
	// "github.com/google/google-api-go-client/drive/v2"
	"net/http"
)

func NewDownloader(assets map[string]struct{}, outputDir string) (*Downloader, error) {
	// client, err := auth.GetOauth2Client(config.ClientId, config.ClientSecret, tokenPath, promptUser)

	client := http.Client{}

	drive, err := drive.New(&client)
	if err != nil {
		return nil, err
	}

	// Return a new authorized Drive client.
	return &Downloader{
		assets,
		outputDir,
		&Drive{
			drive,
			&client,
		},
		map[string]DFile{},
	}, nil
	// return &Drive{drive, &client}, nil
}

type DFile struct {
	DownloadUrl   string `json:"downloadUrl,omitempty"`
	FileExtension string `json:"fileExtension,omitempty"`
	Title         string `json:"title,omitempty"`
	// EmbedLink string `json:"embedLink,omitempty"`
	// ModifiedDate string `json:"modifiedDate,omitempty"`
}

type Drive struct {
	*drive.Service
	client *http.Client
}

type Downloader struct {
	Assets    map[string]struct{}
	OutputDir string
	*Drive
	Metadata map[string]DFile
}

func (d *Downloader) GetInfoAll() error {
	// map["http://gdrive.com/traffic.jpg":{}]
	var err error
	for i := range d.Assets {
		d.Metadata[i], err = d.GetInfo(i)
	}
	return err
}

// /home/andy/go/src/code.google.com/p/google-api-go-client/drive/v2/drive-gen.go
// line 3536
func (d *Downloader) GetInfo(url string) (DFile, error) {
	f, err := d.Service.Files.Get(url).Do()
	return DFile{
		f.DownloadUrl,
		f.FileExtension,
		f.Title,
	}, err
	// return d.Service.Files.Get(url).Do()
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2019 gRPC 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.
 *
 */

// Binary grpclb_fallback is an interop test client for grpclb fallback.
package main

import (
	"context"
	"flag"
	"log"
	"net"
	"os"
	"os/exec"
	"syscall"
	"time"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc"
	_ "google.golang.org/grpc/balancer/grpclb"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/alts"
	"google.golang.org/grpc/credentials/google"
	_ "google.golang.org/grpc/xds/googledirectpath"

	testgrpc "google.golang.org/grpc/interop/grpc_testing"
	testpb "google.golang.org/grpc/interop/grpc_testing"
)

var (
	customCredentialsType         = flag.String("custom_credentials_type", "", "Client creds to use")
	serverURI                     = flag.String("server_uri", "dns:///staging-grpc-directpath-fallback-test.googleapis.com:443", "The server host name")
	unrouteLBAndBackendAddrsCmd   = flag.String("unroute_lb_and_backend_addrs_cmd", "", "Command to make LB and backend address unroutable")
	blackholeLBAndBackendAddrsCmd = flag.String("blackhole_lb_and_backend_addrs_cmd", "", "Command to make LB and backend addresses blackholed")
	testCase                      = flag.String("test_case", "",
		`Configure different test cases. Valid options are:
        fast_fallback_before_startup : LB/backend connections fail fast before RPC's have been made;
        fast_fallback_after_startup : LB/backend connections fail fast after RPC's have been made;
        slow_fallback_before_startup : LB/backend connections black hole before RPC's have been made;
        slow_fallback_after_startup : LB/backend connections black hole after RPC's have been made;`)
	infoLog  = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
	errorLog = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
)

func doRPCAndGetPath(client testgrpc.TestServiceClient, timeout time.Duration) testpb.GrpclbRouteType {
	infoLog.Printf("doRPCAndGetPath timeout:%v\n", timeout)
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	req := &testpb.SimpleRequest{
		FillGrpclbRouteType: true,
	}
	reply, err := client.UnaryCall(ctx, req)
	if err != nil {
		infoLog.Printf("doRPCAndGetPath error:%v\n", err)
		return testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_UNKNOWN
	}
	g := reply.GetGrpclbRouteType()
	infoLog.Printf("doRPCAndGetPath got grpclb route type: %v\n", g)
	if g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK && g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected grpclb route type to be either backend or fallback; got: %d", g)
	}
	return g
}

func dialTCPUserTimeout(ctx context.Context, addr string) (net.Conn, error) {
	control := func(network, address string, c syscall.RawConn) error {
		var syscallErr error
		controlErr := c.Control(func(fd uintptr) {
			syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, 20000)
		})
		if syscallErr != nil {
			errorLog.Fatalf("syscall error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr)
		}
		if controlErr != nil {
			errorLog.Fatalf("control error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr)
		}
		return nil
	}
	d := &net.Dialer{
		Control: control,
	}
	return d.DialContext(ctx, "tcp", addr)
}

func createTestConn() *grpc.ClientConn {
	opts := []grpc.DialOption{
		grpc.WithContextDialer(dialTCPUserTimeout),
	}
	switch *customCredentialsType {
	case "tls":
		creds := credentials.NewClientTLSFromCert(nil, "")
		opts = append(opts, grpc.WithTransportCredentials(creds))
	case "alts":
		creds := alts.NewClientCreds(alts.DefaultClientOptions())
		opts = append(opts, grpc.WithTransportCredentials(creds))
	case "google_default_credentials":
		opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials()))
	case "compute_engine_channel_creds":
		opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()))
	default:
		errorLog.Fatalf("Invalid --custom_credentials_type:%v", *customCredentialsType)
	}
	conn, err := grpc.Dial(*serverURI, opts...)
	if err != nil {
		errorLog.Fatalf("Fail to dial: %v", err)
	}
	return conn
}

func runCmd(command string) {
	infoLog.Printf("Running cmd:|%v|\n", command)
	if err := exec.Command("bash", "-c", command).Run(); err != nil {
		errorLog.Fatalf("error running cmd:|%v| : %v", command, err)
	}
}

func waitForFallbackAndDoRPCs(client testgrpc.TestServiceClient, fallbackDeadline time.Time) {
	fallbackRetryCount := 0
	fellBack := false
	for time.Now().Before(fallbackDeadline) {
		g := doRPCAndGetPath(client, 20*time.Second)
		if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK {
			infoLog.Println("Made one successul RPC to a fallback. Now expect the same for the rest.")
			fellBack = true
			break
		} else if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
			errorLog.Fatalf("Got RPC type backend. This suggests an error in test implementation")
		} else {
			infoLog.Println("Retryable RPC failure on iteration:", fallbackRetryCount)
		}
		fallbackRetryCount++
	}
	if !fellBack {
		infoLog.Fatalf("Didn't fall back before deadline: %v\n", fallbackDeadline)
	}
	for i := 0; i < 30; i++ {
		if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK {
			errorLog.Fatalf("Expected RPC to take grpclb route type FALLBACK. Got: %v", g)
		}
		time.Sleep(time.Second)
	}
}

func doFastFallbackBeforeStartup() {
	runCmd(*unrouteLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(5 * time.Second)
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doSlowFallbackBeforeStartup() {
	runCmd(*blackholeLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(60 * time.Second)
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doFastFallbackAfterStartup() {
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g)
	}
	runCmd(*unrouteLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(40 * time.Second)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doSlowFallbackAfterStartup() {
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g)
	}
	runCmd(*blackholeLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(40 * time.Second)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func main() {
	flag.Parse()
	if len(*unrouteLBAndBackendAddrsCmd) == 0 {
		errorLog.Fatalf("--unroute_lb_and_backend_addrs_cmd unset")
	}
	if len(*blackholeLBAndBackendAddrsCmd) == 0 {
		errorLog.Fatalf("--blackhole_lb_and_backend_addrs_cmd unset")
	}
	switch *testCase {
	case "fast_fallback_before_startup":
		doFastFallbackBeforeStartup()
		log.Printf("FastFallbackBeforeStartup done!\n")
	case "fast_fallback_after_startup":
		doFastFallbackAfterStartup()
		log.Printf("FastFallbackAfterStartup done!\n")
	case "slow_fallback_before_startup":
		doSlowFallbackBeforeStartup()
		log.Printf("SlowFallbackBeforeStartup done!\n")
	case "slow_fallback_after_startup":
		doSlowFallbackAfterStartup()
		log.Printf("SlowFallbackAfterStartup done!\n")
	default:
		errorLog.Fatalf("Unsupported test case: %v", *testCase)
	}
}
<commit_msg>xds/interop: update RPC timeout in blackhole after fallback case (#5174)<commit_after>/*
 *
 * Copyright 2019 gRPC 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.
 *
 */

// Binary grpclb_fallback is an interop test client for grpclb fallback.
package main

import (
	"context"
	"flag"
	"log"
	"net"
	"os"
	"os/exec"
	"syscall"
	"time"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc"
	_ "google.golang.org/grpc/balancer/grpclb"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/alts"
	"google.golang.org/grpc/credentials/google"
	_ "google.golang.org/grpc/xds/googledirectpath"

	testgrpc "google.golang.org/grpc/interop/grpc_testing"
	testpb "google.golang.org/grpc/interop/grpc_testing"
)

var (
	customCredentialsType         = flag.String("custom_credentials_type", "", "Client creds to use")
	serverURI                     = flag.String("server_uri", "dns:///staging-grpc-directpath-fallback-test.googleapis.com:443", "The server host name")
	unrouteLBAndBackendAddrsCmd   = flag.String("unroute_lb_and_backend_addrs_cmd", "", "Command to make LB and backend address unroutable")
	blackholeLBAndBackendAddrsCmd = flag.String("blackhole_lb_and_backend_addrs_cmd", "", "Command to make LB and backend addresses blackholed")
	testCase                      = flag.String("test_case", "",
		`Configure different test cases. Valid options are:
        fast_fallback_before_startup : LB/backend connections fail fast before RPC's have been made;
        fast_fallback_after_startup : LB/backend connections fail fast after RPC's have been made;
        slow_fallback_before_startup : LB/backend connections black hole before RPC's have been made;
        slow_fallback_after_startup : LB/backend connections black hole after RPC's have been made;`)
	infoLog  = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
	errorLog = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
)

func doRPCAndGetPath(client testgrpc.TestServiceClient, timeout time.Duration) testpb.GrpclbRouteType {
	infoLog.Printf("doRPCAndGetPath timeout:%v\n", timeout)
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	req := &testpb.SimpleRequest{
		FillGrpclbRouteType: true,
	}
	reply, err := client.UnaryCall(ctx, req)
	if err != nil {
		infoLog.Printf("doRPCAndGetPath error:%v\n", err)
		return testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_UNKNOWN
	}
	g := reply.GetGrpclbRouteType()
	infoLog.Printf("doRPCAndGetPath got grpclb route type: %v\n", g)
	if g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK && g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected grpclb route type to be either backend or fallback; got: %d", g)
	}
	return g
}

func dialTCPUserTimeout(ctx context.Context, addr string) (net.Conn, error) {
	control := func(network, address string, c syscall.RawConn) error {
		var syscallErr error
		controlErr := c.Control(func(fd uintptr) {
			syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, 20000)
		})
		if syscallErr != nil {
			errorLog.Fatalf("syscall error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr)
		}
		if controlErr != nil {
			errorLog.Fatalf("control error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr)
		}
		return nil
	}
	d := &net.Dialer{
		Control: control,
	}
	return d.DialContext(ctx, "tcp", addr)
}

func createTestConn() *grpc.ClientConn {
	opts := []grpc.DialOption{
		grpc.WithContextDialer(dialTCPUserTimeout),
	}
	switch *customCredentialsType {
	case "tls":
		creds := credentials.NewClientTLSFromCert(nil, "")
		opts = append(opts, grpc.WithTransportCredentials(creds))
	case "alts":
		creds := alts.NewClientCreds(alts.DefaultClientOptions())
		opts = append(opts, grpc.WithTransportCredentials(creds))
	case "google_default_credentials":
		opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials()))
	case "compute_engine_channel_creds":
		opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()))
	default:
		errorLog.Fatalf("Invalid --custom_credentials_type:%v", *customCredentialsType)
	}
	conn, err := grpc.Dial(*serverURI, opts...)
	if err != nil {
		errorLog.Fatalf("Fail to dial: %v", err)
	}
	return conn
}

func runCmd(command string) {
	infoLog.Printf("Running cmd:|%v|\n", command)
	if err := exec.Command("bash", "-c", command).Run(); err != nil {
		errorLog.Fatalf("error running cmd:|%v| : %v", command, err)
	}
}

func waitForFallbackAndDoRPCs(client testgrpc.TestServiceClient, fallbackDeadline time.Time) {
	fallbackRetryCount := 0
	fellBack := false
	for time.Now().Before(fallbackDeadline) {
		g := doRPCAndGetPath(client, 20*time.Second)
		if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK {
			infoLog.Println("Made one successul RPC to a fallback. Now expect the same for the rest.")
			fellBack = true
			break
		} else if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
			errorLog.Fatalf("Got RPC type backend. This suggests an error in test implementation")
		} else {
			infoLog.Println("Retryable RPC failure on iteration:", fallbackRetryCount)
		}
		fallbackRetryCount++
	}
	if !fellBack {
		infoLog.Fatalf("Didn't fall back before deadline: %v\n", fallbackDeadline)
	}
	for i := 0; i < 30; i++ {
		if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK {
			errorLog.Fatalf("Expected RPC to take grpclb route type FALLBACK. Got: %v", g)
		}
		time.Sleep(time.Second)
	}
}

func doFastFallbackBeforeStartup() {
	runCmd(*unrouteLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(5 * time.Second)
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doSlowFallbackBeforeStartup() {
	runCmd(*blackholeLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(60 * time.Second)
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doFastFallbackAfterStartup() {
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g)
	}
	runCmd(*unrouteLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(40 * time.Second)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func doSlowFallbackAfterStartup() {
	conn := createTestConn()
	defer conn.Close()
	client := testgrpc.NewTestServiceClient(conn)
	if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND {
		errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g)
	}
	runCmd(*blackholeLBAndBackendAddrsCmd)
	fallbackDeadline := time.Now().Add(80 * time.Second)
	waitForFallbackAndDoRPCs(client, fallbackDeadline)
}

func main() {
	flag.Parse()
	if len(*unrouteLBAndBackendAddrsCmd) == 0 {
		errorLog.Fatalf("--unroute_lb_and_backend_addrs_cmd unset")
	}
	if len(*blackholeLBAndBackendAddrsCmd) == 0 {
		errorLog.Fatalf("--blackhole_lb_and_backend_addrs_cmd unset")
	}
	switch *testCase {
	case "fast_fallback_before_startup":
		doFastFallbackBeforeStartup()
		log.Printf("FastFallbackBeforeStartup done!\n")
	case "fast_fallback_after_startup":
		doFastFallbackAfterStartup()
		log.Printf("FastFallbackAfterStartup done!\n")
	case "slow_fallback_before_startup":
		doSlowFallbackBeforeStartup()
		log.Printf("SlowFallbackBeforeStartup done!\n")
	case "slow_fallback_after_startup":
		doSlowFallbackAfterStartup()
		log.Printf("SlowFallbackAfterStartup done!\n")
	default:
		errorLog.Fatalf("Unsupported test case: %v", *testCase)
	}
}
<|endoftext|>


<commit_before>package dashboard

import (
	"time"

	"github.com/aerogo/aero"
	"github.com/aerogo/flow"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/pages/frontpage"
	"github.com/animenotifier/notify.moe/utils"
)

const maxPosts = 5
const maxFollowing = 5
const maxSoundTracks = 5
const maxScheduleItems = 5

// Get the dashboard or the frontpage when logged out.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)

	if user == nil {
		return frontpage.Get(ctx)
	}

	return dashboard(ctx)
}

// Render the dashboard.
func dashboard(ctx *aero.Context) string {
	var posts []*arn.Post
	var userList interface{}
	var followingList []*arn.User
	var soundTracks []*arn.SoundTrack
	var upcomingEpisodes []*arn.UpcomingEpisode

	user := utils.GetUser(ctx)

	flow.Parallel(func() {
		var err error
		posts, err = arn.AllPosts()

		if err != nil {
			return
		}

		arn.SortPostsLatestFirst(posts)
		posts = arn.FilterPostsWithUniqueThreads(posts, maxPosts)
	}, func() {
		animeList, err := arn.GetAnimeList(user)

		if err != nil {
			return
		}

		var keys []string

		for _, item := range animeList.Items {
			keys = append(keys, item.AnimeID)
		}

		objects, getErr := arn.DB.GetMany("Anime", keys)

		if getErr != nil {
			return
		}

		allAnimeInList := objects.([]*arn.Anime)
		now := time.Now().UTC().Format(time.RFC3339)

		for _, anime := range allAnimeInList {
			if len(upcomingEpisodes) >= maxScheduleItems {
				break
			}

			for _, episode := range anime.Episodes {
				if episode.AiringDate.Start > now {
					upcomingEpisodes = append(upcomingEpisodes, &arn.UpcomingEpisode{
						Anime:   anime,
						Episode: episode,
					})
					continue
				}
			}
		}
	}, func() {
		var err error
		soundTracks, err = arn.AllSoundTracks()

		if err != nil {
			return
		}

		arn.SortSoundTracksLatestFirst(soundTracks)

		if len(soundTracks) > maxSoundTracks {
			soundTracks = soundTracks[:maxSoundTracks]
		}
	}, func() {
		var err error
		userList, err = arn.DB.GetMany("User", user.Following)

		if err != nil {
			return
		}

		followingList = userList.([]*arn.User)
		followingList = arn.SortUsersLastSeen(followingList)

		if len(followingList) > maxFollowing {
			followingList = followingList[:maxFollowing]
		}
	})

	return ctx.HTML(components.Dashboard(upcomingEpisodes, posts, soundTracks, followingList))
}
<commit_msg>Added sorting to schedule<commit_after>package dashboard

import (
	"sort"
	"time"

	"github.com/aerogo/aero"
	"github.com/aerogo/flow"
	"github.com/animenotifier/arn"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/pages/frontpage"
	"github.com/animenotifier/notify.moe/utils"
)

const maxPosts = 5
const maxFollowing = 5
const maxSoundTracks = 5
const maxScheduleItems = 5

// Get the dashboard or the frontpage when logged out.
func Get(ctx *aero.Context) string {
	user := utils.GetUser(ctx)

	if user == nil {
		return frontpage.Get(ctx)
	}

	return dashboard(ctx)
}

// Render the dashboard.
func dashboard(ctx *aero.Context) string {
	var posts []*arn.Post
	var userList interface{}
	var followingList []*arn.User
	var soundTracks []*arn.SoundTrack
	var upcomingEpisodes []*arn.UpcomingEpisode

	user := utils.GetUser(ctx)

	flow.Parallel(func() {
		var err error
		posts, err = arn.AllPosts()

		if err != nil {
			return
		}

		arn.SortPostsLatestFirst(posts)
		posts = arn.FilterPostsWithUniqueThreads(posts, maxPosts)
	}, func() {
		animeList, err := arn.GetAnimeList(user)

		if err != nil {
			return
		}

		var keys []string

		for _, item := range animeList.Items {
			keys = append(keys, item.AnimeID)
		}

		objects, getErr := arn.DB.GetMany("Anime", keys)

		if getErr != nil {
			return
		}

		allAnimeInList := objects.([]*arn.Anime)
		now := time.Now().UTC().Format(time.RFC3339)

		for _, anime := range allAnimeInList {
			if len(upcomingEpisodes) >= maxScheduleItems {
				break
			}

			for _, episode := range anime.Episodes {
				if episode.AiringDate.Start > now {
					upcomingEpisodes = append(upcomingEpisodes, &arn.UpcomingEpisode{
						Anime:   anime,
						Episode: episode,
					})
					continue
				}
			}
		}

		sort.Slice(upcomingEpisodes, func(i, j int) bool {
			return upcomingEpisodes[i].Episode.AiringDate.Start < upcomingEpisodes[j].Episode.AiringDate.Start
		})
	}, func() {
		var err error
		soundTracks, err = arn.AllSoundTracks()

		if err != nil {
			return
		}

		arn.SortSoundTracksLatestFirst(soundTracks)

		if len(soundTracks) > maxSoundTracks {
			soundTracks = soundTracks[:maxSoundTracks]
		}
	}, func() {
		var err error
		userList, err = arn.DB.GetMany("User", user.Following)

		if err != nil {
			return
		}

		followingList = userList.([]*arn.User)
		followingList = arn.SortUsersLastSeen(followingList)

		if len(followingList) > maxFollowing {
			followingList = followingList[:maxFollowing]
		}
	})

	return ctx.HTML(components.Dashboard(upcomingEpisodes, posts, soundTracks, followingList))
}
<|endoftext|>


<commit_before>/*
Copyright 2020 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 e2e

import (
	"strings"

	apierrors "k8s.io/apimachinery/pkg/api/errors"
	utilnet "k8s.io/apimachinery/pkg/util/net"
)

func isRetryableAPIError(err error) bool {
	// These errors may indicate a transient error that we can retry in tests.
	if apierrors.IsInternalError(err) || apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err) ||
		apierrors.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) || utilnet.IsConnectionReset(err) ||
		utilnet.IsConnectionRefused(err) {
		return true
	}

	// If the error sends the Retry-After header, we respect it as an explicit confirmation we should retry.
	if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry {
		return true
	}

	// "etcdserver: request timed out" does not seem to match the timeout errors above
	if strings.Contains(err.Error(), "etcdserver: request timed out") {
		return true
	}

	return false
}

//nolint:lll // sample output cannot be split into multiple lines.
/*
getStdErr will extract the stderror and returns the actual error message

Sample kubectl output:

error running /usr/local/bin/kubectl --server=https://192.168.39.67:8443 --kubeconfig=***** --namespace=default create -f -:
Command stdout:

stderr:
Error from server (AlreadyExists): error when creating "STDIN": services "csi-rbdplugin-provisioner" already exists
Error from server (AlreadyExists): error when creating "STDIN": deployments.apps "csi-rbdplugin-provisioner" already exists

error:
exit status 1

Sample message returned from this function:

Error from server (AlreadyExists): error when creating "STDIN": services "csi-rbdplugin-provisioner" already exists
Error from server (AlreadyExists): error when creating "STDIN": deployments.apps "csi-rbdplugin-provisioner" already exists.
*/
func getStdErr(errString string) string {
	stdErrStr := "stderr:\n"
	errStr := "error:\n"
	stdErrPosition := strings.Index(errString, stdErrStr)
	if stdErrPosition == -1 {
		return ""
	}

	errPosition := strings.Index(errString, errStr)
	if errPosition == -1 {
		return ""
	}

	stdErrPositionLength := stdErrPosition + len(stdErrStr)
	if stdErrPositionLength >= errPosition {
		return ""
	}

	return errString[stdErrPosition+len(stdErrStr) : errPosition]
}

// isAlreadyExistsCLIError checks for already exists error from kubectl CLI.
func isAlreadyExistsCLIError(err error) bool {
	if err == nil {
		return false
	}
	// if multiple resources already exists. each error is separated by newline
	stdErr := getStdErr(err.Error())
	if stdErr == "" {
		return false
	}

	stdErrs := strings.Split(stdErr, "\n")
	for _, s := range stdErrs {
		// If the string is just a new line continue
		if strings.TrimSuffix(s, "\n") == "" {
			continue
		}
		// Ignore warnings
		if strings.Contains(s, "Warning") {
			continue
		}
		// Resource already exists error message
		if !strings.Contains(s, "Error from server (AlreadyExists)") {
			return false
		}
	}

	return true
}
<commit_msg>e2e: retry when a "transport is closing" error is hit<commit_after>/*
Copyright 2020 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 e2e

import (
	"strings"

	apierrors "k8s.io/apimachinery/pkg/api/errors"
	utilnet "k8s.io/apimachinery/pkg/util/net"
)

func isRetryableAPIError(err error) bool {
	// These errors may indicate a transient error that we can retry in tests.
	if apierrors.IsInternalError(err) || apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err) ||
		apierrors.IsTooManyRequests(err) || utilnet.IsProbableEOF(err) || utilnet.IsConnectionReset(err) ||
		utilnet.IsConnectionRefused(err) {
		return true
	}

	// If the error sends the Retry-After header, we respect it as an explicit confirmation we should retry.
	if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry {
		return true
	}

	// "etcdserver: request timed out" does not seem to match the timeout errors above
	if strings.Contains(err.Error(), "etcdserver: request timed out") {
		return true
	}

	// "transport is closing" is an internal gRPC err, we can not use ErrConnClosing
	if strings.Contains(err.Error(), "transport is closing") {
		return true
	}

	return false
}

//nolint:lll // sample output cannot be split into multiple lines.
/*
getStdErr will extract the stderror and returns the actual error message

Sample kubectl output:

error running /usr/local/bin/kubectl --server=https://192.168.39.67:8443 --kubeconfig=***** --namespace=default create -f -:
Command stdout:

stderr:
Error from server (AlreadyExists): error when creating "STDIN": services "csi-rbdplugin-provisioner" already exists
Error from server (AlreadyExists): error when creating "STDIN": deployments.apps "csi-rbdplugin-provisioner" already exists

error:
exit status 1

Sample message returned from this function:

Error from server (AlreadyExists): error when creating "STDIN": services "csi-rbdplugin-provisioner" already exists
Error from server (AlreadyExists): error when creating "STDIN": deployments.apps "csi-rbdplugin-provisioner" already exists.
*/
func getStdErr(errString string) string {
	stdErrStr := "stderr:\n"
	errStr := "error:\n"
	stdErrPosition := strings.Index(errString, stdErrStr)
	if stdErrPosition == -1 {
		return ""
	}

	errPosition := strings.Index(errString, errStr)
	if errPosition == -1 {
		return ""
	}

	stdErrPositionLength := stdErrPosition + len(stdErrStr)
	if stdErrPositionLength >= errPosition {
		return ""
	}

	return errString[stdErrPosition+len(stdErrStr) : errPosition]
}

// isAlreadyExistsCLIError checks for already exists error from kubectl CLI.
func isAlreadyExistsCLIError(err error) bool {
	if err == nil {
		return false
	}
	// if multiple resources already exists. each error is separated by newline
	stdErr := getStdErr(err.Error())
	if stdErr == "" {
		return false
	}

	stdErrs := strings.Split(stdErr, "\n")
	for _, s := range stdErrs {
		// If the string is just a new line continue
		if strings.TrimSuffix(s, "\n") == "" {
			continue
		}
		// Ignore warnings
		if strings.Contains(s, "Warning") {
			continue
		}
		// Resource already exists error message
		if !strings.Contains(s, "Error from server (AlreadyExists)") {
			return false
		}
	}

	return true
}
<|endoftext|>