<commit_before>package ec2

//----------------------------------------------------------------------------
// Package factored import statement:
//----------------------------------------------------------------------------

import (

	// Stdlib:
	"encoding/base64"
	"fmt"
	"log"
	"strings"

	// Community:
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
)

//----------------------------------------------------------------------------
// Typedefs:
//----------------------------------------------------------------------------

// Data contains variables used by EC2 API.
type Data struct {
	Region        string
	SubnetIds     string
	ImageID       string
	KeyPair       string
	InsType       string
	Hostname      string
	ElasticIP     string
	VpcCidrBlock  string
	VpcID         string
	VpcNameTag    string
	IntSubnetCidr string
	ExtSubnetCidr string
	IntSubnetID   string
	ExtSubnetID   string
}

//--------------------------------------------------------------------------
// func: Setup
//--------------------------------------------------------------------------

// Setup an EC2 VPC and all the related components.
func (d *Data) Setup() error {

	// Connect and authenticate to the API endpoint:
	log.Printf("[setup-ec2] INFO Connecting to %s\n", d.Region)
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(d.Region)}))

	// Create the VPC:
	if err := d.createVpc(*svc); err != nil {
		return err
	}

	// Create external and internal subnets:
	if err := d.createSubnets(*svc); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-------------------------------------------------------------------------
// func: createVpc
//-------------------------------------------------------------------------

func (d *Data) createVpc(svc ec2.EC2) error {

	// Forge the VPC request:
	prmsVpc := &ec2.CreateVpcInput{
		CidrBlock:       aws.String(d.VpcCidrBlock),
		DryRun:          aws.Bool(false),
		InstanceTenancy: aws.String("default"),
	}

	// Send the VPC request:
	rspVpc, err := svc.CreateVpc(prmsVpc)
	if err != nil {
		return err
	}

	// Store the VPC ID:
	d.VpcID = *rspVpc.Vpc.VpcId
	log.Printf("[setup-ec2] INFO New VPC %s\n", d.VpcID)

	// Tag the VPC:
	if err = tag(d.VpcID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Return on success:
	log.Printf("[setup-ec2] INFO VPC tagged as %s\n", d.VpcNameTag)
	return nil
}

//-------------------------------------------------------------------------
// func: createSubnets
//-------------------------------------------------------------------------

func (d *Data) createSubnets(svc ec2.EC2) error {

	// Forge the internal subnet request:
	prmsInt := &ec2.CreateSubnetInput{
		CidrBlock: aws.String(d.IntSubnetCidr),
		VpcId:     aws.String(d.VpcID),
		DryRun:    aws.Bool(false),
	}

	// Send the subnet request:
	rspInt, err := svc.CreateSubnet(prmsInt)
	if err != nil {
		return err
	}

	// Store the subnet ID:
	d.IntSubnetID = *rspInt.Subnet.SubnetId
	log.Printf("[setup-ec2] INFO New internal subnet %s\n", d.IntSubnetID)

	// Tag the subnet:
	if err = tag(d.IntSubnetID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Forge the external subnet request:
	prmsExt := &ec2.CreateSubnetInput{
		CidrBlock: aws.String(d.ExtSubnetCidr),
		VpcId:     aws.String(d.VpcID),
		DryRun:    aws.Bool(false),
	}

	// Send the subnet request:
	rspExt, err := svc.CreateSubnet(prmsExt)
	if err != nil {
		return err
	}

	// Store the subnet ID:
	d.ExtSubnetID = *rspExt.Subnet.SubnetId
	log.Printf("[setup-ec2] INFO New external subnet %s\n", d.ExtSubnetID)

	// Tag the subnet:
	if err = tag(d.IntSubnetID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-------------------------------------------------------------------------
// func: tag
//-------------------------------------------------------------------------

func tag(resource, key, value string, svc ec2.EC2) error {

	// Forge the tag request:
	params := &ec2.CreateTagsInput{
		Resources: []*string{
			aws.String(resource),
		},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String(key),
				Value: aws.String(value),
			},
		},
		DryRun: aws.Bool(false),
	}

	// Send the tag request:
	_, err := svc.CreateTags(params)
	if err != nil {
		return err
	}

	return nil
}

//--------------------------------------------------------------------------
// func: Run
//--------------------------------------------------------------------------

// Run uses EC2 API to launch a new instance.
func (d *Data) Run(udata []byte) error {

	// Connect and authenticate to the API endpoint:
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(d.Region)}))

	// Forge the network interfaces:
	var networkInterfaces []*ec2.InstanceNetworkInterfaceSpecification
	subnetIds := strings.Split(d.SubnetIds, ",")

	for i := 0; i < len(subnetIds); i++ {

		// Forge the security group ids:
		var securityGroupIds []*string
		for _, gid := range strings.Split(subnetIds[i], ":")[1:] {
			securityGroupIds = append(securityGroupIds, aws.String(gid))
		}

		iface := ec2.InstanceNetworkInterfaceSpecification{
			DeleteOnTermination: aws.Bool(true),
			DeviceIndex:         aws.Int64(int64(i)),
			Groups:              securityGroupIds,
			SubnetId:            aws.String(strings.Split(subnetIds[i], ":")[0]),
		}

		networkInterfaces = append(networkInterfaces, &iface)
	}

	// Send the request:
	runResult, err := svc.RunInstances(&ec2.RunInstancesInput{
		ImageId:           aws.String(d.ImageID),
		MinCount:          aws.Int64(1),
		MaxCount:          aws.Int64(1),
		KeyName:           aws.String(d.KeyPair),
		InstanceType:      aws.String(d.InsType),
		NetworkInterfaces: networkInterfaces,
		UserData:          aws.String(base64.StdEncoding.EncodeToString([]byte(udata))),
	})

	if err != nil {
		return err
	}

	// Pretty-print the response data:
	fmt.Println("Created instance", *runResult.Instances[0].InstanceId)

	// Add tags to the created instance:
	_, err = svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{runResult.Instances[0].InstanceId},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String("Name"),
				Value: aws.String(d.Hostname),
			},
		},
	})

	if err != nil {
		return err
	}

	// Allocate an elastic IP address:
	if d.ElasticIP == "true" {

		params := &ec2.AllocateAddressInput{
			Domain: aws.String("vpc"),
			DryRun: aws.Bool(false),
		}

		// Send the request:
		resp, err := svc.AllocateAddress(params)

		if err != nil {
			return err
		}

		// Pretty-print the response data:
		fmt.Println(resp)
	}

	// Return on success:
	return nil
}
<commit_msg>Fix resource ID<commit_after>package ec2

//----------------------------------------------------------------------------
// Package factored import statement:
//----------------------------------------------------------------------------

import (

	// Stdlib:
	"encoding/base64"
	"fmt"
	"log"
	"strings"

	// Community:
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
)

//----------------------------------------------------------------------------
// Typedefs:
//----------------------------------------------------------------------------

// Data contains variables used by EC2 API.
type Data struct {
	Region        string
	SubnetIds     string
	ImageID       string
	KeyPair       string
	InsType       string
	Hostname      string
	ElasticIP     string
	VpcCidrBlock  string
	VpcID         string
	VpcNameTag    string
	IntSubnetCidr string
	ExtSubnetCidr string
	IntSubnetID   string
	ExtSubnetID   string
}

//--------------------------------------------------------------------------
// func: Setup
//--------------------------------------------------------------------------

// Setup an EC2 VPC and all the related components.
func (d *Data) Setup() error {

	// Connect and authenticate to the API endpoint:
	log.Printf("[setup-ec2] INFO Connecting to %s\n", d.Region)
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(d.Region)}))

	// Create the VPC:
	if err := d.createVpc(*svc); err != nil {
		return err
	}

	// Create external and internal subnets:
	if err := d.createSubnets(*svc); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-------------------------------------------------------------------------
// func: createVpc
//-------------------------------------------------------------------------

func (d *Data) createVpc(svc ec2.EC2) error {

	// Forge the VPC request:
	prmsVpc := &ec2.CreateVpcInput{
		CidrBlock:       aws.String(d.VpcCidrBlock),
		DryRun:          aws.Bool(false),
		InstanceTenancy: aws.String("default"),
	}

	// Send the VPC request:
	rspVpc, err := svc.CreateVpc(prmsVpc)
	if err != nil {
		return err
	}

	// Store the VPC ID:
	d.VpcID = *rspVpc.Vpc.VpcId
	log.Printf("[setup-ec2] INFO New VPC %s\n", d.VpcID)

	// Tag the VPC:
	if err = tag(d.VpcID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Return on success:
	log.Printf("[setup-ec2] INFO VPC tagged as %s\n", d.VpcNameTag)
	return nil
}

//-------------------------------------------------------------------------
// func: createSubnets
//-------------------------------------------------------------------------

func (d *Data) createSubnets(svc ec2.EC2) error {

	// Forge the internal subnet request:
	prmsInt := &ec2.CreateSubnetInput{
		CidrBlock: aws.String(d.IntSubnetCidr),
		VpcId:     aws.String(d.VpcID),
		DryRun:    aws.Bool(false),
	}

	// Send the subnet request:
	rspInt, err := svc.CreateSubnet(prmsInt)
	if err != nil {
		return err
	}

	// Store the subnet ID:
	d.IntSubnetID = *rspInt.Subnet.SubnetId
	log.Printf("[setup-ec2] INFO New internal subnet %s\n", d.IntSubnetID)

	// Tag the subnet:
	if err = tag(d.IntSubnetID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Forge the external subnet request:
	prmsExt := &ec2.CreateSubnetInput{
		CidrBlock: aws.String(d.ExtSubnetCidr),
		VpcId:     aws.String(d.VpcID),
		DryRun:    aws.Bool(false),
	}

	// Send the subnet request:
	rspExt, err := svc.CreateSubnet(prmsExt)
	if err != nil {
		return err
	}

	// Store the subnet ID:
	d.ExtSubnetID = *rspExt.Subnet.SubnetId
	log.Printf("[setup-ec2] INFO New external subnet %s\n", d.ExtSubnetID)

	// Tag the subnet:
	if err = tag(d.ExtSubnetID, "Name", d.VpcNameTag, svc); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-------------------------------------------------------------------------
// func: tag
//-------------------------------------------------------------------------

func tag(resource, key, value string, svc ec2.EC2) error {

	// Forge the tag request:
	params := &ec2.CreateTagsInput{
		Resources: []*string{
			aws.String(resource),
		},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String(key),
				Value: aws.String(value),
			},
		},
		DryRun: aws.Bool(false),
	}

	// Send the tag request:
	_, err := svc.CreateTags(params)
	if err != nil {
		return err
	}

	return nil
}

//--------------------------------------------------------------------------
// func: Run
//--------------------------------------------------------------------------

// Run uses EC2 API to launch a new instance.
func (d *Data) Run(udata []byte) error {

	// Connect and authenticate to the API endpoint:
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(d.Region)}))

	// Forge the network interfaces:
	var networkInterfaces []*ec2.InstanceNetworkInterfaceSpecification
	subnetIds := strings.Split(d.SubnetIds, ",")

	for i := 0; i < len(subnetIds); i++ {

		// Forge the security group ids:
		var securityGroupIds []*string
		for _, gid := range strings.Split(subnetIds[i], ":")[1:] {
			securityGroupIds = append(securityGroupIds, aws.String(gid))
		}

		iface := ec2.InstanceNetworkInterfaceSpecification{
			DeleteOnTermination: aws.Bool(true),
			DeviceIndex:         aws.Int64(int64(i)),
			Groups:              securityGroupIds,
			SubnetId:            aws.String(strings.Split(subnetIds[i], ":")[0]),
		}

		networkInterfaces = append(networkInterfaces, &iface)
	}

	// Send the request:
	runResult, err := svc.RunInstances(&ec2.RunInstancesInput{
		ImageId:           aws.String(d.ImageID),
		MinCount:          aws.Int64(1),
		MaxCount:          aws.Int64(1),
		KeyName:           aws.String(d.KeyPair),
		InstanceType:      aws.String(d.InsType),
		NetworkInterfaces: networkInterfaces,
		UserData:          aws.String(base64.StdEncoding.EncodeToString([]byte(udata))),
	})

	if err != nil {
		return err
	}

	// Pretty-print the response data:
	fmt.Println("Created instance", *runResult.Instances[0].InstanceId)

	// Add tags to the created instance:
	_, err = svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{runResult.Instances[0].InstanceId},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String("Name"),
				Value: aws.String(d.Hostname),
			},
		},
	})

	if err != nil {
		return err
	}

	// Allocate an elastic IP address:
	if d.ElasticIP == "true" {

		params := &ec2.AllocateAddressInput{
			Domain: aws.String("vpc"),
			DryRun: aws.Bool(false),
		}

		// Send the request:
		resp, err := svc.AllocateAddress(params)

		if err != nil {
			return err
		}

		// Pretty-print the response data:
		fmt.Println(resp)
	}

	// Return on success:
	return nil
}
<|endoftext|>


<commit_before>package richcontent

import (
	"fmt"
	"html"
	"net/url"
	"regexp"
	"strings"

	"github.com/ptt/pttweb/extcache"
	"golang.org/x/net/context"
)

func FindUrl(ctx context.Context, input []byte) ([]RichContent, error) {
	rcs := make([]RichContent, 0, 4)
	for _, u := range FindAllUrlsIndex(input) {
		urlBytes := input[u[0]:u[1]]
		var components []Component
		for _, p := range defaultUrlPatterns {
			if match := p.Pattern.FindSubmatchIndex(urlBytes); match != nil {
				if c, err := p.Handler(ctx, urlBytes, MatchIndices(match)); err == nil {
					components = c
				}
				break
			}
		}
		rcs = append(rcs, MakeRichContent(u[0], u[1], string(urlBytes), components))
	}
	return rcs, nil
}

type UrlPatternHandler func(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error)

type UrlPattern struct {
	Pattern *regexp.Regexp
	Handler UrlPatternHandler
}

var defaultUrlPatterns = []*UrlPattern{
	newUrlPattern(`^https?://(?:www\.youtube\.com/watch\?(?:.+&)*v=|youtu\.be/)([\w\-]+)`, handleYoutube),
	newUrlPattern(`^https?://i\.imgur\.com/([\w]+)\.((?i)png|jpeg|jpg|gif)$`, handleImgurSingle), // Note: cuz some users use http
	newUrlPattern(`^https?://imgur\.com/([,\w]+)(?:\#(\d+))?[^/]*$`, handleImgurMulti),
	newUrlPattern(`^http://picmoe\.net/d\.php\?id=(\d+)`, handlePicmoe),
	newUrlPattern(`\.(?i:png|jpeg|jpg|gif)$`, handleGenericImage),
}

func newUrlPattern(pattern string, handler UrlPatternHandler) *UrlPattern {
	return &UrlPattern{
		Pattern: regexp.MustCompile(pattern),
		Handler: handler,
	}
}

func imageHtmlTag(urlString string) string {
	return fmt.Sprintf(`<img src="%s" alt="" />`, html.EscapeString(urlString))
}

// Handlers

func handleYoutube(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	id := url.PathEscape(string(match.ByteSliceOf(urlBytes, 1)))
	return []Component{
		MakeComponent(fmt.Sprintf(
			`<div class="resize-container"><div class="resize-content"><iframe class="youtube-player" type="text/html" src="//www.youtube.com/embed/%s" frameborder="0" allowfullscreen></iframe></div></div>`,
			id)),
	}, nil
}

func handleSameSchemeImage(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	return []Component{MakeComponent(imageHtmlTag(string(match.ByteSliceOf(urlBytes, 1))))}, nil
}

func handleImgurSingle(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	cache, _ := extcache.FromContext(ctx)
	if cache == nil {
		return handleImgurMulti(ctx, urlBytes, match)
	}
	id := string(match.ByteSliceOf(urlBytes, 1))
	ext := string(match.ByteSliceOf(urlBytes, 2))
	// Use at biggest large image.
	if n := len(id); n > 0 && id[n-1] == 'h' {
		id = id[:n-1] + "l"
	} else {
		id += "l"
	}
	escapedId := url.PathEscape(id + "." + ext)
	src, err := cache.Generate("https://i.imgur.com/" + escapedId)
	if err != nil {
		return nil, nil // Silently ignore
	}
	return []Component{MakeComponent(imageHtmlTag(src))}, nil
}

func handleImgurMulti(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	var comps []Component
	for _, id := range strings.Split(string(match.ByteSliceOf(urlBytes, 1)), ",") {
		escapedId := url.PathEscape(id)
		comps = append(comps, MakeComponent(
			fmt.Sprintf(`<blockquote class="imgur-embed-pub" lang="en" data-id="%s"><a href="//imgur.com/%s"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>`, escapedId, escapedId),
		))
	}
	return comps, nil
}

func handlePicmoe(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	link := fmt.Sprintf(`http://picmoe.net/src/%ss.jpg`, string(match.ByteSliceOf(urlBytes, 1)))
	return []Component{MakeComponent(imageHtmlTag(link))}, nil
}

func handleGenericImage(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	return []Component{MakeComponent(imageHtmlTag(string(urlBytes)))}, nil
}
<commit_msg>richcontent: Use lazy image loading<commit_after>package richcontent

import (
	"fmt"
	"html"
	"net/url"
	"regexp"
	"strings"

	"github.com/ptt/pttweb/extcache"
	"golang.org/x/net/context"
)

func FindUrl(ctx context.Context, input []byte) ([]RichContent, error) {
	rcs := make([]RichContent, 0, 4)
	for _, u := range FindAllUrlsIndex(input) {
		urlBytes := input[u[0]:u[1]]
		var components []Component
		for _, p := range defaultUrlPatterns {
			if match := p.Pattern.FindSubmatchIndex(urlBytes); match != nil {
				if c, err := p.Handler(ctx, urlBytes, MatchIndices(match)); err == nil {
					components = c
				}
				break
			}
		}
		rcs = append(rcs, MakeRichContent(u[0], u[1], string(urlBytes), components))
	}
	return rcs, nil
}

type UrlPatternHandler func(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error)

type UrlPattern struct {
	Pattern *regexp.Regexp
	Handler UrlPatternHandler
}

var defaultUrlPatterns = []*UrlPattern{
	newUrlPattern(`^https?://(?:www\.youtube\.com/watch\?(?:.+&)*v=|youtu\.be/)([\w\-]+)`, handleYoutube),
	newUrlPattern(`^https?://i\.imgur\.com/([\w]+)\.((?i)png|jpeg|jpg|gif)$`, handleImgurSingle), // Note: cuz some users use http
	newUrlPattern(`^https?://imgur\.com/([,\w]+)(?:\#(\d+))?[^/]*$`, handleImgurMulti),
	newUrlPattern(`^http://picmoe\.net/d\.php\?id=(\d+)`, handlePicmoe),
	newUrlPattern(`\.(?i:png|jpeg|jpg|gif)$`, handleGenericImage),
}

func newUrlPattern(pattern string, handler UrlPatternHandler) *UrlPattern {
	return &UrlPattern{
		Pattern: regexp.MustCompile(pattern),
		Handler: handler,
	}
}

func imageHtmlTag(urlString string) string {
	return fmt.Sprintf(`<img src="%s" alt="" loading="lazy" />`, html.EscapeString(urlString))
}

// Handlers

func handleYoutube(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	id := url.PathEscape(string(match.ByteSliceOf(urlBytes, 1)))
	return []Component{
		MakeComponent(fmt.Sprintf(
			`<div class="resize-container"><div class="resize-content"><iframe class="youtube-player" type="text/html" src="//www.youtube.com/embed/%s" frameborder="0" allowfullscreen></iframe></div></div>`,
			id)),
	}, nil
}

func handleSameSchemeImage(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	return []Component{MakeComponent(imageHtmlTag(string(match.ByteSliceOf(urlBytes, 1))))}, nil
}

func handleImgurSingle(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	cache, _ := extcache.FromContext(ctx)
	if cache == nil {
		return handleImgurMulti(ctx, urlBytes, match)
	}
	id := string(match.ByteSliceOf(urlBytes, 1))
	ext := string(match.ByteSliceOf(urlBytes, 2))
	// Use at biggest large image.
	if n := len(id); n > 0 && id[n-1] == 'h' {
		id = id[:n-1] + "l"
	} else {
		id += "l"
	}
	escapedId := url.PathEscape(id + "." + ext)
	src, err := cache.Generate("https://i.imgur.com/" + escapedId)
	if err != nil {
		return nil, nil // Silently ignore
	}
	return []Component{MakeComponent(imageHtmlTag(src))}, nil
}

func handleImgurMulti(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	var comps []Component
	for _, id := range strings.Split(string(match.ByteSliceOf(urlBytes, 1)), ",") {
		escapedId := url.PathEscape(id)
		comps = append(comps, MakeComponent(
			fmt.Sprintf(`<blockquote class="imgur-embed-pub" lang="en" data-id="%s"><a href="//imgur.com/%s"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>`, escapedId, escapedId),
		))
	}
	return comps, nil
}

func handlePicmoe(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	link := fmt.Sprintf(`http://picmoe.net/src/%ss.jpg`, string(match.ByteSliceOf(urlBytes, 1)))
	return []Component{MakeComponent(imageHtmlTag(link))}, nil
}

func handleGenericImage(ctx context.Context, urlBytes []byte, match MatchIndices) ([]Component, error) {
	return []Component{MakeComponent(imageHtmlTag(string(urlBytes)))}, nil
}
<|endoftext|>


<commit_before>// +build !confonly
package http

import (
	"context"
	"encoding/base64"
	"io"
	"strings"

	"v2ray.com/core"
	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/retry"
	"v2ray.com/core/common/session"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/common/task"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/transport"
	"v2ray.com/core/transport/internet"
)

type Client struct {
	serverPicker  protocol.ServerPicker
	policyManager policy.Manager
}

// NewClient create a new http client based on the given config.
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
	serverList := protocol.NewServerList()
	for _, rec := range config.Server {
		s, err := protocol.NewServerSpecFromPB(*rec)
		if err != nil {
			return nil, newError("failed to get server spec").Base(err)
		}
		serverList.AddServer(s)
	}
	if serverList.Size() == 0 {
		return nil, newError("0 target server")
	}

	v := core.MustFromContext(ctx)
	return &Client{
		serverPicker:  protocol.NewRoundRobinServerPicker(serverList),
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
	}, nil
}

// Process implements proxy.Outbound.Process. We first create a socket tunnel via HTTP CONNECT method, then redirect all inbound traffic to that tunnel.
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
	outbound := session.OutboundFromContext(ctx)
	if outbound == nil || !outbound.Target.IsValid() {
		return newError("target not specified.")
	}
	destination := outbound.Target

	if destination.Network == net.Network_UDP {
		return newError("UDP is not supported by HTTP outbound")
	}

	var server *protocol.ServerSpec
	var conn internet.Connection

	if err := retry.ExponentialBackoff(5, 100).On(func() error {
		server = c.serverPicker.PickServer()
		dest := server.Destination()
		rawConn, err := dialer.Dial(ctx, dest)
		if err != nil {
			return err
		}
		conn = rawConn

		return nil
	}); err != nil {
		return newError("failed to find an available destination").Base(err)
	}

	defer func() {
		if err := conn.Close(); err != nil {
			newError("failed to closed connection").Base(err).WriteToLog(session.ExportIDToError(ctx))
		}
	}()

	p := c.policyManager.ForLevel(0)

	user := server.PickUser()
	if user != nil {
		p = c.policyManager.ForLevel(user.Level)
	}

	if err := setUpHttpTunnel(conn, conn, &destination, user); err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(ctx)
	timer := signal.CancelAfterInactivity(ctx, cancel, p.Timeouts.ConnectionIdle)

	requestFunc := func() error {
		defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
		return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
	}
	responseFunc := func() error {
		defer timer.SetTimeout(p.Timeouts.UplinkOnly)
		return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
	}

	var responseDonePost = task.OnSuccess(responseFunc, task.Close(link.Writer))
	if err := task.Run(ctx, requestFunc, responseDonePost); err != nil {
		return newError("connection ends").Base(err)
	}

	return nil
}

// setUpHttpTunnel will create a socket tunnel via HTTP CONNECT method
func setUpHttpTunnel(reader io.Reader, writer io.Writer, destination *net.Destination, user *protocol.MemoryUser) error {
	var headers []string
	destNetAddr := destination.NetAddr()
	headers = append(headers, "CONNECT "+destNetAddr+" HTTP/1.1")
	headers = append(headers, "Host: "+destNetAddr)
	if user != nil && user.Account != nil {
		account := user.Account.(*Account)
		auth := account.GetUsername() + ":" + account.GetPassword()
		headers = append(headers, "Proxy-Authorization: Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
	}
	headers = append(headers, "Proxy-Connection: Keep-Alive")

	b := buf.New()
	b.WriteString(strings.Join(headers, "\r\n") + "\r\n\r\n")
	if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
		return err
	}

	b.Clear()
	if _, err := b.ReadFrom(reader); err != nil {
		return err
	}

	return nil
}

func init() {
	common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return NewClient(ctx, config.(*ClientConfig))
	}))
}
<commit_msg>blank row between build and package<commit_after>// +build !confonly

package http

import (
	"context"
	"encoding/base64"
	"io"
	"strings"

	"v2ray.com/core"
	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/retry"
	"v2ray.com/core/common/session"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/common/task"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/transport"
	"v2ray.com/core/transport/internet"
)

type Client struct {
	serverPicker  protocol.ServerPicker
	policyManager policy.Manager
}

// NewClient create a new http client based on the given config.
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
	serverList := protocol.NewServerList()
	for _, rec := range config.Server {
		s, err := protocol.NewServerSpecFromPB(*rec)
		if err != nil {
			return nil, newError("failed to get server spec").Base(err)
		}
		serverList.AddServer(s)
	}
	if serverList.Size() == 0 {
		return nil, newError("0 target server")
	}

	v := core.MustFromContext(ctx)
	return &Client{
		serverPicker:  protocol.NewRoundRobinServerPicker(serverList),
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
	}, nil
}

// Process implements proxy.Outbound.Process. We first create a socket tunnel via HTTP CONNECT method, then redirect all inbound traffic to that tunnel.
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
	outbound := session.OutboundFromContext(ctx)
	if outbound == nil || !outbound.Target.IsValid() {
		return newError("target not specified.")
	}
	destination := outbound.Target

	if destination.Network == net.Network_UDP {
		return newError("UDP is not supported by HTTP outbound")
	}

	var server *protocol.ServerSpec
	var conn internet.Connection

	if err := retry.ExponentialBackoff(5, 100).On(func() error {
		server = c.serverPicker.PickServer()
		dest := server.Destination()
		rawConn, err := dialer.Dial(ctx, dest)
		if err != nil {
			return err
		}
		conn = rawConn

		return nil
	}); err != nil {
		return newError("failed to find an available destination").Base(err)
	}

	defer func() {
		if err := conn.Close(); err != nil {
			newError("failed to closed connection").Base(err).WriteToLog(session.ExportIDToError(ctx))
		}
	}()

	p := c.policyManager.ForLevel(0)

	user := server.PickUser()
	if user != nil {
		p = c.policyManager.ForLevel(user.Level)
	}

	if err := setUpHttpTunnel(conn, conn, &destination, user); err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(ctx)
	timer := signal.CancelAfterInactivity(ctx, cancel, p.Timeouts.ConnectionIdle)

	requestFunc := func() error {
		defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
		return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
	}
	responseFunc := func() error {
		defer timer.SetTimeout(p.Timeouts.UplinkOnly)
		return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
	}

	var responseDonePost = task.OnSuccess(responseFunc, task.Close(link.Writer))
	if err := task.Run(ctx, requestFunc, responseDonePost); err != nil {
		return newError("connection ends").Base(err)
	}

	return nil
}

// setUpHttpTunnel will create a socket tunnel via HTTP CONNECT method
func setUpHttpTunnel(reader io.Reader, writer io.Writer, destination *net.Destination, user *protocol.MemoryUser) error {
	var headers []string
	destNetAddr := destination.NetAddr()
	headers = append(headers, "CONNECT "+destNetAddr+" HTTP/1.1")
	headers = append(headers, "Host: "+destNetAddr)
	if user != nil && user.Account != nil {
		account := user.Account.(*Account)
		auth := account.GetUsername() + ":" + account.GetPassword()
		headers = append(headers, "Proxy-Authorization: Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
	}
	headers = append(headers, "Proxy-Connection: Keep-Alive")

	b := buf.New()
	b.WriteString(strings.Join(headers, "\r\n") + "\r\n\r\n")
	if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
		return err
	}

	b.Clear()
	if _, err := b.ReadFrom(reader); err != nil {
		return err
	}

	return nil
}

func init() {
	common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return NewClient(ctx, config.(*ClientConfig))
	}))
}
<|endoftext|>


<commit_before>package kv

import (
	"fmt"
	"os"
	"path"
	"github.com/s3git/s3git-go/internal/config"
	mdb "github.com/szferi/gomdb"
	"encoding/hex"
)

var env *mdb.Env

// KV databases containing root level digests for different object types
// When a particular key is present, the value is as follows:
//   - when empty, underlying chunk(s) are not cached locally
//   - when set, it is the concatenation of the leaf level digests for all nodes
//     (and thus necessarily needs to correspond when BLAKE2'd to its key)
//
// If you know the type of the key, you can fetch it directly for the corresponding database
// If you do not know the type, you need to search all stores

var dbiLevel1Blobs mdb.DBI
var dbiLevel1Commits mdb.DBI
var dbiLevel1Prefixes mdb.DBI
var dbiLevel1Trees mdb.DBI

// KV database containing overview of added/removed blobs in stage
var dbiStage mdb.DBI

// KV database that marks commits objects as being a parent commit
var dbiLevel1CommitsIsParent mdb.DBI

func OpenDatabase() error {

	mdbDir := path.Join(config.Config.S3gitCasPath, ".mdb")
	err := os.MkdirAll(mdbDir, 0777)
	if err != nil {
		return err
	}

	env, _ = mdb.NewEnv()
	// TODO: Figure out proper size for lmdb
	env.SetMapSize(1 << 36) // max file size
	env.SetMaxDBs(10)		// up to 10 named databases
	env.Open(mdbDir, 0, 0664)
	txn, _ := env.BeginTxn(nil, 0)

	// overview of blobs in stage
	dbstage := "stage"
	dbiStage, _ = txn.DBIOpen(&dbstage, mdb.CREATE)

	// Level 1 databases
	dbl1blobs := "l1blobs"
	dbiLevel1Blobs, _ = txn.DBIOpen(&dbl1blobs, mdb.CREATE)
	dbl1commits := "l1commits"
	dbiLevel1Commits, _ = txn.DBIOpen(&dbl1commits, mdb.CREATE)
	dbl1prefixes := "l1prefixes"
	dbiLevel1Prefixes, _ = txn.DBIOpen(&dbl1prefixes, mdb.CREATE)
	dbl1trees := "l1trees"
	dbiLevel1Trees, _ = txn.DBIOpen(&dbl1trees, mdb.CREATE)

	// list of top most commits
	dbcommitsisparents := "l1commitsisparent"
	dbiLevel1CommitsIsParent, _ = txn.DBIOpen(&dbcommitsisparents, mdb.CREATE)

	txn.Commit()

	// TODO: Make sure all databases are flushed before exiting program
	//	defer env.DBIClose(dbi)
	//	defer env.Close()

	return nil
}

func AddToStage(key string) error {

	hx, _ := hex.DecodeString(key)

	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(dbiStage, hx, nil, 0)
	txn.Commit()

	return nil
}

func ClearStage() error {

	list, err := listMdb(&dbiStage, "")
	if err != nil {
		return err
	}

	txn, _ := env.BeginTxn(nil, 0)
	for k := range list {
		txn.Del(dbiStage, k, nil)
	}
	txn.Commit()

	return nil
}

func ListStage() (<-chan []byte, error) {

	return listMdb(&dbiStage, "")
}

func MarkCommitAsParent(key string) error {

	hx, _ := hex.DecodeString(key)

	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(dbiLevel1CommitsIsParent, hx, nil, 0)
	txn.Commit()

	return nil
}

func CommitIsParent(key []byte) (bool, error) {

	txn, _ := env.BeginTxn(nil, mdb.RDONLY)
	defer txn.Abort()

	_, err := txn.Get(dbiLevel1CommitsIsParent, key)
	if err != nil && !(err == mdb.NotFound) {
		return false, err
	} else if !(err == mdb.NotFound) {
		return true, err
	}

	return false, mdb.NotFound
}

func ListTopMostCommits() (<-chan []byte, error) {

	list, err := ListLevel1Commits()
	if err != nil {
		return nil, err
	}

	result := make(chan []byte)

	go func() {
		// make sure we always close the channel
		defer close(result)

		for l := range list {
			isParent, err := CommitIsParent(l)
			if err != nil && err != mdb.NotFound {
				return
			}

			if !isParent {	// In case this commit is not a parent --> output it as a top most commit
				result <- l
			}
		}
	}()

	return result, nil
}

func ListLevel1Commits() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Commits, "")
}

func ListLevel1Prefixes() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Prefixes, "")
}

func ListLevel1Trees() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Trees, "")
}

func ListLevel1Blobs(query string) (<-chan []byte, error) {

	return listMdb(&dbiLevel1Blobs, query)
}

// TODO: Remove duplicate definitions
const BLOB="blob"
const COMMIT="commit"
const PREFIX="prefix"
const TREE="tree"

func getDbForObjectType( objType string) *mdb.DBI {

	var dbi *mdb.DBI
	switch objType {
	case BLOB:
		dbi = &dbiLevel1Blobs
	case COMMIT:
		dbi = &dbiLevel1Commits
	case PREFIX:
		dbi = &dbiLevel1Prefixes
	case TREE:
		dbi = &dbiLevel1Trees
	default:
		panic(fmt.Sprintf("Bad type: %s", objType))
	}
	return dbi
}

func AddToLevel1(key, value []byte, objType string) error {

	dbi := getDbForObjectType(objType)
	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(*dbi, key, value, 0)
	txn.Commit()

	return nil
}

func AddMultiToLevel1(keys, values [][]byte, objType string) error {

	dbi := getDbForObjectType(objType)
	txn, _ := env.BeginTxn(nil, 0)
	for index, key := range keys {
		txn.Put(*dbi, key, values[index], 0)
	}
	txn.Commit()

	return nil
}

// Get object of any type, return value and type
func GetLevel1(key []byte) ([]byte, string, error) {

	txn, _ := env.BeginTxn(nil, mdb.RDONLY)
	defer txn.Abort()

	val, err := txn.Get(dbiLevel1Blobs, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, BLOB, err
	}

	val, err = txn.Get(dbiLevel1Commits, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, COMMIT, err
	}

	val, err = txn.Get(dbiLevel1Prefixes, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, PREFIX, err
	}

	val, err = txn.Get(dbiLevel1Trees, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, TREE, err
	}

	return nil, "", mdb.NotFound
}

func listMdb(dbi *mdb.DBI, query string) (<-chan []byte, error) {

	result := make(chan []byte)

	go func() {
		// make sure we always close the channel
		defer close(result)

		// scan the database
		txn, _ := env.BeginTxn(nil, mdb.RDONLY)
		defer txn.Abort()
		cursor, _ := txn.CursorOpen(*dbi)
		defer cursor.Close()

		setRangeUponStart := len(query) > 0
		var queryKey []byte
		if setRangeUponStart {
			q := query
			if len(q) % 2 == 1 {
				q = q + "0"
			}
			queryKey, _ = hex.DecodeString(q)
		}

		for {

			var bkey []byte
			if setRangeUponStart {
				bval, _, err := cursor.GetVal(queryKey, nil, mdb.SET_RANGE)
				if err == mdb.NotFound {
					break
				}
				if err != nil {
					// TODO: Log error
					return
				}

				bkey = bval.Bytes()

				setRangeUponStart = false
			} else {
				var err error
				bkey, _, err = cursor.Get(nil, nil, mdb.NEXT)
				if err == mdb.NotFound {
					break
				}
				if err != nil {
					// TODO: Log error
					return
				}

			}

			// break early if start of key is not longer
			if hex.EncodeToString(bkey)[:len(query)] != query {
				break
			}
			result <- bkey
		}

	}()

	return result, nil
}
<commit_msg>For Windows max KV size is capped at 32 bits -- investigate how to make larger<commit_after>package kv

import (
	"fmt"
	"os"
	"path"
	"github.com/s3git/s3git-go/internal/config"
	mdb "github.com/szferi/gomdb"
	"encoding/hex"
)

var env *mdb.Env

// KV databases containing root level digests for different object types
// When a particular key is present, the value is as follows:
//   - when empty, underlying chunk(s) are not cached locally
//   - when set, it is the concatenation of the leaf level digests for all nodes
//     (and thus necessarily needs to correspond when BLAKE2'd to its key)
//
// If you know the type of the key, you can fetch it directly for the corresponding database
// If you do not know the type, you need to search all stores

var dbiLevel1Blobs mdb.DBI
var dbiLevel1Commits mdb.DBI
var dbiLevel1Prefixes mdb.DBI
var dbiLevel1Trees mdb.DBI

// KV database containing overview of added/removed blobs in stage
var dbiStage mdb.DBI

// KV database that marks commits objects as being a parent commit
var dbiLevel1CommitsIsParent mdb.DBI

func OpenDatabase() error {

	mdbDir := path.Join(config.Config.S3gitCasPath, ".mdb")
	err := os.MkdirAll(mdbDir, 0777)
	if err != nil {
		return err
	}

	env, _ = mdb.NewEnv()
	// TODO: Figure out proper size for lmdb
	// TODO: Windows: max size is capped at 32
	env.SetMapSize(1 << 36) // max file size
	env.SetMaxDBs(10)		// up to 10 named databases
	env.Open(mdbDir, 0, 0664)
	txn, _ := env.BeginTxn(nil, 0)

	// overview of blobs in stage
	dbstage := "stage"
	dbiStage, _ = txn.DBIOpen(&dbstage, mdb.CREATE)

	// Level 1 databases
	dbl1blobs := "l1blobs"
	dbiLevel1Blobs, _ = txn.DBIOpen(&dbl1blobs, mdb.CREATE)
	dbl1commits := "l1commits"
	dbiLevel1Commits, _ = txn.DBIOpen(&dbl1commits, mdb.CREATE)
	dbl1prefixes := "l1prefixes"
	dbiLevel1Prefixes, _ = txn.DBIOpen(&dbl1prefixes, mdb.CREATE)
	dbl1trees := "l1trees"
	dbiLevel1Trees, _ = txn.DBIOpen(&dbl1trees, mdb.CREATE)

	// list of top most commits
	dbcommitsisparents := "l1commitsisparent"
	dbiLevel1CommitsIsParent, _ = txn.DBIOpen(&dbcommitsisparents, mdb.CREATE)

	txn.Commit()

	// TODO: Make sure all databases are flushed before exiting program
	//	defer env.DBIClose(dbi)
	//	defer env.Close()

	return nil
}

func AddToStage(key string) error {

	hx, _ := hex.DecodeString(key)

	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(dbiStage, hx, nil, 0)
	txn.Commit()

	return nil
}

func ClearStage() error {

	list, err := listMdb(&dbiStage, "")
	if err != nil {
		return err
	}

	txn, _ := env.BeginTxn(nil, 0)
	for k := range list {
		txn.Del(dbiStage, k, nil)
	}
	txn.Commit()

	return nil
}

func ListStage() (<-chan []byte, error) {

	return listMdb(&dbiStage, "")
}

func MarkCommitAsParent(key string) error {

	hx, _ := hex.DecodeString(key)

	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(dbiLevel1CommitsIsParent, hx, nil, 0)
	txn.Commit()

	return nil
}

func CommitIsParent(key []byte) (bool, error) {

	txn, _ := env.BeginTxn(nil, mdb.RDONLY)
	defer txn.Abort()

	_, err := txn.Get(dbiLevel1CommitsIsParent, key)
	if err != nil && !(err == mdb.NotFound) {
		return false, err
	} else if !(err == mdb.NotFound) {
		return true, err
	}

	return false, mdb.NotFound
}

func ListTopMostCommits() (<-chan []byte, error) {

	list, err := ListLevel1Commits()
	if err != nil {
		return nil, err
	}

	result := make(chan []byte)

	go func() {
		// make sure we always close the channel
		defer close(result)

		for l := range list {
			isParent, err := CommitIsParent(l)
			if err != nil && err != mdb.NotFound {
				return
			}

			if !isParent {	// In case this commit is not a parent --> output it as a top most commit
				result <- l
			}
		}
	}()

	return result, nil
}

func ListLevel1Commits() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Commits, "")
}

func ListLevel1Prefixes() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Prefixes, "")
}

func ListLevel1Trees() (<-chan []byte, error) {

	return listMdb(&dbiLevel1Trees, "")
}

func ListLevel1Blobs(query string) (<-chan []byte, error) {

	return listMdb(&dbiLevel1Blobs, query)
}

// TODO: Remove duplicate definitions
const BLOB="blob"
const COMMIT="commit"
const PREFIX="prefix"
const TREE="tree"

func getDbForObjectType( objType string) *mdb.DBI {

	var dbi *mdb.DBI
	switch objType {
	case BLOB:
		dbi = &dbiLevel1Blobs
	case COMMIT:
		dbi = &dbiLevel1Commits
	case PREFIX:
		dbi = &dbiLevel1Prefixes
	case TREE:
		dbi = &dbiLevel1Trees
	default:
		panic(fmt.Sprintf("Bad type: %s", objType))
	}
	return dbi
}

func AddToLevel1(key, value []byte, objType string) error {

	dbi := getDbForObjectType(objType)
	txn, _ := env.BeginTxn(nil, 0)
	txn.Put(*dbi, key, value, 0)
	txn.Commit()

	return nil
}

func AddMultiToLevel1(keys, values [][]byte, objType string) error {

	dbi := getDbForObjectType(objType)
	txn, _ := env.BeginTxn(nil, 0)
	for index, key := range keys {
		txn.Put(*dbi, key, values[index], 0)
	}
	txn.Commit()

	return nil
}

// Get object of any type, return value and type
func GetLevel1(key []byte) ([]byte, string, error) {

	txn, _ := env.BeginTxn(nil, mdb.RDONLY)
	defer txn.Abort()

	val, err := txn.Get(dbiLevel1Blobs, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, BLOB, err
	}

	val, err = txn.Get(dbiLevel1Commits, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, COMMIT, err
	}

	val, err = txn.Get(dbiLevel1Prefixes, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, PREFIX, err
	}

	val, err = txn.Get(dbiLevel1Trees, key)
	if err != nil && !(err == mdb.NotFound) {
		return nil, "", err
	} else if !(err == mdb.NotFound) {
		return val, TREE, err
	}

	return nil, "", mdb.NotFound
}

func listMdb(dbi *mdb.DBI, query string) (<-chan []byte, error) {

	result := make(chan []byte)

	go func() {
		// make sure we always close the channel
		defer close(result)

		// scan the database
		txn, _ := env.BeginTxn(nil, mdb.RDONLY)
		defer txn.Abort()
		cursor, _ := txn.CursorOpen(*dbi)
		defer cursor.Close()

		setRangeUponStart := len(query) > 0
		var queryKey []byte
		if setRangeUponStart {
			q := query
			if len(q) % 2 == 1 {
				q = q + "0"
			}
			queryKey, _ = hex.DecodeString(q)
		}

		for {

			var bkey []byte
			if setRangeUponStart {
				bval, _, err := cursor.GetVal(queryKey, nil, mdb.SET_RANGE)
				if err == mdb.NotFound {
					break
				}
				if err != nil {
					// TODO: Log error
					return
				}

				bkey = bval.Bytes()

				setRangeUponStart = false
			} else {
				var err error
				bkey, _, err = cursor.Get(nil, nil, mdb.NEXT)
				if err == mdb.NotFound {
					break
				}
				if err != nil {
					// TODO: Log error
					return
				}

			}

			// break early if start of key is not longer
			if hex.EncodeToString(bkey)[:len(query)] != query {
				break
			}
			result <- bkey
		}

	}()

	return result, nil
}
<|endoftext|>


<commit_before>package containerdrunner

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

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

type Config struct {
	Root            string      `toml:"root"`
	State           string      `toml:"state"`
	Subreaper       bool        `toml:"subreaper"`
	OomScore        int         `toml:"oom_score"`
	GRPC            GRPCConfig  `toml:"grpc"`
	Debug           DebugConfig `toml:"debug"`
	DisabledPlugins []string    `toml:"disabled_plugins"`
	Plugins         Plugins     `toml:"plugins"`

	RunDir string
}

type GRPCConfig struct {
	Address string `toml:"address"`
}

type DebugConfig struct {
	Address string `toml:"address"`
	Level   string `toml:"level"`
}

type Plugins struct {
	Linux Linux `toml:"linux"`
}

type Linux struct {
	ShimDebug bool `toml:"shim_debug"`
}

func ContainerdConfig(containerdDataDir string) Config {
	return Config{
		Root:      filepath.Join(containerdDataDir, "root"),
		State:     filepath.Join(containerdDataDir, "state"),
		Subreaper: true,
		OomScore:  -999,
		GRPC: GRPCConfig{
			Address: filepath.Join(containerdDataDir, "containerd.sock"),
		},
		Debug: DebugConfig{
			Address: filepath.Join(containerdDataDir, "debug.sock"),
			Level:   "debug",
		},
		DisabledPlugins: []string{
			"aufs",
			"overlayfs",
			"zfs",
			"walking",
			"scheduler",
			"content-service",
			"diff-service",
			"images-service",
			"namespaces-service",
			"snapshots-service",
			"content",
			"diff",
			"healthcheck",
			"images",
			"namespaces",
			"snapshots",
			"version",
			"cri",
			"leases",
			"leases-service",
			"restart",
		},
		Plugins: Plugins{
			Linux: Linux{
				ShimDebug: true,
			},
		},
	}
}

func NewContainerdProcess(runDir string, config Config) *os.Process {
	configFile, err := os.OpenFile(filepath.Join(runDir, "containerd.toml"), os.O_TRUNC|os.O_WRONLY|os.O_CREATE, os.ModePerm)
	Expect(err).NotTo(HaveOccurred())
	Expect(toml.NewEncoder(configFile).Encode(&config)).To(Succeed())
	Expect(configFile.Close()).To(Succeed())

	cmd := exec.Command("containerd", "--config", configFile.Name())
	cmd.Env = append(os.Environ(), fmt.Sprintf("PATH=%s", fmt.Sprintf("%s:%s", os.Getenv("PATH"), "/usr/local/bin")))
	cmd.Stdout = GinkgoWriter
	cmd.Stderr = GinkgoWriter
	Expect(cmd.Start()).To(Succeed())
	return cmd.Process
}
<commit_msg>Wait for containerd socket in GQTs<commit_after>package containerdrunner

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"time"

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

type Config struct {
	Root            string      `toml:"root"`
	State           string      `toml:"state"`
	Subreaper       bool        `toml:"subreaper"`
	OomScore        int         `toml:"oom_score"`
	GRPC            GRPCConfig  `toml:"grpc"`
	Debug           DebugConfig `toml:"debug"`
	DisabledPlugins []string    `toml:"disabled_plugins"`
	Plugins         Plugins     `toml:"plugins"`

	RunDir string
}

type GRPCConfig struct {
	Address string `toml:"address"`
}

type DebugConfig struct {
	Address string `toml:"address"`
	Level   string `toml:"level"`
}

type Plugins struct {
	Linux Linux `toml:"linux"`
}

type Linux struct {
	ShimDebug bool `toml:"shim_debug"`
}

func ContainerdConfig(containerdDataDir string) Config {
	return Config{
		Root:      filepath.Join(containerdDataDir, "root"),
		State:     filepath.Join(containerdDataDir, "state"),
		Subreaper: true,
		OomScore:  -999,
		GRPC: GRPCConfig{
			Address: filepath.Join(containerdDataDir, "containerd.sock"),
		},
		Debug: DebugConfig{
			Address: filepath.Join(containerdDataDir, "debug.sock"),
			Level:   "debug",
		},
		DisabledPlugins: []string{
			"aufs",
			"overlayfs",
			"zfs",
			"walking",
			"scheduler",
			"content-service",
			"diff-service",
			"images-service",
			"namespaces-service",
			"snapshots-service",
			"content",
			"diff",
			"healthcheck",
			"images",
			"namespaces",
			"snapshots",
			"version",
			"cri",
			"leases",
			"leases-service",
			"restart",
		},
		Plugins: Plugins{
			Linux: Linux{
				ShimDebug: true,
			},
		},
	}
}

func NewContainerdProcess(runDir string, config Config) *os.Process {
	configFile, err := os.OpenFile(filepath.Join(runDir, "containerd.toml"), os.O_TRUNC|os.O_WRONLY|os.O_CREATE, os.ModePerm)
	Expect(err).NotTo(HaveOccurred())
	Expect(toml.NewEncoder(configFile).Encode(&config)).To(Succeed())
	Expect(configFile.Close()).To(Succeed())

	cmd := exec.Command("containerd", "--config", configFile.Name())
	cmd.Env = append(os.Environ(), fmt.Sprintf("PATH=%s", fmt.Sprintf("%s:%s", os.Getenv("PATH"), "/usr/local/bin")))
	cmd.Stdout = GinkgoWriter
	cmd.Stderr = GinkgoWriter
	Expect(cmd.Start()).To(Succeed())
	Eventually(func() error { return ping(config) }, time.Minute).Should(Succeed(), "containerd is taking too long to make socket available")
	return cmd.Process
}

func ping(config Config) error {
	_, err := net.Dial("unix", config.GRPC.Address)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2010 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.

package suffixarray

import (
	"bytes"
	"exp/regexp"
	"rand"
	"sort"
	"strings"
	"testing"
)

type testCase struct {
	name     string   // name of test case
	source   string   // source to index
	patterns []string // patterns to lookup
}

var testCases = []testCase{
	{
		"empty string",
		"",
		[]string{
			"",
			"foo",
			"(foo)",
			".*",
			"a*",
		},
	},

	{
		"all a's",
		"aaaaaaaaaa", // 10 a's
		[]string{
			"",
			"a",
			"aa",
			"aaa",
			"aaaa",
			"aaaaa",
			"aaaaaa",
			"aaaaaaa",
			"aaaaaaaa",
			"aaaaaaaaa",
			"aaaaaaaaaa",
			"aaaaaaaaaaa", // 11 a's
			".",
			".*",
			"a+",
			"aa+",
			"aaaa[b]?",
			"aaa*",
		},
	},

	{
		"abc",
		"abc",
		[]string{
			"a",
			"b",
			"c",
			"ab",
			"bc",
			"abc",
			"a.c",
			"a(b|c)",
			"abc?",
		},
	},

	{
		"barbara*3",
		"barbarabarbarabarbara",
		[]string{
			"a",
			"bar",
			"rab",
			"arab",
			"barbar",
			"bara?bar",
		},
	},

	{
		"typing drill",
		"Now is the time for all good men to come to the aid of their country.",
		[]string{
			"Now",
			"the time",
			"to come the aid",
			"is the time for all good men to come to the aid of their",
			"to (come|the)?",
		},
	},

	{
		"godoc simulation",
		"package main\n\nimport(\n    \"rand\"\n    ",
		[]string{},
	},
}

// find all occurrences of s in source; report at most n occurrences
func find(src, s string, n int) []int {
	var res []int
	if s != "" && n != 0 {
		// find at most n occurrences of s in src
		for i := -1; n < 0 || len(res) < n; {
			j := strings.Index(src[i+1:], s)
			if j < 0 {
				break
			}
			i += j + 1
			res = append(res, i)
		}
	}
	return res
}

func testLookup(t *testing.T, tc *testCase, x *Index, s string, n int) {
	res := x.Lookup([]byte(s), n)
	exp := find(tc.source, s, n)

	// check that the lengths match
	if len(res) != len(exp) {
		t.Errorf("test %q, lookup %q (n = %d): expected %d results; got %d", tc.name, s, n, len(exp), len(res))
	}

	// if n >= 0 the number of results is limited --- unless n >= all results,
	// we may obtain different positions from the Index and from find (because
	// Index may not find the results in the same order as find) => in general
	// we cannot simply check that the res and exp lists are equal

	// check that each result is in fact a correct match and there are no duplicates
	sort.Ints(res)
	for i, r := range res {
		if r < 0 || len(tc.source) <= r {
			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d out of range [0, %d[", tc.name, s, i, n, r, len(tc.source))
		} else if !strings.HasPrefix(tc.source[r:], s) {
			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d not a match", tc.name, s, i, n, r)
		}
		if i > 0 && res[i-1] == r {
			t.Errorf("test %q, lookup %q, result %d (n = %d): found duplicate index %d", tc.name, s, i, n, r)
		}
	}

	if n < 0 {
		// all results computed - sorted res and exp must be equal
		for i, r := range res {
			e := exp[i]
			if r != e {
				t.Errorf("test %q, lookup %q, result %d: expected index %d; got %d", tc.name, s, i, e, r)
			}
		}
	}
}

func testFindAllIndex(t *testing.T, tc *testCase, x *Index, rx *regexp.Regexp, n int) {
	res := x.FindAllIndex(rx, n)
	exp := rx.FindAllStringIndex(tc.source, n)

	// check that the lengths match
	if len(res) != len(exp) {
		t.Errorf("test %q, FindAllIndex %q (n = %d): expected %d results; got %d", tc.name, rx, n, len(exp), len(res))
	}

	// if n >= 0 the number of results is limited --- unless n >= all results,
	// we may obtain different positions from the Index and from regexp (because
	// Index may not find the results in the same order as regexp) => in general
	// we cannot simply check that the res and exp lists are equal

	// check that each result is in fact a correct match and the result is sorted
	for i, r := range res {
		if r[0] < 0 || r[0] > r[1] || len(tc.source) < r[1] {
			t.Errorf("test %q, FindAllIndex %q, result %d (n == %d): illegal match [%d, %d]", tc.name, rx, i, n, r[0], r[1])
		} else if !rx.MatchString(tc.source[r[0]:r[1]]) {
			t.Errorf("test %q, FindAllIndex %q, result %d (n = %d): [%d, %d] not a match", tc.name, rx, i, n, r[0], r[1])
		}
	}

	if n < 0 {
		// all results computed - sorted res and exp must be equal
		for i, r := range res {
			e := exp[i]
			if r[0] != e[0] || r[1] != e[1] {
				t.Errorf("test %q, FindAllIndex %q, result %d: expected match [%d, %d]; got [%d, %d]",
					tc.name, rx, i, e[0], e[1], r[0], r[1])
			}
		}
	}
}

func testLookups(t *testing.T, tc *testCase, x *Index, n int) {
	for _, pat := range tc.patterns {
		testLookup(t, tc, x, pat, n)
		if rx, err := regexp.Compile(pat); err == nil {
			testFindAllIndex(t, tc, x, rx, n)
		}
	}
}

// index is used to hide the sort.Interface
type index Index

func (x *index) Len() int           { return len(x.sa) }
func (x *index) Less(i, j int) bool { return bytes.Compare(x.at(i), x.at(j)) < 0 }
func (x *index) Swap(i, j int)      { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
func (a *index) at(i int) []byte    { return a.data[a.sa[i]:] }

func testConstruction(t *testing.T, tc *testCase, x *Index) {
	if !sort.IsSorted((*index)(x)) {
		t.Errorf("failed testConstruction %s", tc.name)
	}
}

func equal(x, y *Index) bool {
	if !bytes.Equal(x.data, y.data) {
		return false
	}
	for i, j := range x.sa {
		if j != y.sa[i] {
			return false
		}
	}
	return true
}

func testSaveRestore(t *testing.T, tc *testCase, x *Index) {
	var buf bytes.Buffer
	if err := x.Write(&buf); err != nil {
		t.Errorf("failed writing index %s (%s)", tc.name, err)
	}
	var y Index
	if err := y.Read(&buf); err != nil {
		t.Errorf("failed reading index %s (%s)", tc.name, err)
	}
	if !equal(x, &y) {
		t.Errorf("restored index doesn't match saved index %s", tc.name)
	}
}

func TestIndex(t *testing.T) {
	for _, tc := range testCases {
		x := New([]byte(tc.source))
		testConstruction(t, &tc, x)
		testSaveRestore(t, &tc, x)
		testLookups(t, &tc, x, 0)
		testLookups(t, &tc, x, 1)
		testLookups(t, &tc, x, 10)
		testLookups(t, &tc, x, 2e9)
		testLookups(t, &tc, x, -1)
	}
}

func BenchmarkSaveRestore(b *testing.B) {
	b.StopTimer()
	r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
	data := make([]byte, 10<<20)            // 10MB index data
	for i := range data {
		data[i] = byte(r.Intn(256))
	}
	x := New(data)
	testSaveRestore(nil, nil, x)                    // verify correctness
	buf := bytes.NewBuffer(make([]byte, len(data))) // avoid frequent growing
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x.Write(buf)
		var y Index
		y.Read(buf)
	}
}
<commit_msg>suffixarray: add benchmarks for construction<commit_after>// Copyright 2010 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.

package suffixarray

import (
	"bytes"
	"exp/regexp"
	"rand"
	"sort"
	"strings"
	"testing"
)

type testCase struct {
	name     string   // name of test case
	source   string   // source to index
	patterns []string // patterns to lookup
}

var testCases = []testCase{
	{
		"empty string",
		"",
		[]string{
			"",
			"foo",
			"(foo)",
			".*",
			"a*",
		},
	},

	{
		"all a's",
		"aaaaaaaaaa", // 10 a's
		[]string{
			"",
			"a",
			"aa",
			"aaa",
			"aaaa",
			"aaaaa",
			"aaaaaa",
			"aaaaaaa",
			"aaaaaaaa",
			"aaaaaaaaa",
			"aaaaaaaaaa",
			"aaaaaaaaaaa", // 11 a's
			".",
			".*",
			"a+",
			"aa+",
			"aaaa[b]?",
			"aaa*",
		},
	},

	{
		"abc",
		"abc",
		[]string{
			"a",
			"b",
			"c",
			"ab",
			"bc",
			"abc",
			"a.c",
			"a(b|c)",
			"abc?",
		},
	},

	{
		"barbara*3",
		"barbarabarbarabarbara",
		[]string{
			"a",
			"bar",
			"rab",
			"arab",
			"barbar",
			"bara?bar",
		},
	},

	{
		"typing drill",
		"Now is the time for all good men to come to the aid of their country.",
		[]string{
			"Now",
			"the time",
			"to come the aid",
			"is the time for all good men to come to the aid of their",
			"to (come|the)?",
		},
	},

	{
		"godoc simulation",
		"package main\n\nimport(\n    \"rand\"\n    ",
		[]string{},
	},
}

// find all occurrences of s in source; report at most n occurrences
func find(src, s string, n int) []int {
	var res []int
	if s != "" && n != 0 {
		// find at most n occurrences of s in src
		for i := -1; n < 0 || len(res) < n; {
			j := strings.Index(src[i+1:], s)
			if j < 0 {
				break
			}
			i += j + 1
			res = append(res, i)
		}
	}
	return res
}

func testLookup(t *testing.T, tc *testCase, x *Index, s string, n int) {
	res := x.Lookup([]byte(s), n)
	exp := find(tc.source, s, n)

	// check that the lengths match
	if len(res) != len(exp) {
		t.Errorf("test %q, lookup %q (n = %d): expected %d results; got %d", tc.name, s, n, len(exp), len(res))
	}

	// if n >= 0 the number of results is limited --- unless n >= all results,
	// we may obtain different positions from the Index and from find (because
	// Index may not find the results in the same order as find) => in general
	// we cannot simply check that the res and exp lists are equal

	// check that each result is in fact a correct match and there are no duplicates
	sort.Ints(res)
	for i, r := range res {
		if r < 0 || len(tc.source) <= r {
			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d out of range [0, %d[", tc.name, s, i, n, r, len(tc.source))
		} else if !strings.HasPrefix(tc.source[r:], s) {
			t.Errorf("test %q, lookup %q, result %d (n = %d): index %d not a match", tc.name, s, i, n, r)
		}
		if i > 0 && res[i-1] == r {
			t.Errorf("test %q, lookup %q, result %d (n = %d): found duplicate index %d", tc.name, s, i, n, r)
		}
	}

	if n < 0 {
		// all results computed - sorted res and exp must be equal
		for i, r := range res {
			e := exp[i]
			if r != e {
				t.Errorf("test %q, lookup %q, result %d: expected index %d; got %d", tc.name, s, i, e, r)
			}
		}
	}
}

func testFindAllIndex(t *testing.T, tc *testCase, x *Index, rx *regexp.Regexp, n int) {
	res := x.FindAllIndex(rx, n)
	exp := rx.FindAllStringIndex(tc.source, n)

	// check that the lengths match
	if len(res) != len(exp) {
		t.Errorf("test %q, FindAllIndex %q (n = %d): expected %d results; got %d", tc.name, rx, n, len(exp), len(res))
	}

	// if n >= 0 the number of results is limited --- unless n >= all results,
	// we may obtain different positions from the Index and from regexp (because
	// Index may not find the results in the same order as regexp) => in general
	// we cannot simply check that the res and exp lists are equal

	// check that each result is in fact a correct match and the result is sorted
	for i, r := range res {
		if r[0] < 0 || r[0] > r[1] || len(tc.source) < r[1] {
			t.Errorf("test %q, FindAllIndex %q, result %d (n == %d): illegal match [%d, %d]", tc.name, rx, i, n, r[0], r[1])
		} else if !rx.MatchString(tc.source[r[0]:r[1]]) {
			t.Errorf("test %q, FindAllIndex %q, result %d (n = %d): [%d, %d] not a match", tc.name, rx, i, n, r[0], r[1])
		}
	}

	if n < 0 {
		// all results computed - sorted res and exp must be equal
		for i, r := range res {
			e := exp[i]
			if r[0] != e[0] || r[1] != e[1] {
				t.Errorf("test %q, FindAllIndex %q, result %d: expected match [%d, %d]; got [%d, %d]",
					tc.name, rx, i, e[0], e[1], r[0], r[1])
			}
		}
	}
}

func testLookups(t *testing.T, tc *testCase, x *Index, n int) {
	for _, pat := range tc.patterns {
		testLookup(t, tc, x, pat, n)
		if rx, err := regexp.Compile(pat); err == nil {
			testFindAllIndex(t, tc, x, rx, n)
		}
	}
}

// index is used to hide the sort.Interface
type index Index

func (x *index) Len() int           { return len(x.sa) }
func (x *index) Less(i, j int) bool { return bytes.Compare(x.at(i), x.at(j)) < 0 }
func (x *index) Swap(i, j int)      { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
func (a *index) at(i int) []byte    { return a.data[a.sa[i]:] }

func testConstruction(t *testing.T, tc *testCase, x *Index) {
	if !sort.IsSorted((*index)(x)) {
		t.Errorf("failed testConstruction %s", tc.name)
	}
}

func equal(x, y *Index) bool {
	if !bytes.Equal(x.data, y.data) {
		return false
	}
	for i, j := range x.sa {
		if j != y.sa[i] {
			return false
		}
	}
	return true
}

func testSaveRestore(t *testing.T, tc *testCase, x *Index) {
	var buf bytes.Buffer
	if err := x.Write(&buf); err != nil {
		t.Errorf("failed writing index %s (%s)", tc.name, err)
	}
	var y Index
	if err := y.Read(&buf); err != nil {
		t.Errorf("failed reading index %s (%s)", tc.name, err)
	}
	if !equal(x, &y) {
		t.Errorf("restored index doesn't match saved index %s", tc.name)
	}
}

func TestIndex(t *testing.T) {
	for _, tc := range testCases {
		x := New([]byte(tc.source))
		testConstruction(t, &tc, x)
		testSaveRestore(t, &tc, x)
		testLookups(t, &tc, x, 0)
		testLookups(t, &tc, x, 1)
		testLookups(t, &tc, x, 10)
		testLookups(t, &tc, x, 2e9)
		testLookups(t, &tc, x, -1)
	}
}

// Of all possible inputs, the random bytes have the least amount of substring
// repetition, and the repeated bytes have the most. For most algorithms,
// the running time of every input will be between these two.
func benchmarkNew(b *testing.B, random bool) {
	b.StopTimer()
	data := make([]byte, 1e6)
	if random {
		for i := range data {
			data[i] = byte(rand.Intn(256))
		}
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		New(data)
	}
}

func BenchmarkNewIndexRandom(b *testing.B) {
	benchmarkNew(b, true)
}
func BenchmarkNewIndexRepeat(b *testing.B) {
	benchmarkNew(b, false)
}

func BenchmarkSaveRestore(b *testing.B) {
	b.StopTimer()
	r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
	data := make([]byte, 10<<20)            // 10MB index data
	for i := range data {
		data[i] = byte(r.Intn(256))
	}
	x := New(data)
	testSaveRestore(nil, nil, x)                    // verify correctness
	buf := bytes.NewBuffer(make([]byte, len(data))) // avoid frequent growing
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x.Write(buf)
		var y Index
		y.Read(buf)
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced 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 nfs

import (
	"fmt"
	"os/exec"

	"github.com/control-center/serviced/utils"
	"github.com/zenoss/glog"
)

var nfsServiceName = determineNfsServiceName()
var usrBinService = determineServiceCommand()

var start = startImpl
var reload = reloadImpl
var restart = restartImpl
var stop = stopImpl

func determineServiceCommand() string {
	if utils.Platform == utils.Rhel {
		return "systemctl"
	} else {
		return "/usr/sbin/service"
	}
}

func determineNfsServiceName() string {
	// In RHEL-based releases, the 'nfs-server' service is used
	if utils.Platform == utils.Rhel {
		return "nfs-server"
	} else {
		return "nfs-kernel-server"
	}
}

// reload triggers the kernel to reread its NFS exports.
func reloadImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "reload", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "reload")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	return nil
}

func startImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "reload-or-restart", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "start")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("started nfs server: %s", string(output))
	return nil
}

func restartImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "restart", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "restart")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("started nfs server: %s", string(output))
	return nil
}

func stopImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "stop", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "stop")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("stopped nfs server: %s", string(output))
	return nil
}
<commit_msg>clarify nfs-related logging<commit_after>// Copyright 2014 The Serviced 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 nfs

import (
	"fmt"
	"os/exec"

	"github.com/control-center/serviced/utils"
	"github.com/zenoss/glog"
)

var nfsServiceName = determineNfsServiceName()
var usrBinService = determineServiceCommand()

var start = startImpl
var reload = reloadImpl
var restart = restartImpl
var stop = stopImpl

func determineServiceCommand() string {
	if utils.Platform == utils.Rhel {
		return "systemctl"
	} else {
		return "/usr/sbin/service"
	}
}

func determineNfsServiceName() string {
	// In RHEL-based releases, the 'nfs-server' service is used
	if utils.Platform == utils.Rhel {
		return "nfs-server"
	} else {
		return "nfs-kernel-server"
	}
}

// reload triggers the kernel to reread its NFS exports.
func reloadImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "reload", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "reload")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("reloaded nfs server: %s", string(output))
	return nil
}

func startImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "reload-or-restart", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "start")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("started nfs server: %s", string(output))
	return nil
}

func restartImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "restart", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "restart")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("restarted nfs server: %s", string(output))
	return nil
}

func stopImpl() error {
	// FIXME: this does not return the proper exit code to see if nfs is running
	var cmd *exec.Cmd
	if utils.Platform == utils.Rhel {
		cmd = exec.Command(usrBinService, "stop", nfsServiceName)
	} else {
		cmd = exec.Command(usrBinService, nfsServiceName, "stop")
	}
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s: %s", err, string(output))
	}
	glog.Infof("stopped nfs server: %s", string(output))
	return nil
}
<|endoftext|>


<commit_before>package jenkins

import "encoding/xml"

type Config struct {
	RAW                              string        `xml:"-"`
	XMLName                          xml.Name      `xml:"project"`
	KeepDependencies                 bool          `xml:"keepDependencies"`
	Properties                       []interface{} `xml:"properties>ignored"`
	Scm                              interface{}   `xml:"scm"`
	CanRoam                          bool          `xml:"canRoam"`                          // true</canRoam>
	Disabled                         bool          `xml:"disabled"`                         // false</disabled>
	BlockBuildWhenDownstreamBuilding bool          `xml:"blockBuildWhenDownstreamBuilding"` // false</blockBuildWhenDownstreamBuilding>
	BlockBuildWhenUpstreamBuilding   bool          `xml:"blockBuildWhenUpstreamBuilding"`   // false</blockBuildWhenUpstreamBuilding>
	ConcurrentBuild                  bool          `xml:"concurrentBuild"`
	//Triggers                         []interface{} `xml:"triggers>trigger"`
	// Builders                         []interface{}   `xml:"builders>builder"`
	SCMTrigger     []*SCMTrigger   `xml:"triggers>hudson.triggers.SCMTrigger"`
	ShellBuilders  []*ShellBuilder `xml:"builders>hudson.tasks.Shell"`
	AssignedToNode string          `xml:"assignedNode,omitempty"`
	Publishers     []interface{}   `xml:"publishers>ignored"`
	LogRotator     *LogRotator     `xml:"logRotator,omitempty"`
}

type ShellBuilder struct {
	Command string `xml:"command"`
}

type LogRotator struct {
	Class              string `xml:"class,attr"`
	DaysToKeep         int    `xml:"daysToKeep"`
	NumToKeep          int    `xml:"numToKeep"`
	ArtifactDaysToKeep int    `xml:"artifactDaysToKeep"`
	ArtifactNumToKeep  int    `xml:"artifactNumToKeep"`
}

func NewLogRotator(n int) *LogRotator {
	return &LogRotator{
		Class:              "hudson.tasks.LogRotator",
		DaysToKeep:         -1,
		NumToKeep:          n,
		ArtifactDaysToKeep: -1,
		ArtifactNumToKeep:  -1,
	}
}

type Builders struct {
	Tasks []interface{} `xml:""`
}

type ShellTask struct {
	XMLName xml.Name `xml:"hudson.tasks.Shell"`
	Command string   `xml:"command"`
}

type TimerTrigger struct {
	XMLName xml.Name `xml:"hudson.triggers.TimerTrigger"`
	Spec    string   `xml:"spec"`
}

func NullScm() *Scm {
	return &Scm{Class: "hudson.scm.NullSCM"}
}

type SCMTrigger struct {
	XMLName xml.Name `xml:"hudson.triggers.SCMTrigger"`
}

type Scm struct {
	Class         string `xml:"class,attr"`
	Plugin        string `xml:"plugin,attr,omitempty"`
	ConfigVersion int    `xml:"configVersion,omitempty"`
}
<commit_msg>add TimeTrigger<commit_after>package jenkins

import "encoding/xml"

type Config struct {
	RAW                              string        `xml:"-"`
	XMLName                          xml.Name      `xml:"project"`
	KeepDependencies                 bool          `xml:"keepDependencies"`
	Properties                       []interface{} `xml:"properties>ignored"`
	Scm                              interface{}   `xml:"scm"`
	CanRoam                          bool          `xml:"canRoam"`                          // true</canRoam>
	Disabled                         bool          `xml:"disabled"`                         // false</disabled>
	BlockBuildWhenDownstreamBuilding bool          `xml:"blockBuildWhenDownstreamBuilding"` // false</blockBuildWhenDownstreamBuilding>
	BlockBuildWhenUpstreamBuilding   bool          `xml:"blockBuildWhenUpstreamBuilding"`   // false</blockBuildWhenUpstreamBuilding>
	ConcurrentBuild                  bool          `xml:"concurrentBuild"`
	//Triggers                         []interface{} `xml:"triggers>trigger"`
	// Builders                         []interface{}   `xml:"builders>builder"`
	SCMTrigger     []*SCMTrigger   `xml:"triggers>hudson.triggers.SCMTrigger"`
	ShellBuilders  []*ShellBuilder `xml:"builders>hudson.tasks.Shell"`
	TimerTriggers  []*TimerTrigger `xml:"triggers>hudson.triggers.TimerTrigger"`
	AssignedToNode string          `xml:"assignedNode,omitempty"`
	Publishers     []interface{}   `xml:"publishers>ignored"`
	LogRotator     *LogRotator     `xml:"logRotator,omitempty"`
}

type ShellBuilder struct {
	Command string `xml:"command"`
}

type LogRotator struct {
	Class              string `xml:"class,attr"`
	DaysToKeep         int    `xml:"daysToKeep"`
	NumToKeep          int    `xml:"numToKeep"`
	ArtifactDaysToKeep int    `xml:"artifactDaysToKeep"`
	ArtifactNumToKeep  int    `xml:"artifactNumToKeep"`
}

func NewLogRotator(n int) *LogRotator {
	return &LogRotator{
		Class:              "hudson.tasks.LogRotator",
		DaysToKeep:         -1,
		NumToKeep:          n,
		ArtifactDaysToKeep: -1,
		ArtifactNumToKeep:  -1,
	}
}

type Builders struct {
	Tasks []interface{} `xml:""`
}

type ShellTask struct {
	XMLName xml.Name `xml:"hudson.tasks.Shell"`
	Command string   `xml:"command"`
}

type TimerTrigger struct {
	XMLName xml.Name `xml:"hudson.triggers.TimerTrigger"`
	Spec    string   `xml:"spec"`
}

func NullScm() *Scm {
	return &Scm{Class: "hudson.scm.NullSCM"}
}

type SCMTrigger struct {
	XMLName xml.Name `xml:"hudson.triggers.SCMTrigger"`
}

type Scm struct {
	Class         string `xml:"class,attr"`
	Plugin        string `xml:"plugin,attr,omitempty"`
	ConfigVersion int    `xml:"configVersion,omitempty"`
}
<|endoftext|>


<commit_before>// Copyright 2021 The Ebiten 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 oboe

// Disable AAudio (#1634).
// AAudio doesn't care about plugging in/out of a headphone.
// See https://github.com/google/oboe/blob/master/docs/notes/disconnect.md

// #cgo CXXFLAGS: -std=c++17 -DOBOE_ENABLE_AAUDIO=0
// #cgo LDFLAGS: -llog -lOpenSLES -static-libstdc++
//
// #include "binding_android.h"
import "C"

import (
	"fmt"
	"reflect"
	"unsafe"
)

var theReadFunc func(buf []float32)

func Play(sampleRate, channelNum, bitDepthInBytes int, readFunc func(buf []float32)) error {
	// Play can invoke the callback. Set the callback before Play.
	theReadFunc = readFunc
	if msg := C.ebiten_oboe_Play(C.int(sampleRate), C.int(channelNum), C.int(bitDepthInBytes)); msg != nil {
		return fmt.Errorf("oboe: Play failed: %s", C.GoString(msg))
	}
	return nil
}

func Suspend() error {
	if msg := C.ebiten_oboe_Suspend(); msg != nil {
		return fmt.Errorf("oboe: Suspend failed: %s", C.GoString(msg))
	}
	return nil
}

func Resume() error {
	if msg := C.ebiten_oboe_Resume(); msg != nil {
		return fmt.Errorf("oboe: Resume failed: %s", C.GoString(msg))
	}
	return nil
}

//export ebiten_oboe_read
func ebiten_oboe_read(buf *C.float, len C.size_t) {
	s := []float32{}
	h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
	h.Data = uintptr(unsafe.Pointer(buf))
	h.Len = int(len)
	h.Cap = int(len)
	for i := range s {
		s[i] = 0
	}
	theReadFunc(s)
}
<commit_msg>audio/internal/oboe: Nil slice should be safe to convert to reflect.SliceHeader<commit_after>// Copyright 2021 The Ebiten 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 oboe

// Disable AAudio (#1634).
// AAudio doesn't care about plugging in/out of a headphone.
// See https://github.com/google/oboe/blob/master/docs/notes/disconnect.md

// #cgo CXXFLAGS: -std=c++17 -DOBOE_ENABLE_AAUDIO=0
// #cgo LDFLAGS: -llog -lOpenSLES -static-libstdc++
//
// #include "binding_android.h"
import "C"

import (
	"fmt"
	"reflect"
	"unsafe"
)

var theReadFunc func(buf []float32)

func Play(sampleRate, channelNum, bitDepthInBytes int, readFunc func(buf []float32)) error {
	// Play can invoke the callback. Set the callback before Play.
	theReadFunc = readFunc
	if msg := C.ebiten_oboe_Play(C.int(sampleRate), C.int(channelNum), C.int(bitDepthInBytes)); msg != nil {
		return fmt.Errorf("oboe: Play failed: %s", C.GoString(msg))
	}
	return nil
}

func Suspend() error {
	if msg := C.ebiten_oboe_Suspend(); msg != nil {
		return fmt.Errorf("oboe: Suspend failed: %s", C.GoString(msg))
	}
	return nil
}

func Resume() error {
	if msg := C.ebiten_oboe_Resume(); msg != nil {
		return fmt.Errorf("oboe: Resume failed: %s", C.GoString(msg))
	}
	return nil
}

//export ebiten_oboe_read
func ebiten_oboe_read(buf *C.float, len C.size_t) {
	var s []float32
	h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
	h.Data = uintptr(unsafe.Pointer(buf))
	h.Len = int(len)
	h.Cap = int(len)
	for i := range s {
		s[i] = 0
	}
	theReadFunc(s)
}
<|endoftext|>


<commit_before>package clockwork

import (
	"sync"
	"time"
)

// Clock provides an interface that packages can use instead of directly
// using the time module, so that chronology-related behavior can be tested
type Clock interface {
	After(d time.Duration) <-chan time.Time
	Sleep(d time.Duration)
	Now() time.Time
}

// FakeClock provides an interface for a clock which can be
// manually ticked through time
type FakeClock interface {
	Clock
	// Tick advances the FakeClock to a new point in time,
	// ensuring any existing sleepers are notified
	// appropriately before returning
	Tick(d time.Duration)
	// BlockUntil will block until the FakeClock has the given
	// number of sleepers (callers of Sleep or After)
	BlockUntil(n int)
}

// NewRealClock returns a Clock which simply delegates calls to the actual time
// package; it should be used by packages in production.
func NewRealClock() Clock {
	return &realClock{}
}

// NewFakeClock returns a FakeClock implementation which can be
// manually ticked through time for testing.
func NewFakeClock() *FakeClock {
	return &fakeClock{
		l: sync.RWMutex{},
	}
}

type realClock struct{}

func (rc *realClock) After(d time.Duration) <-chan time.Time {
	return time.After(d)
}

func (rc *realClock) Sleep(d time.Duration) {
	time.Sleep(d)
}

func (rc *realClock) Now() time.Time {
	return time.Now()
}

type fakeClock struct {
	sleepers []*sleeper
	blockers []*blocker
	time     time.Time

	l sync.RWMutex
}

// sleeper represents a caller of After or Sleep
type sleeper struct {
	until time.Time
	done  chan time.Time
}

// blocker represents a caller of BlockUntil
type blocker struct {
	count int
	ch    chan struct{}
}

// After mimics time.After; it waits for the given duration to elapse on the
// fakeClock, then sends the current time on the returned channel.
func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	now := fc.time
	done := make(chan time.Time, 1)
	if d.Nanoseconds() == 0 {
		// special case - trigger immediately
		go func() {
			done <- now
		}()
	} else {
		// otherwise, add to the set of sleepers
		s := &sleeper{
			until: now.Add(d),
			done:  done,
		}
		fc.sleepers = append(fc.sleepers, s)
		// and notify any blockers
		fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	}
	return done
}

// notifyBlockers notifies all the blockers waiting until the
// given number of sleepers are waiting on the fakeClock. It
// returns an updated slice of blockers (i.e. those still waiting)
func notifyBlockers(blockers []*blocker, count int) (newBlockers []*blocker) {
	for _, b := range blockers {
		if b.count == count {
			close(b.ch)
		} else {
			newBlockers = append(newBlockers, b)
		}
	}
	return
}

// Sleep blocks until the given duration has passed on the fakeClock
func (fc *fakeClock) Sleep(d time.Duration) {
	<-fc.After(d)
}

// Time returns the current time of the fakeClock
func (fc *fakeClock) Now() time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	return fc.time
}

// Tick advances fakeClock to a new point in time, ensuring channels from any
// previous invocations of After are notified appropriately before returning
func (fc *fakeClock) Tick(d time.Duration) {
	fc.l.Lock()
	end := fc.time.Add(d)
	var newSleepers []*sleeper
	for _, s := range fc.sleepers {
		if end.Sub(s.until) >= 0 {
			s.done <- end
		} else {
			newSleepers = append(newSleepers, s)
		}
	}
	fc.sleepers = newSleepers
	fc.time = end
	fc.l.Unlock()
}

// BlockUntil will block until the fakeClock has the given number of sleepers
// (callers of Sleep or After)
func (fc *fakeClock) BlockUntil(n int) {
	fc.l.Lock()
	// Fast path: current number of sleepers is what we're looking for
	if len(fc.sleepers) == n {
		fc.l.Unlock()
		return
	}
	// Otherwise, set up a new blocker
	b := &blocker{
		count: n,
		ch:    make(chan struct{}),
	}
	fc.blockers = append(fc.blockers, b)
	fc.l.Unlock()
	<-b.ch
}
<commit_msg>clockwork: fix docstring formatting<commit_after>package clockwork

import (
	"sync"
	"time"
)

// Clock provides an interface that packages can use instead of directly
// using the time module, so that chronology-related behavior can be tested
type Clock interface {
	After(d time.Duration) <-chan time.Time
	Sleep(d time.Duration)
	Now() time.Time
}

// FakeClock provides an interface for a clock which can be
// manually ticked through time
type FakeClock interface {
	Clock
	// Tick advances the FakeClock to a new point in time, ensuring any existing
	// sleepers are notified appropriately before returning
	Tick(d time.Duration)
	// BlockUntil will block until the FakeClock has the given number of
	// sleepers (callers of Sleep or After)
	BlockUntil(n int)
}

// NewRealClock returns a Clock which simply delegates calls to the actual time
// package; it should be used by packages in production.
func NewRealClock() Clock {
	return &realClock{}
}

// NewFakeClock returns a FakeClock implementation which can be
// manually ticked through time for testing.
func NewFakeClock() *FakeClock {
	return &fakeClock{
		l: sync.RWMutex{},
	}
}

type realClock struct{}

func (rc *realClock) After(d time.Duration) <-chan time.Time {
	return time.After(d)
}

func (rc *realClock) Sleep(d time.Duration) {
	time.Sleep(d)
}

func (rc *realClock) Now() time.Time {
	return time.Now()
}

type fakeClock struct {
	sleepers []*sleeper
	blockers []*blocker
	time     time.Time

	l sync.RWMutex
}

// sleeper represents a caller of After or Sleep
type sleeper struct {
	until time.Time
	done  chan time.Time
}

// blocker represents a caller of BlockUntil
type blocker struct {
	count int
	ch    chan struct{}
}

// After mimics time.After; it waits for the given duration to elapse on the
// fakeClock, then sends the current time on the returned channel.
func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	now := fc.time
	done := make(chan time.Time, 1)
	if d.Nanoseconds() == 0 {
		// special case - trigger immediately
		go func() {
			done <- now
		}()
	} else {
		// otherwise, add to the set of sleepers
		s := &sleeper{
			until: now.Add(d),
			done:  done,
		}
		fc.sleepers = append(fc.sleepers, s)
		// and notify any blockers
		fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
	}
	return done
}

// notifyBlockers notifies all the blockers waiting until the
// given number of sleepers are waiting on the fakeClock. It
// returns an updated slice of blockers (i.e. those still waiting)
func notifyBlockers(blockers []*blocker, count int) (newBlockers []*blocker) {
	for _, b := range blockers {
		if b.count == count {
			close(b.ch)
		} else {
			newBlockers = append(newBlockers, b)
		}
	}
	return
}

// Sleep blocks until the given duration has passed on the fakeClock
func (fc *fakeClock) Sleep(d time.Duration) {
	<-fc.After(d)
}

// Time returns the current time of the fakeClock
func (fc *fakeClock) Now() time.Time {
	fc.l.Lock()
	defer fc.l.Unlock()
	return fc.time
}

// Tick advances fakeClock to a new point in time, ensuring channels from any
// previous invocations of After are notified appropriately before returning
func (fc *fakeClock) Tick(d time.Duration) {
	fc.l.Lock()
	end := fc.time.Add(d)
	var newSleepers []*sleeper
	for _, s := range fc.sleepers {
		if end.Sub(s.until) >= 0 {
			s.done <- end
		} else {
			newSleepers = append(newSleepers, s)
		}
	}
	fc.sleepers = newSleepers
	fc.time = end
	fc.l.Unlock()
}

// BlockUntil will block until the fakeClock has the given number of sleepers
// (callers of Sleep or After)
func (fc *fakeClock) BlockUntil(n int) {
	fc.l.Lock()
	// Fast path: current number of sleepers is what we're looking for
	if len(fc.sleepers) == n {
		fc.l.Unlock()
		return
	}
	// Otherwise, set up a new blocker
	b := &blocker{
		count: n,
		ch:    make(chan struct{}),
	}
	fc.blockers = append(fc.blockers, b)
	fc.l.Unlock()
	<-b.ch
}
<|endoftext|>


<commit_before>// Copyright © 2016 Samsung CNCT
//
// 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 cmd

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/spf13/cobra"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// Computes the hash of file named patchPath and compares it with the expected hash
func VerifyPatch(patch string, expectedHash string) (valid bool, err error) {
	fileData, err := ioutil.ReadFile(patch)
	if err != nil {
		return false, err
	}
	fileLen := len(fileData)

	fileHash := sha1.New()
	io.WriteString(fileHash, string(fileData[:fileLen]))
	computedHash := hex.EncodeToString(fileHash.Sum(nil))
	if computedHash != expectedHash {
		return false, fmt.Errorf("Computed hash %v does not equal expected hash %v", computedHash, expectedHash)
	}

	return true, nil
}

func Apply(repoDir string, patchPath string) (err error) {
	var (
		stdout bytes.Buffer
		stderr bytes.Buffer
	)

	absRepoDir, err := filepath.Abs(repoDir)
	if err != nil {
		return err
	}

	absPatchPath, err := filepath.Abs(patchPath)
	if err != nil {
		return err
	}

	oldPwd, err := os.Getwd()
	if err != nil {
		return err
	}

	defer func() {
		err = os.Chdir(oldPwd)
	}()

	err = os.Chdir(absRepoDir)
	if err != nil {
		return err
	}

	cmdName := "git"
	cmdArgs := []string{"apply", absPatchPath}
	cmd := exec.Command(cmdName, cmdArgs...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	fmt.Printf("INFO: Running command \"%v %v\"\n", cmdName, strings.Join(cmdArgs, " "))
	err = cmd.Run()
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
		fmt.Fprintf(os.Stderr, "Stdout:\n %v", stdout.String())
		fmt.Fprintf(os.Stderr, "Stderr:\n %v", stderr.String())
		return fmt.Errorf("There was an error running \"git apply\" command")
	}
	fmt.Println("INFO: Command completed successfully\n")

	return nil
}

// applyCmd represents the apply command
var applyCmd = &cobra.Command{
	Use:          "apply [config filename] (default ) " + careenConfig.GetString("config"),
	Short:        "Applies patches to repositories",
	SilenceUsage: true,
	Long:         `Applies patches to the repositories after verifying that the patch file matches the specified hash`,
	Run: func(cmd *cobra.Command, args []string) {
		manifestFilename := careenConfig.GetString("manifest")
		fmt.Printf("INFO: Using manifest %v\n", manifestFilename)

		manifest, err := GetManifestFromFile(manifestFilename)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
			fmt.Fprintf(os.Stderr, "ERROR: Failed to get manifest %v\n", manifestFilename)
			ExitCode = 1
			return
		}

		patchDir := careenConfig.GetString("patches.directory")
		outputDir := careenConfig.GetString("output.directory")

		for _, pkg := range manifest.Packages {
			fmt.Printf("INFO: Applying patches to package: %v\n", pkg.Name)
			repoDir := outputDir + pkg.Name
			for _, patch := range pkg.Patches {
				patchName := patchDir + patch.Filename
				fmt.Printf("INFO: Applying patch %v to repo %v\n", patchName, repoDir)
				valid, err := VerifyPatch(patchName, patch.Hash)
				if !valid || err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
					fmt.Fprintf(os.Stderr, "ERROR: Refusing to apply patch %v\n", patchName)
					ExitCode = 1
					return
				}
				err = Apply(repoDir, patchName)
				if err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
					fmt.Fprintf(os.Stderr, "ERROR: Failed to apply patch %v\n", patchName)
					ExitCode = 1
					return
				}
				fmt.Printf("INFO: Applied patch %v to repo %v\n", patchName, repoDir)
			}
		}

		ExitCode = 0
	},
}

func init() {
	RootCmd.AddCommand(applyCmd)
}
<commit_msg>Add a timeout to spawned command for completeness.<commit_after>// Copyright © 2016 Samsung CNCT
//
// 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 cmd

import (
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/spf13/cobra"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// Computes the hash of file named patchPath and compares it with the expected hash
func VerifyPatch(patch string, expectedHash string) (valid bool, err error) {
	fileData, err := ioutil.ReadFile(patch)
	if err != nil {
		return false, err
	}
	fileLen := len(fileData)

	fileHash := sha1.New()
	io.WriteString(fileHash, string(fileData[:fileLen]))
	computedHash := hex.EncodeToString(fileHash.Sum(nil))
	if computedHash != expectedHash {
		return false, fmt.Errorf("Computed hash %v does not equal expected hash %v", computedHash, expectedHash)
	}

	return true, nil
}

// Run command with args and kill if timeout is reached
func RunCommand(name string, args []string, timeout time.Duration) error {
	fmt.Printf("Running command \"%v %v\"\n", name, strings.Join(args, " "))
	cmd := exec.Command(name, args...)

	err := cmd.Start()
	if err != nil {
		return err
	}

	done := make(chan error, 1)
	go func() {
		done <- cmd.Wait()
	}()

	select {
	case <-time.After(timeout):
		fmt.Fprintf(os.Stderr, "Command %v timed out\n", name)
		if err := cmd.Process.Kill(); err != nil {
			panic(fmt.Sprintf("Failed to kill command %v, err %v", name, err))
		}
	case err := <-done:
		if err != nil {
			fmt.Fprintf(os.Stderr, "Command %v returned err %v\n", name, err)
			output, e := cmd.CombinedOutput()
			if e != nil {
				return e
			}
			fmt.Fprintf(os.Stderr, "%v", output)
			return err
		}
	}
	fmt.Printf("Command %v completed successfully\n", name)

	return nil
}

// Apply patch to repo in repoDir
func Apply(repoDir string, patchPath string) (err error) {
	absRepoDir, err := filepath.Abs(repoDir)
	if err != nil {
		return err
	}

	absPatchPath, err := filepath.Abs(patchPath)
	if err != nil {
		return err
	}

	oldPwd, err := os.Getwd()
	if err != nil {
		return err
	}

	defer func() {
		err = os.Chdir(oldPwd)
	}()

	err = os.Chdir(absRepoDir)
	if err != nil {
		return err
	}

	cmdName := "git"
	cmdArgs := []string{"apply", absPatchPath}
	cmdTimeout := time.Duration(10) * time.Second
	err = RunCommand(cmdName, cmdArgs, cmdTimeout)
	if err != nil {
		return err
	}

	return nil
}

// applyCmd represents the apply command
var applyCmd = &cobra.Command{
	Use:          "apply [config filename] (default ) " + careenConfig.GetString("config"),
	Short:        "Applies patches to repositories",
	SilenceUsage: true,
	Long:         `Applies patches to the repositories after verifying that the patch file matches the specified hash`,
	Run: func(cmd *cobra.Command, args []string) {
		manifestFilename := careenConfig.GetString("manifest")
		fmt.Printf("INFO: Using manifest %v\n", manifestFilename)

		manifest, err := GetManifestFromFile(manifestFilename)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
			fmt.Fprintf(os.Stderr, "ERROR: Failed to get manifest %v\n", manifestFilename)
			ExitCode = 1
			return
		}

		patchDir := careenConfig.GetString("patches.directory")
		outputDir := careenConfig.GetString("output.directory")

		for _, pkg := range manifest.Packages {
			fmt.Printf("INFO: Applying patches to package: %v\n", pkg.Name)
			repoDir := outputDir + pkg.Name
			for _, patch := range pkg.Patches {
				patchName := patchDir + patch.Filename
				fmt.Printf("INFO: Applying patch %v to repo %v\n", patchName, repoDir)
				valid, err := VerifyPatch(patchName, patch.Hash)
				if !valid || err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
					fmt.Fprintf(os.Stderr, "ERROR: Refusing to apply patch %v\n", patchName)
					ExitCode = 1
					return
				}
				err = Apply(repoDir, patchName)
				if err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
					fmt.Fprintf(os.Stderr, "ERROR: Failed to apply patch %v\n", patchName)
					ExitCode = 1
					return
				}
				fmt.Printf("INFO: Applied patch %v to repo %v\n", patchName, repoDir)
			}
		}

		ExitCode = 0
	},
}

func init() {
	RootCmd.AddCommand(applyCmd)
}
<|endoftext|>