<commit_before>package controller

import (
	"flag"
	"html/template"
	"log"
	"net/http"
)

// If flag is set, templates are reloaded on every refresh
var noCache = flag.Bool("nocache", false, "Determines whether template caching should occur.")

// Global template engine
var tpl *BlogTemplate

// Custom template wrapper
type BlogTemplate struct {
	*template.Template
	files []string
}

// ExecuteTemplate wrapper, if -nocache flag is set, all templates are loaded on every request
func (t *BlogTemplate) ExecuteTemplate(w http.ResponseWriter, name string, data interface{}) error {
	if *noCache {
		log.Printf("[%s] Recompiling templates.", name)
		t.Template = template.Must(template.ParseFiles(t.files...))
	}

	return t.Template.ExecuteTemplate(w, name, data)
}

func init() {
	tpl = &BlogTemplate{
		files: []string{
			"views/login.html",
			"views/404.html",
			"views/manage.html",
			"views/editPost.html",
			"views/header.html",
			"views/footer.html",
			"views/home.html",
			"views/post.html",
		},
	}

	tpl.Template = template.Must(template.ParseFiles(tpl.files...))
}
<commit_msg>Aggregated fields<commit_after>package controller

import (
	"flag"
	"html/template"
	"log"
	"net/http"
)

// If flag is set, templates are reloaded on every refresh
var noCache = flag.Bool("nocache", false, "Determines whether template caching should occur.")

// Global template engine
var tpl *BlogTemplate

// Custom template wrapper
type BlogTemplate struct {
	*template.Template
	files []string
}

func (t *BlogTemplate) ExecuteTemplate(w http.ResponseWriter, name string, data interface{}) error {
	if *noCache {
		log.Printf("[%s] Recompiling templates.", name)
		t.Template = template.Must(template.ParseFiles(t.files...))
	}

	return t.Template.ExecuteTemplate(w, name, data)
}

func init() {
	tpl = &BlogTemplate{
		files: []string{
			"views/login.html",
			"views/404.html",
			"views/manage.html",
			"views/editPost.html",
			"views/header.html",
			"views/footer.html",
			"views/home.html",
			"views/post.html",
		},
	}

	tpl.Template = template.Must(template.ParseFiles(tpl.files...))
}
<|endoftext|>


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

package vrf

import (
	"crypto/elliptic"
	"errors"
	"math/big"
)

// This file implements compressed point unmarshaling.
// This code will be in go 1.15
// Code borrowed from: https://github.com/golang/go/pull/35110

// marshalCompressed converts an EC point to an octet string according to
// the encoding specified in Section 2.3.3 of [SECG1] with point compression
// on. This implies ptLen = 2n + 1 = 33.
//
// SECG1 Section 2.3.3 https://www.secg.org/sec1-v1.99.dif.pdf
func marshalCompressed(curve elliptic.Curve, x, y *big.Int) []byte {
	byteLen := (curve.Params().BitSize + 7) >> 3
	compressed := make([]byte, 1+byteLen)
	compressed[0] = 2 // compressed point
	compressed[0] += byte(y.Bit(0))
	i := byteLen + 1 - len(x.Bytes())
	copy(compressed[i:], x.Bytes())
	return compressed
}

var errInvalidPoint = errors.New("invalid point")

// marshalCompressed decodes a EC point, given as a compressed string.
// If the decoding fails x and y will be nil.
//
// http://www.secg.org/sec1-v2.pdf
// https://tools.ietf.org/html/rfc8032#section-5.1.3
// Section 4.3.6 of ANSI X9.62.
func unmarshalCompressed(curve elliptic.Curve, data []byte) (x, y *big.Int, err error) {
	byteLen := (curve.Params().BitSize + 7) >> 3
	if (data[0] &^ 1) != 2 { // compressed form
		return nil, nil, errors.New("unrecognized point encoding")
	}
	if len(data) != 1+byteLen {
		return nil, nil, errors.New("invalid length for curve")
	}

	// Based on Routine 2.2.4 in NIST Mathematical routines paper
	x = new(big.Int).SetBytes(data[1:])
	y2 := polynomial(curve.Params(), x)
	y = new(big.Int).ModSqrt(y2, curve.Params().P)
	if y == nil {
		return nil, nil, errInvalidPoint // "y^2" is not a square
	}
	if !curve.IsOnCurve(x, y) {
		return nil, nil, errInvalidPoint
	}
	if y.Bit(0) != uint(data[0]&0x01) {
		y.Sub(curve.Params().P, y)
	}

	return x, y, nil // valid point: return x,y
}

// polynomial returns x³ - 3x + b.
func polynomial(curve *elliptic.CurveParams, x *big.Int) *big.Int {
	x3 := new(big.Int).Mul(x, x)
	x3.Mul(x3, x)

	threeX := new(big.Int).Lsh(x, 1)
	threeX.Add(threeX, x)
	x3.Sub(x3, threeX)

	x3.Add(x3, curve.B)
	x3.Mod(x3, curve.P)
	return x3
}
<commit_msg>Slightly more readable test for compressed curve form<commit_after>// Copyright 2020 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vrf

import (
	"crypto/elliptic"
	"errors"
	"math/big"
)

// This file implements compressed point unmarshaling.
// This code will be in go 1.15
// Code borrowed from: https://github.com/golang/go/pull/35110

// marshalCompressed converts an EC point to an octet string according to
// the encoding specified in Section 2.3.3 of [SECG1] with point compression
// on. This implies ptLen = 2n + 1 = 33.
//
// SECG1 Section 2.3.3 https://www.secg.org/sec1-v1.99.dif.pdf
func marshalCompressed(curve elliptic.Curve, x, y *big.Int) []byte {
	byteLen := (curve.Params().BitSize + 7) >> 3
	compressed := make([]byte, 1+byteLen)
	compressed[0] = 2 // compressed point
	compressed[0] += byte(y.Bit(0))
	i := byteLen + 1 - len(x.Bytes())
	copy(compressed[i:], x.Bytes())
	return compressed
}

var errInvalidPoint = errors.New("invalid point")

// marshalCompressed decodes a EC point, given as a compressed string.
// If the decoding fails x and y will be nil.
//
// http://www.secg.org/sec1-v2.pdf
// https://tools.ietf.org/html/rfc8032#section-5.1.3
// Section 4.3.6 of ANSI X9.62.
func unmarshalCompressed(curve elliptic.Curve, data []byte) (x, y *big.Int, err error) {
	byteLen := (curve.Params().BitSize + 7) >> 3
	if data[0] != 2 && data[0] != 3 { // compressed form
		return nil, nil, errors.New("unrecognized point encoding")
	}
	if len(data) != 1+byteLen {
		return nil, nil, errors.New("invalid length for curve")
	}

	// Based on Routine 2.2.4 in NIST Mathematical routines paper
	x = new(big.Int).SetBytes(data[1:])
	y2 := polynomial(curve.Params(), x)
	y = new(big.Int).ModSqrt(y2, curve.Params().P)
	if y == nil {
		return nil, nil, errInvalidPoint // "y^2" is not a square
	}
	if !curve.IsOnCurve(x, y) {
		return nil, nil, errInvalidPoint
	}
	if y.Bit(0) != uint(data[0]&0x01) {
		y.Sub(curve.Params().P, y)
	}

	return x, y, nil // valid point: return x,y
}

// polynomial returns x³ - 3x + b.
func polynomial(curve *elliptic.CurveParams, x *big.Int) *big.Int {
	x3 := new(big.Int).Mul(x, x)
	x3.Mul(x3, x)

	threeX := new(big.Int).Lsh(x, 1)
	threeX.Add(threeX, x)
	x3.Sub(x3, threeX)

	x3.Add(x3, curve.B)
	x3.Mod(x3, curve.P)
	return x3
}
<|endoftext|>


<commit_before>package wf

import (
	"fmt"
	"unsafe"

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

type arena struct {
	slabs     []uintptr
	next      uintptr
	remaining uintptr
}

const slabSize = 4096

func (a *arena) grow() {
	slab, err := windows.LocalAlloc(windows.LPTR, slabSize)
	if err != nil {
		panic(fmt.Sprintf("memory allocation failed: %v", err))
	}
	a.slabs = append(a.slabs, slab)
	a.next = slab
	a.remaining = slabSize
}

func (a *arena) alloc(length uintptr) unsafe.Pointer {
	if length > slabSize {
		panic(fmt.Sprintf("can't allocate something that big (%d bytes)", length))
	}
	if length == 0 {
		panic("can't allocate zero bytes")
	}
	if length > a.remaining {
		a.grow()
	}
	ret := *(**struct{})(unsafe.Pointer(&a.next))
	a.next += length
	a.remaining -= length
	return unsafe.Pointer(ret)
}

func (a *arena) calloc(num int, size uintptr) unsafe.Pointer {
	return a.alloc(uintptr(num) * size)
}

func (a *arena) dispose() {
	for _, slab := range a.slabs {
		if _, err := windows.LocalFree(windows.Handle(slab)); err != nil {
			panic(fmt.Sprintf("free failed: %v", err))
		}
	}
	a.slabs = nil
	a.next = 0
	a.remaining = 0
}
<commit_msg>tweak and document malloc things.<commit_after>package wf

import (
	"fmt"
	"unsafe"

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

type arena struct {
	slabs     []uintptr
	next      uintptr
	remaining uintptr
}

const slabSize = 4096

func (a *arena) grow() {
	slab, err := windows.LocalAlloc(windows.LPTR, slabSize)
	if err != nil {
		panic(fmt.Sprintf("memory allocation failed: %v", err))
	}
	a.slabs = append(a.slabs, slab)
	a.next = slab
	a.remaining = slabSize
}

func (a *arena) alloc(length uintptr) unsafe.Pointer {
	if length > slabSize {
		panic(fmt.Sprintf("can't allocate something that big (%d bytes)", length))
	}
	if length == 0 {
		panic("can't allocate zero bytes")
	}
	if length > a.remaining {
		a.grow()
	}

	// Cast from *uintptr rather than plain uintptr to avoid the go
	// vet unsafe.Pointer safety check. This pattern is safe because
	// a.next never points into the Go heap.
	ret := *(**struct{})(unsafe.Pointer(&a.next))
	a.next += length
	a.remaining -= length
	return unsafe.Pointer(ret)
}

func (a *arena) calloc(num int, size uintptr) unsafe.Pointer {
	return a.alloc(uintptr(num) * size)
}

func (a *arena) dispose() {
	for _, slab := range a.slabs {
		if _, err := windows.LocalFree(windows.Handle(slab)); err != nil {
			panic(fmt.Sprintf("free failed: %v", err))
		}
	}
	a.slabs = a.slabs[:0]
	a.next = 0
	a.remaining = 0
}
<|endoftext|>


<commit_before>package web

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"gopkg.in/mgo.v2"

	"context"

	"github.com/nlopes/slack"
	"github.com/tuna-timer/tuna-timer-api/commands"
	"github.com/tuna-timer/tuna-timer-api/data"
	"github.com/tuna-timer/tuna-timer-api/models"
	"github.com/tuna-timer/tuna-timer-api/themes"
	"github.com/tuna-timer/tuna-timer-api/utils"
	"gopkg.in/mgo.v2/bson"
	"log"
)

// Handlers is a collection of net/http handlers to serve the API
type Handlers struct {
	env                   *utils.Environment
	mongoSession          *mgo.Session
	status                map[string]string
	commandLookupFunction func(ctx context.Context, slackCommand models.SlackCustomCommand) (commands.SlackCustomCommandHandler, error)
	slackOAuth            SlackOAuth
}

// NewHandlers constructs a Handlers collection
func NewHandlers(env *utils.Environment, mongoSession *mgo.Session) *Handlers {
	return &Handlers{
		env:          env,
		mongoSession: mongoSession,
		status: map[string]string{
			"env":     env.Name,
			"version": env.AppVersion,
		},
		commandLookupFunction: commands.LookupHandler,
		slackOAuth:            NewSlackOAuth(),
	}
}

// Timer handles Slack /timer command
func (h *Handlers) Timer(w http.ResponseWriter, r *http.Request) {
	now := time.Now()

	slackCommand := models.SlackCustomCommand{
		ChannelID:   r.PostFormValue("channel_id"),
		ChannelName: r.PostFormValue("channel_name"),
		Command:     r.PostFormValue("command"),
		ResponseURL: r.PostFormValue("response_url"),
		TeamDomain:  r.PostFormValue("team_domain"),
		TeamID:      r.PostFormValue("team_id"),
		Text:        r.PostFormValue("text"),
		Token:       r.PostFormValue("token"),
		UserID:      r.PostFormValue("user_id"),
		UserName:    r.PostFormValue("user_name"),
	}
	slackCommand = utils.NormalizeSlackCustomCommand(slackCommand)

	session := h.mongoSession.Clone()
	defer session.Close()
	ctx := utils.PutMongoSessionInContext(r.Context(), session)

	selfBaseURL := utils.GetSelfURLFromRequest(r)
	ctx = utils.PutSelfBaseURLInContext(ctx, selfBaseURL)

	theme := themes.NewDefaultSlackMessageTheme(ctx)
	ctx = utils.PutThemeInContext(ctx, theme)

	command, err := h.commandLookupFunction(ctx, slackCommand)
	if err != nil {
		w.Write([]byte(theme.FormatError(err.Error())))
		return
	}

	result := command.Handle(ctx, slackCommand)
	w.Header().Set("Content-Type", "application/json")
	w.Write(result.Body)

	//todo: rather defer it
	log.Printf("Timer command took %s", time.Since(now).String())
}

// SlackOauth2Redirect handles the OAuth2 redirect from Slack and exchanges the `code` with `accessToken`
// https://api.slack.com/methods/oauth.access
func (h *Handlers) SlackOauth2Redirect(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	clientID := h.env.Config.UString("slack.client_id")
	clientSecret := h.env.Config.UString("slack.client_secret")

	if code == "" {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("`code` parameter is either missed or blank!"))
		return
	}

	oauthResponse, err := h.slackOAuth.GetOAuthResponse(clientID, clientSecret, code)
	if err != nil {
		msg := fmt.Sprintf("Got a failure during getting an access token from Slack: %s", err)
		log.Println(msg)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(msg))
		return
	}

	teamService := data.NewTeamService(h.mongoSession)

	err = teamService.CreateOrUpdateWithSlackOAuthResponse(oauthResponse)
	if err != nil {
		msg := fmt.Sprintf("Got a failure during creating a team: %s", err)
		log.Println(msg)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(msg))
		return
	}

	w.WriteHeader(http.StatusOK)
}

// Health handles a call for app health request
func (h *Handlers) Health(w http.ResponseWriter, r *http.Request) {
	uptime := time.Since(h.env.CreatedAt)
	h.status["uptime"] = uptime.String() //is it good or not if I modify the map here?
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(h.status)
}

func (h *Handlers) SendSampleMessageFromBot(w http.ResponseWriter, r *http.Request) {

	teamRepo := data.NewTeamRepository(h.mongoSession)
	team, _ := teamRepo.FindByExternalID("T02BC0MM7")

	accessToken := team.SlackOAuth.Bot.BotAccessToken
	slackAPI := slack.New(accessToken)

	slackAPI.PostMessage("U02BC0MM9", "You're about stopping a timer...", slack.PostMessageParameters{
		AsUser: true,
		Attachments: []slack.Attachment{
			{
				Text:       "Would you like to stop the timer?",
				AuthorName: "Pavlo",
				Actions: []slack.AttachmentAction{
					{
						Text:  "Yes, I'd like to stop it",
						Name:  "yes",
						Type:  "button",
						Style: "danger",
						Confirm: []slack.ConfirmationField{
							{
								Text:        "Are you sure?",
								DismissText: "Cancel",
								OkText:      "Yes!",
								Title:       "Are you sure you want to stop the timer?",
							},
						},
					},
					{
						Text:  "I am not sure yet",
						Name:  "not sure",
						Type:  "button",
						Style: "default",
					},
					{
						Text:  "No, let's keep it!",
						Name:  "no",
						Type:  "button",
						Style: "primary",
					},
				},
			},
		},
	})
}

// ClearAllData - is supposed to be called by the QA team during early testing stage
func (h *Handlers) ClearAllData(w http.ResponseWriter, r *http.Request) {
	session := h.mongoSession.Clone()
	defer session.Close()
	utils.TruncateTables(session)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(bson.M{"success": true})
}
<commit_msg>set application/json header for all possible responses within Timer handler<commit_after>package web

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"gopkg.in/mgo.v2"

	"context"

	"github.com/nlopes/slack"
	"github.com/tuna-timer/tuna-timer-api/commands"
	"github.com/tuna-timer/tuna-timer-api/data"
	"github.com/tuna-timer/tuna-timer-api/models"
	"github.com/tuna-timer/tuna-timer-api/themes"
	"github.com/tuna-timer/tuna-timer-api/utils"
	"gopkg.in/mgo.v2/bson"
	"log"
)

// Handlers is a collection of net/http handlers to serve the API
type Handlers struct {
	env                   *utils.Environment
	mongoSession          *mgo.Session
	status                map[string]string
	commandLookupFunction func(ctx context.Context, slackCommand models.SlackCustomCommand) (commands.SlackCustomCommandHandler, error)
	slackOAuth            SlackOAuth
}

// NewHandlers constructs a Handlers collection
func NewHandlers(env *utils.Environment, mongoSession *mgo.Session) *Handlers {
	return &Handlers{
		env:          env,
		mongoSession: mongoSession,
		status: map[string]string{
			"env":     env.Name,
			"version": env.AppVersion,
		},
		commandLookupFunction: commands.LookupHandler,
		slackOAuth:            NewSlackOAuth(),
	}
}

// Timer handles Slack /timer command
func (h *Handlers) Timer(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	now := time.Now()

	slackCommand := models.SlackCustomCommand{
		ChannelID:   r.PostFormValue("channel_id"),
		ChannelName: r.PostFormValue("channel_name"),
		Command:     r.PostFormValue("command"),
		ResponseURL: r.PostFormValue("response_url"),
		TeamDomain:  r.PostFormValue("team_domain"),
		TeamID:      r.PostFormValue("team_id"),
		Text:        r.PostFormValue("text"),
		Token:       r.PostFormValue("token"),
		UserID:      r.PostFormValue("user_id"),
		UserName:    r.PostFormValue("user_name"),
	}
	slackCommand = utils.NormalizeSlackCustomCommand(slackCommand)

	session := h.mongoSession.Clone()
	defer session.Close()
	ctx := utils.PutMongoSessionInContext(r.Context(), session)

	selfBaseURL := utils.GetSelfURLFromRequest(r)
	ctx = utils.PutSelfBaseURLInContext(ctx, selfBaseURL)

	theme := themes.NewDefaultSlackMessageTheme(ctx)
	ctx = utils.PutThemeInContext(ctx, theme)

	command, err := h.commandLookupFunction(ctx, slackCommand)
	if err != nil {
		w.Write([]byte(theme.FormatError(err.Error())))
		return
	}

	result := command.Handle(ctx, slackCommand)
	w.Write(result.Body)

	//todo: rather defer it
	log.Printf("Timer command took %s", time.Since(now).String())
}

// SlackOauth2Redirect handles the OAuth2 redirect from Slack and exchanges the `code` with `accessToken`
// https://api.slack.com/methods/oauth.access
func (h *Handlers) SlackOauth2Redirect(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	clientID := h.env.Config.UString("slack.client_id")
	clientSecret := h.env.Config.UString("slack.client_secret")

	if code == "" {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("`code` parameter is either missed or blank!"))
		return
	}

	oauthResponse, err := h.slackOAuth.GetOAuthResponse(clientID, clientSecret, code)
	if err != nil {
		msg := fmt.Sprintf("Got a failure during getting an access token from Slack: %s", err)
		log.Println(msg)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(msg))
		return
	}

	teamService := data.NewTeamService(h.mongoSession)

	err = teamService.CreateOrUpdateWithSlackOAuthResponse(oauthResponse)
	if err != nil {
		msg := fmt.Sprintf("Got a failure during creating a team: %s", err)
		log.Println(msg)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(msg))
		return
	}

	w.WriteHeader(http.StatusOK)
}

// Health handles a call for app health request
func (h *Handlers) Health(w http.ResponseWriter, r *http.Request) {
	uptime := time.Since(h.env.CreatedAt)
	h.status["uptime"] = uptime.String() //is it good or not if I modify the map here?
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(h.status)
}

func (h *Handlers) SendSampleMessageFromBot(w http.ResponseWriter, r *http.Request) {

	teamRepo := data.NewTeamRepository(h.mongoSession)
	team, _ := teamRepo.FindByExternalID("T02BC0MM7")

	accessToken := team.SlackOAuth.Bot.BotAccessToken
	slackAPI := slack.New(accessToken)

	slackAPI.PostMessage("U02BC0MM9", "You're about stopping a timer...", slack.PostMessageParameters{
		AsUser: true,
		Attachments: []slack.Attachment{
			{
				Text:       "Would you like to stop the timer?",
				AuthorName: "Pavlo",
				Actions: []slack.AttachmentAction{
					{
						Text:  "Yes, I'd like to stop it",
						Name:  "yes",
						Type:  "button",
						Style: "danger",
						Confirm: []slack.ConfirmationField{
							{
								Text:        "Are you sure?",
								DismissText: "Cancel",
								OkText:      "Yes!",
								Title:       "Are you sure you want to stop the timer?",
							},
						},
					},
					{
						Text:  "I am not sure yet",
						Name:  "not sure",
						Type:  "button",
						Style: "default",
					},
					{
						Text:  "No, let's keep it!",
						Name:  "no",
						Type:  "button",
						Style: "primary",
					},
				},
			},
		},
	})
}

// ClearAllData - is supposed to be called by the QA team during early testing stage
func (h *Handlers) ClearAllData(w http.ResponseWriter, r *http.Request) {
	session := h.mongoSession.Clone()
	defer session.Close()
	utils.TruncateTables(session)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(bson.M{"success": true})
}
<|endoftext|>


<commit_before>package external

import (
	"time"

	"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
)

// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool

// Convenience vars for AdminStateUp values.
var (
	iTrue  = true
	iFalse = false

	Up   AdminState = &iTrue
	Down AdminState = &iFalse
)

// CreateOpts is the structure used when creating new external network
// resources. It embeds networks.CreateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type CreateOpts struct {
	Parent   networks.CreateOpts
	External bool
}

// ToNetworkCreateMap casts a CreateOpts struct to a map.
func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
	time.Sleep(0 * time.Millisecond)

	outer, err := o.Parent.ToNetworkCreateMap()
	if err != nil {
		return nil, err
	}

	outer["network"].(map[string]interface{})["router:external"] = o.External

	return outer, nil
}

// UpdateOpts is the structure used when updating existing external network
// resources. It embeds networks.UpdateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type UpdateOpts struct {
	Parent   networks.UpdateOpts
	External bool
}

// ToNetworkUpdateMap casts an UpdateOpts struct to a map.
func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
	outer, err := o.Parent.ToNetworkUpdateMap()
	if err != nil {
		return nil, err
	}

	outer["network"].(map[string]interface{})["router:external"] = o.External

	return outer, nil
}
<commit_msg>comment for filler line<commit_after>package external

import (
	"time"

	"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
)

// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool

// Convenience vars for AdminStateUp values.
var (
	iTrue  = true
	iFalse = false

	Up   AdminState = &iTrue
	Down AdminState = &iFalse
)

// CreateOpts is the structure used when creating new external network
// resources. It embeds networks.CreateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type CreateOpts struct {
	Parent   networks.CreateOpts
	External bool
}

// ToNetworkCreateMap casts a CreateOpts struct to a map.
func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {

	// DO NOT REMOVE. Though this line seemingly does nothing of value, it is a
	// splint to prevent the unit test from failing on Go Tip. We suspect it is a
	// compiler issue that will hopefully be worked out prior to our next release.
	// Again, for all the unit tests to pass, this line is necessary and sufficient
	// at the moment.
	time.Sleep(0 * time.Millisecond)

	outer, err := o.Parent.ToNetworkCreateMap()
	if err != nil {
		return nil, err
	}

	outer["network"].(map[string]interface{})["router:external"] = o.External

	return outer, nil
}

// UpdateOpts is the structure used when updating existing external network
// resources. It embeds networks.UpdateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type UpdateOpts struct {
	Parent   networks.UpdateOpts
	External bool
}

// ToNetworkUpdateMap casts an UpdateOpts struct to a map.
func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
	outer, err := o.Parent.ToNetworkUpdateMap()
	if err != nil {
		return nil, err
	}

	outer["network"].(map[string]interface{})["router:external"] = o.External

	return outer, nil
}
<|endoftext|>


<commit_before>package json

import (
	"github.com/agext/levenshtein"
)

var keywords = []string{"false", "true", "null"}

// keywordSuggestion tries to find a valid JSON keyword that is close to the
// given string and returns it if found. If no keyword is close enough, returns
// the empty string.
func keywordSuggestion(given string) string {
	for _, kw := range keywords {
		dist := levenshtein.Distance(given, kw, nil)
		if dist < 3 { // threshold determined experimentally
			return kw
		}
	}
	return ""
}
<commit_msg>json: Generalize "keywordSuggestion" for general name suggestions<commit_after>package json

import (
	"github.com/agext/levenshtein"
)

var keywords = []string{"false", "true", "null"}

// keywordSuggestion tries to find a valid JSON keyword that is close to the
// given string and returns it if found. If no keyword is close enough, returns
// the empty string.
func keywordSuggestion(given string) string {
	return nameSuggestion(given, keywords)
}

// nameSuggestion tries to find a name from the given slice of suggested names
// that is close to the given name and returns it if found. If no suggestion
// is close enough, returns the empty string.
//
// The suggestions are tried in order, so earlier suggestions take precedence
// if the given string is similar to two or more suggestions.
//
// This function is intended to be used with a relatively-small number of
// suggestions. It's not optimized for hundreds or thousands of them.
func nameSuggestion(given string, suggestions []string) string {
	for _, suggestion := range suggestions {
		dist := levenshtein.Distance(given, suggestion, nil)
		if dist < 3 { // threshold determined experimentally
			return suggestion
		}
	}
	return ""
}
<|endoftext|>


<commit_before>// Copyright 2014 The Azul3D 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 wav

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

	"azul3d.org/audio.v1"
)

func testDecode(t *testing.T, fileName string) {
	t.Log(fileName)

	file, err := os.Open(fileName)
	if err != nil {
		t.Fatal(err)
	}

	// Create an decoder for the audio source
	decoder, format, err := audio.NewDecoder(file)
	if err != nil {
		t.Fatal(err)
	}

	// Grab the decoder's configuration
	config := decoder.Config()
	t.Log("Decoding an", format, "file.")
	t.Log(config)

	// Create an buffer that can hold 1 second of audio samples
	bufSize := 1 * config.SampleRate * config.Channels
	buf := make(audio.F64Samples, bufSize)

	// Fill the buffer with as many audio samples as we can
	read, err := decoder.Read(buf)
	if err != nil {
		t.Fatal(err)
	}
	t.Log("Read", read, "audio samples.")
	t.Log("")

	// readBuf := buf.Slice(0, read)
	// for i := 0; i < readBuf.Len(); i++ {
	//     sample := readBuf.At(i)
	// }
}

func TestALaw(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_alaw.wav")
}

func TestFloat32(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_float32.wav")
}

func TestFloat64(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_float64.wav")
}

func TestInt16(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int16.wav")
}

func TestInt24(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int24.wav")
}

func TestInt32(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int32.wav")
}

func TestMulaw(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_mulaw.wav")
}

func TestUint8(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_uint8.wav")
}

func BenchmarkInt24(b *testing.B) {
	data, err := ioutil.ReadFile("testdata/tune_stereo_44100hz_int24.wav")
	if err != nil {
		b.Fatal(err)
	}
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		// Create an decoder for the audio source
		decoder, _, err := audio.NewDecoder(bytes.NewReader(data))
		if err != nil {
			b.Fatal(err)
		}

		// Grab the decoder's configuration
		config := decoder.Config()

		// Create an buffer that can hold 1 second of audio samples
		bufSize := 1 * config.SampleRate * config.Channels
		buf := make(audio.F64Samples, bufSize)

		// Fill the buffer with as many audio samples as we can
		_, err = decoder.Read(buf)
		if err != nil {
			b.Fatal(err)
		}
	}
}
<commit_msg>Prefix decoder tests (e.g. TestDecodeInt16 instead of TestInt64).<commit_after>// Copyright 2014 The Azul3D 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 wav

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

	"azul3d.org/audio.v1"
)

func testDecode(t *testing.T, fileName string) {
	t.Log(fileName)

	file, err := os.Open(fileName)
	if err != nil {
		t.Fatal(err)
	}

	// Create an decoder for the audio source
	decoder, format, err := audio.NewDecoder(file)
	if err != nil {
		t.Fatal(err)
	}

	// Grab the decoder's configuration
	config := decoder.Config()
	t.Log("Decoding an", format, "file.")
	t.Log(config)

	// Create an buffer that can hold 1 second of audio samples
	bufSize := 1 * config.SampleRate * config.Channels
	buf := make(audio.F64Samples, bufSize)

	// Fill the buffer with as many audio samples as we can
	read, err := decoder.Read(buf)
	if err != nil {
		t.Fatal(err)
	}
	t.Log("Read", read, "audio samples.")
	t.Log("")

	// readBuf := buf.Slice(0, read)
	// for i := 0; i < readBuf.Len(); i++ {
	//     sample := readBuf.At(i)
	// }
}

func TestDecodeALaw(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_alaw.wav")
}

func TestDecodeFloat32(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_float32.wav")
}

func TestDecodeFloat64(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_float64.wav")
}

func TestDecodeInt16(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int16.wav")
}

func TestDecodeInt24(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int24.wav")
}

func TestDecodeInt32(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_int32.wav")
}

func TestDecodeMulaw(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_mulaw.wav")
}

func TestUint8(t *testing.T) {
	testDecode(t, "testdata/tune_stereo_44100hz_uint8.wav")
}

func BenchmarkInt24(b *testing.B) {
	data, err := ioutil.ReadFile("testdata/tune_stereo_44100hz_int24.wav")
	if err != nil {
		b.Fatal(err)
	}
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		// Create an decoder for the audio source
		decoder, _, err := audio.NewDecoder(bytes.NewReader(data))
		if err != nil {
			b.Fatal(err)
		}

		// Grab the decoder's configuration
		config := decoder.Config()

		// Create an buffer that can hold 1 second of audio samples
		bufSize := 1 * config.SampleRate * config.Channels
		buf := make(audio.F64Samples, bufSize)

		// Fill the buffer with as many audio samples as we can
		_, err = decoder.Read(buf)
		if err != nil {
			b.Fatal(err)
		}
	}
}
<|endoftext|>


<commit_before>package sms

import (
	"bufio"
	"bytes"
	"errors"
	"net"
	"strings"
)

type Sender struct {
	Id     string // Server identifier. See Source field in smsd.cfg
	Server string // IP address:port or unix domain socket path
	Delete bool   // Will message need to be deleted after sent/reported?
	Report bool   // Is report required?
}

// Sends txt as SMS to recipients. Recipient need to be specified as
// PhoneNumber[=DstId] You can use DstId to link recipient with some other
// data in your database. Send is thread-safe.
func (s *Sender) Send(txt string, recipients ...string) error {
	if len(recipients) == 0 {
		return nil
	}
	proto := "tcp"
	if strings.IndexRune(s.Server, ':') == -1 {
		proto = "unix"
	}
	c, err := net.Dial(proto, s.Server)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(c)

	if err = writeln(w, s.Id); err != nil {
		return err
	}

	if _, err = w.WriteString(recipients[0]); err != nil {
		return err
	}
	for _, num := range recipients[1:] {
		if err = w.WriteByte(' '); err != nil {
			return err
		}
		if _, err = w.WriteString(num); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if s.Delete {
		if err = writeln(w, "delete"); err != nil {
			return err
		}
	}
	if s.Report {
		if err = writeln(w, "report"); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if _, err = w.WriteString(strings.TrimSpace(txt)); err != nil {
		return err
	}
	if err = writeln(w, "\n."); err != nil {
		return err
	}
	if err = w.Flush(); err != nil {
		return err
	}
	// Read OK response
	buf, _, err := bufio.NewReader(c).ReadLine()
	if err != nil {
		return err
	}
	buf = bytes.TrimSpace(buf)
	if !bytes.Equal(buf, []byte{'O', 'K'}) {
		c.Close()
		return errors.New(string(buf))
	}
	return c.Close()
}

func newLine(w *bufio.Writer) error {
	return w.WriteByte('\n')
}

func writeln(w *bufio.Writer, s string) error {
	_, err := w.WriteString(s)
	if err != nil {
		return err
	}
	return newLine(w)
}
<commit_msg>Fix typo in sms.Sender description<commit_after>package sms

import (
	"bufio"
	"bytes"
	"errors"
	"net"
	"strings"
)

type Sender struct {
	Id     string // Sender identifier. See Source field in smsd.cfg
	Server string // IP address:port or unix domain socket path
	Delete bool   // Will message need to be deleted after sent/reported?
	Report bool   // Is report required?
}

// Sends txt as SMS to recipients. Recipient need to be specified as
// PhoneNumber[=DstId] You can use DstId to link recipient with some other
// data in your database. Send is thread-safe.
func (s *Sender) Send(txt string, recipients ...string) error {
	if len(recipients) == 0 {
		return nil
	}
	proto := "tcp"
	if strings.IndexRune(s.Server, ':') == -1 {
		proto = "unix"
	}
	c, err := net.Dial(proto, s.Server)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(c)

	if err = writeln(w, s.Id); err != nil {
		return err
	}

	if _, err = w.WriteString(recipients[0]); err != nil {
		return err
	}
	for _, num := range recipients[1:] {
		if err = w.WriteByte(' '); err != nil {
			return err
		}
		if _, err = w.WriteString(num); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if s.Delete {
		if err = writeln(w, "delete"); err != nil {
			return err
		}
	}
	if s.Report {
		if err = writeln(w, "report"); err != nil {
			return err
		}
	}
	if err = newLine(w); err != nil {
		return err
	}

	if _, err = w.WriteString(strings.TrimSpace(txt)); err != nil {
		return err
	}
	if err = writeln(w, "\n."); err != nil {
		return err
	}
	if err = w.Flush(); err != nil {
		return err
	}
	// Read OK response
	buf, _, err := bufio.NewReader(c).ReadLine()
	if err != nil {
		return err
	}
	buf = bytes.TrimSpace(buf)
	if !bytes.Equal(buf, []byte{'O', 'K'}) {
		c.Close()
		return errors.New(string(buf))
	}
	return c.Close()
}

func newLine(w *bufio.Writer) error {
	return w.WriteByte('\n')
}

func writeln(w *bufio.Writer, s string) error {
	_, err := w.WriteString(s)
	if err != nil {
		return err
	}
	return newLine(w)
}
<|endoftext|>


<commit_before>package trousseau

import (
	"testing"
	"encoding/json"

	"github.com/oleiade/tempura"
)

func TestOpenTrousseau(t *testing.T) {
	testData := make(map[string]interface{})
	testData["encryption_type"] = ASYMMETRIC_ENCRYPTION
	testData["encryption_algorithm"] = GPG_ENCRYPTION
	testData["_data"] = "qeiun91inwd918hnd913dn19dni1dn9183nd9138d"

	jsonData, _ := json.Marshal(&testData)
	tmp, _ := tempura.FromBytes("/tmp", "trousseau", jsonData)

	tr, err := OpenTrousseau(tmp.File.Name())
	if err != nil {
		t.Fatal(err)
	}

	assert(t, tr.EncryptionType == ASYMMETRIC_ENCRYPTION, "Wrong encryption type")
	assert(t, tr.EncryptionAlgorithm == GPG_ENCRYPTION, "Wrong encryption algorithm")
	assert(t, tr.Store == "qeiun91inwd918hnd913dn19dni1dn9183nd9138d", "Invalid data retrieved")
}

func TestOpenTrousseau_returns_err_when_file_does_not_exist(t *testing.T) {
	_, err := OpenTrousseau("/does/not/exist")
	if err == nil {
		t.Fatalf("OpenTrousseau function didn't failed while loading non existing file")
	}
}
<commit_msg>Fix trousseau tests<commit_after>package trousseau

import (
	"testing"
	"encoding/json"

	"github.com/oleiade/tempura"
	"os"
)

func TestOpenTrousseau(t *testing.T) {
	testData := make(map[string]interface{})
	testData["crypto_type"] = ASYMMETRIC_ENCRYPTION
	testData["crypto_algorithm"] = GPG_ENCRYPTION
	testData["_data"] = []byte("abc")

	jsonData, _ := json.Marshal(&testData)
	tmp, _ := tempura.FromBytes("/tmp", "trousseau", jsonData)
	defer tmp.File.Close()
	defer os.Remove(tmp.File.Name())

	tr, err := OpenTrousseau(tmp.File.Name())
	if err != nil {
		t.Fatal(err)
	}

	assert(t, tr.CryptoType == ASYMMETRIC_ENCRYPTION, "Wrong encryption type")
	assert(t, tr.CryptoAlgorithm == GPG_ENCRYPTION, "Wrong encryption algorithm")
	equals(t, tr.Data, []byte("abc"))
}

func TestOpenTrousseau_returns_err_when_file_does_not_exist(t *testing.T) {
	_, err := OpenTrousseau("/does/not/exist")
	if err == nil {
		t.Fatalf("OpenTrousseau function didn't failed while loading non existing file")
	}
}
<|endoftext|>


<commit_before>/*
Package "matrix" provides types and operations for matrix manipulation.
*/
package matrix

type Matrix interface {
	// Return the shape of matrix, which consists of the "rows" and the "columns".
	Shape() (rows, columns int)

	// Return the "rows" of matrix.
	Rows() (rows int)

	// Return the "columns" of matrix.
	Columns() (columns int)
}
<commit_msg>Create "Row" interface and "Column" interface.<commit_after>/*
Package "matrix" provides types and operations for matrix manipulation.
*/
package matrix

type Matrix interface {
	// Return the shape of matrix, which consists of the "rows" and the "columns".
	Shape() (rows, columns int)

	// Return the "rows" of matrix.
	Rows() (rows int)

	// Return the "columns" of matrix.
	Columns() (columns int)
}

type Row interface {
}

type Column interface {
}
<|endoftext|>


<commit_before>package publish

import (
	"fmt"

	"github.com/jinzhu/gorm"
)

func isDraftMode(scope *gorm.Scope) bool {
	if draftMode, ok := scope.Get("publish:draft_mode"); ok {
		if isDraft, ok := draftMode.(bool); ok && isDraft {
			return true
		}
	}
	return false
}

func setTableAndPublishStatus(ensureDraftMode bool) func(*gorm.Scope) {
	return func(scope *gorm.Scope) {
		if scope.Value == nil {
			return
		}

		if isPublishableModel(scope.Value) {
			scope.InstanceSet("publish:supported_model", true)

			if ensureDraftMode {
				scope.Set("publish:force_draft_mode", true)
				scope.Search.Table(draftTableName(scope.TableName()))
			}

			if isDraftMode(scope) {
				if attrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
					updateAttrs := attrs.(map[string]interface{})
					updateAttrs["publish_status"] = DIRTY
					scope.InstanceSet("gorm:update_attrs", updateAttrs)
				} else {
					scope.SetColumn("PublishStatus", DIRTY)
				}
			}
		}
	}
}

func getModeAndNewScope(scope *gorm.Scope) (isProduction bool, clone *gorm.Scope) {
	if draftMode, ok := scope.Get("publish:draft_mode"); !ok || !draftMode.(bool) {
		if _, ok := scope.InstanceGet("publish:supported_model"); ok {
			table := originalTableName(scope.TableName())
			clone := scope.New(scope.Value)
			clone.Search.Table(table)
			return true, clone
		}
	}
	return false, nil
}

func syncToProductionAfterCreate(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		gorm.Create(clone)
	}
}

func syncToProductionAfterUpdate(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
			table := originalTableName(scope.TableName())
			clone.Search = scope.Search
			clone.Search.Table(table)
			clone.InstanceSet("gorm:update_attrs", updateAttrs)
		}
		gorm.Update(clone)
	}
}

func syncToProductionAfterDelete(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		gorm.Delete(clone)
	}
}

func deleteScope(scope *gorm.Scope) {
	if !scope.HasError() {
		_, supportedModel := scope.InstanceGet("publish:supported_model")
		isDraftMode, ok := scope.Get("publish:draft_mode")

		if supportedModel && (ok && isDraftMode.(bool)) {
			scope.Raw(
				fmt.Sprintf("UPDATE %v SET deleted_at=%v, publish_status=%v %v",
					scope.QuotedTableName(),
					scope.AddToVars(gorm.NowFunc()),
					scope.AddToVars(DIRTY),
					scope.CombinedConditionSql(),
				))
			scope.Exec()
		} else {
			gorm.Delete(scope)
		}
	}
}
<commit_msg>Only set publish status when updating data from draft tables<commit_after>package publish

import (
	"fmt"

	"github.com/jinzhu/gorm"
)

func isDraftMode(scope *gorm.Scope) bool {
	if draftMode, ok := scope.Get("publish:draft_mode"); ok {
		if isDraft, ok := draftMode.(bool); ok && isDraft {
			return true
		}
	}
	return false
}

func setTableAndPublishStatus(ensureDraftMode bool) func(*gorm.Scope) {
	return func(scope *gorm.Scope) {
		if scope.Value == nil {
			return
		}

		if isPublishableModel(scope.Value) {
			scope.InstanceSet("publish:supported_model", true)

			if ensureDraftMode {
				scope.Set("publish:force_draft_mode", true)
				scope.Search.Table(draftTableName(scope.TableName()))

				// Only set publish status when updating data from draft tables
				if isDraftMode(scope) {
					if attrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
						updateAttrs := attrs.(map[string]interface{})
						updateAttrs["publish_status"] = DIRTY
						scope.InstanceSet("gorm:update_attrs", updateAttrs)
					} else {
						scope.SetColumn("PublishStatus", DIRTY)
					}
				}
			}
		}
	}
}

func getModeAndNewScope(scope *gorm.Scope) (isProduction bool, clone *gorm.Scope) {
	if draftMode, ok := scope.Get("publish:draft_mode"); !ok || !draftMode.(bool) {
		if _, ok := scope.InstanceGet("publish:supported_model"); ok {
			table := originalTableName(scope.TableName())
			clone := scope.New(scope.Value)
			clone.Search.Table(table)
			return true, clone
		}
	}
	return false, nil
}

func syncToProductionAfterCreate(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		gorm.Create(clone)
	}
}

func syncToProductionAfterUpdate(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok {
			table := originalTableName(scope.TableName())
			clone.Search = scope.Search
			clone.Search.Table(table)
			clone.InstanceSet("gorm:update_attrs", updateAttrs)
		}
		gorm.Update(clone)
	}
}

func syncToProductionAfterDelete(scope *gorm.Scope) {
	if ok, clone := getModeAndNewScope(scope); ok {
		gorm.Delete(clone)
	}
}

func deleteScope(scope *gorm.Scope) {
	if !scope.HasError() {
		_, supportedModel := scope.InstanceGet("publish:supported_model")
		isDraftMode, ok := scope.Get("publish:draft_mode")

		if supportedModel && (ok && isDraftMode.(bool)) {
			scope.Raw(
				fmt.Sprintf("UPDATE %v SET deleted_at=%v, publish_status=%v %v",
					scope.QuotedTableName(),
					scope.AddToVars(gorm.NowFunc()),
					scope.AddToVars(DIRTY),
					scope.CombinedConditionSql(),
				))
			scope.Exec()
		} else {
			gorm.Delete(scope)
		}
	}
}
<|endoftext|>


<commit_before>// Get the number of open files for a process and compare that against /proc/<pid>/limits and alert if
// over the given threshold.
//
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package main

import (
//	"encoding/json"
	"flag"
	"fmt"
	"github.com/yieldbot/dhuran"
//	"github.com/yieldbot/dracky"
//	"github.com/olivere/elastic"
	// "io/ioutil"
  "strconv"
	"os"
  "os/exec"
//	"time"
)

// Get the pid for the supplied process
func get_pid(app string) string {
  go_pid := strconv.Itoa(os.Getpid())
  fmt.Printf(go_pid)
  ps_aef := exec.Command("ps", "-aef")
  grep_find := exec.Command("grep", app)
  grep_exclude := exec.Command("grep", "-v", go_pid)

  outPipe, err := ps_aef.StdoutPipe()
  if err != nil {
    dhuran.Check(err)
  }

  ps_aef.Start()
  grep_find.Stdin = outPipe

  outGrep, err := grep_find.StdoutPipe()
  if err != nil {
    dhuran.Check(err)
  }
fmt.Printf("one\n")
  // fmt.Printf("%v",outGrep)
  grep_exclude.Stdin = outGrep
fmt.Printf("two\n")
  out, err := grep_exclude.Output()
  fmt.Printf("three\n")
  // fmt.Printf(out)
  if err != nil {

    fmt.Printf("%v\n", err)
    // dhuran.Check(err)
  }
  fmt.Printf("four\n")
  defer outPipe.Close()
  defer outGrep.Close()

fmt.Printf(go_pid)

  return string(out)
}

// Calculate if the value is over a threshold
// func determine_threshold(val int, threshold int) bool {
//
// }
//
// // Get the current number of open file handles for the process
// func get_file_handles(pid string) int {
//
// }

func main() {

	// set commandline flags
	// PidPtr := flag.String("pid", "1", "the pid for the process you wish to check")
	AppPtr := flag.String("app", "sbin/init", "the process name")
	WarnPtr := flag.Int("warn", 75, "the alert warning threshold percentage")
	CritPtr := flag.Int("crit", 75, "the alert critical threshold percentage")

	flag.Parse()
	// PidPtr := *PidPtr
	app := *AppPtr
	warn_threshold := *WarnPtr
	crit_threshold := *CritPtr

	// I don't want to call these if they are not needed
	// sensu_event := new(dracky.Sensu_Event)
	// user_event := new(dracky.User_Event)
	//t_format := *timePtr

	// sensu_env := dracky.Set_sensu_env()

	//   if t_format != "" {
	//     // get the format of the time
	//     es_index = es_index + t_format
	//   }

	if app != "" {
    pid := get_pid(app)
    fmt.Printf(pid)
  } else {
    fmt.Printf("Please enter a process name to check")
		os.Exit(100)
    }

    fmt.Printf(out)
    fmt.Printf("%v , %v\n", warn_threshold, crit_threshold)

	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// 	err = json.Unmarshal(user_input, &user_event)
	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// 	es_type = "user"
	// } else if (rd_stdin == false) && (input_file == "") {
	// 	fmt.Printf("Please enter a file to read from")
	// 	os.Exit(1)
	// } else {
	// 	sensu_event = sensu_event.Acquire_sensu_event()
	// }
  //
	// // Create a client
	// client, err := elastic.NewClient(
	// 	elastic.SetURL("http://" + es_host + ":" + es_port),
	// )
	// if err != nil {
	// 	dhuran.Check(err)
	// }
  //
	// // Check to see if the index exists and if not create it
	// if client.IndexExists == nil { // need to test to make sure this does what I want
	// 	_, err = client.CreateIndex(es_index).Do()
	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// }
  //
	// // Create an Elasticsearch document. The document type will define the mapping used for the document.
	// doc := make(map[string]string)
	// var doc_id string
	// switch es_type {
	// case "sensu":
	// 	doc_id = dracky.Event_name(sensu_event.Client.Name, sensu_event.Check.Name)
	// 	doc["monitored_instance"] = sensu_event.Acquire_monitored_instance()
	// 	doc["sensu_client"] = sensu_event.Client.Name
	// 	doc["incident_timestamp"] = time.Unix(sensu_event.Check.Issued, 0).Format(time.RFC822Z)
	// 	doc["check_name"] = dracky.Create_check_name(sensu_event.Check.Name)
	// 	doc["check_state"] = dracky.Define_status(sensu_event.Check.Status)
	// 	doc["sensu_env"] = dracky.Define_sensu_env(sensu_env.Sensu.Environment)
	// 	doc["instance_address"] = sensu_event.Client.Address
	// 	doc["check_state_duration"] = dracky.Define_check_state_duration()
	// case "user":
	// 	doc["product"] = user_event.Product
	// 	doc["data"] = user_event.Data
	// 	doc["timestamp"] = time.Unix(sensu_event.Check.Issued, 0).Format(time.RFC822Z) // dracky.Set_time(user_event.Timestamp)
	// default:
	// 	fmt.Printf("Type is not correctly set")
	// 	os.Exit(2)
	// }
  //
	// // Add a document to the Elasticsearch index
	// _, err = client.Index().
	// 	Index(es_index).
	// 	Type(es_type).
	// 	Id(doc_id).
	// 	BodyJson(doc).
	// 	Do()
	// if err != nil {
	// 	dhuran.Check(err)
	// }
  //
	// // Log a successful document push to stdout. I don't add the id here as some id's are fixed but
	// // the user has the ability to autogenerate an id if they don't want to provide one.
	// fmt.Printf("Record added to ES\n")
}
<commit_msg>will get the pid for a given process, excluding itself<commit_after>// Get the number of open files for a process and compare that against /proc/<pid>/limits and alert if
// over the given threshold.
//
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package main

import (
//	"encoding/json"
	"flag"
	"fmt"
	"github.com/yieldbot/dhuran"
//	"github.com/yieldbot/dracky"
//	"github.com/olivere/elastic"
	// "io/ioutil"
  // "github.com/shirou/gopsutil/process"
  "strconv"
  "regexp"
  "strings"
	"os"
  "os/exec"
//	"time"
)

// Get the pid for the supplied process
func get_pid(app string) string {
  pid_exp := regexp.MustCompile("[0-9]+")
  go_pid := os.Getpid()
  var a_pid string
  fmt.Printf("golang binary pid: %v\n", go_pid)

  ps_aef := exec.Command("ps", "-aef")

  out, err := ps_aef.Output()
  if err != nil {
    dhuran.Check(err)
  }

  ps_aef.Start()

  lines := strings.Split(string(out), "\n")
  for i := range lines {
    if (strings.Contains(lines[i], app) && ! strings.Contains(lines[i], strconv.Itoa(go_pid))){
      // fmt.Printf("%v\n", lines[i])
      a_pid = pid_exp.FindString(lines[i])
      return a_pid
      // matty := strings.Split(lines[i]," ")
    // for j := range matty {
    //   fmt.Printf("%v\n", matty[j])
    // }
    //     return lines[i]
    }
  }
  return ""
}

// Calculate if the value is over a threshold
// func determine_threshold(val int, threshold int) bool {
//
// }
//
// // Get the current number of open file handles for the process
// func get_file_handles(pid string) int {
//
// }

func main() {

	// set commandline flags
	AppPtr := flag.String("app", "sbin/init", "the process name")
	WarnPtr := flag.Int("warn", 75, "the alert warning threshold percentage")
	CritPtr := flag.Int("crit", 75, "the alert critical threshold percentage")

	flag.Parse()
	app := *AppPtr
	warn_threshold := *WarnPtr
	crit_threshold := *CritPtr

  var app_pid string

	if app != "" {
    // YELLOW check for a null or nil string
    // need to check for the process better, regex?
    app_pid = get_pid(app)

  } else {
    fmt.Printf("Please enter a process name to check")
		os.Exit(100)
    }

    fmt.Printf("warning threshold: %v, critical threshold: %v\n", warn_threshold, crit_threshold)
    fmt.Printf("app pid is: %v\n", app_pid)

	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// 	err = json.Unmarshal(user_input, &user_event)
	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// 	es_type = "user"
	// } else if (rd_stdin == false) && (input_file == "") {
	// 	fmt.Printf("Please enter a file to read from")
	// 	os.Exit(1)
	// } else {
	// 	sensu_event = sensu_event.Acquire_sensu_event()
	// }
  //
	// // Create a client
	// client, err := elastic.NewClient(
	// 	elastic.SetURL("http://" + es_host + ":" + es_port),
	// )
	// if err != nil {
	// 	dhuran.Check(err)
	// }
  //
	// // Check to see if the index exists and if not create it
	// if client.IndexExists == nil { // need to test to make sure this does what I want
	// 	_, err = client.CreateIndex(es_index).Do()
	// 	if err != nil {
	// 		dhuran.Check(err)
	// 	}
	// }
  //
	// // Create an Elasticsearch document. The document type will define the mapping used for the document.
	// doc := make(map[string]string)
	// var doc_id string
	// switch es_type {
	// case "sensu":
	// 	doc_id = dracky.Event_name(sensu_event.Client.Name, sensu_event.Check.Name)
	// 	doc["monitored_instance"] = sensu_event.Acquire_monitored_instance()
	// 	doc["sensu_client"] = sensu_event.Client.Name
	// 	doc["incident_timestamp"] = time.Unix(sensu_event.Check.Issued, 0).Format(time.RFC822Z)
	// 	doc["check_name"] = dracky.Create_check_name(sensu_event.Check.Name)
	// 	doc["check_state"] = dracky.Define_status(sensu_event.Check.Status)
	// 	doc["sensu_env"] = dracky.Define_sensu_env(sensu_env.Sensu.Environment)
	// 	doc["instance_address"] = sensu_event.Client.Address
	// 	doc["check_state_duration"] = dracky.Define_check_state_duration()
	// case "user":
	// 	doc["product"] = user_event.Product
	// 	doc["data"] = user_event.Data
	// 	doc["timestamp"] = time.Unix(sensu_event.Check.Issued, 0).Format(time.RFC822Z) // dracky.Set_time(user_event.Timestamp)
	// default:
	// 	fmt.Printf("Type is not correctly set")
	// 	os.Exit(2)
	// }
  //
	// // Add a document to the Elasticsearch index
	// _, err = client.Index().
	// 	Index(es_index).
	// 	Type(es_type).
	// 	Id(doc_id).
	// 	BodyJson(doc).
	// 	Do()
	// if err != nil {
	// 	dhuran.Check(err)
	// }
  //
	// // Log a successful document push to stdout. I don't add the id here as some id's are fixed but
	// // the user has the ability to autogenerate an id if they don't want to provide one.
	// fmt.Printf("Record added to ES\n")
}
<|endoftext|>


<commit_before>package copy

import (
	"io"

	internalblobinfocache "github.com/containers/image/v5/internal/blobinfocache"
	"github.com/containers/image/v5/pkg/compression"
	compressiontypes "github.com/containers/image/v5/pkg/compression/types"
	"github.com/containers/image/v5/types"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// bpDetectCompressionStepData contains data that the copy pipeline needs about the “detect compression” step.
type bpDetectCompressionStepData struct {
	isCompressed      bool
	format            compressiontypes.Algorithm        // Valid if isCompressed
	decompressor      compressiontypes.DecompressorFunc // Valid if isCompressed
	srcCompressorName string                            // Compressor name to possibly record in the blob info cache for the source blob.
}

// blobPipelineDetectCompressionStep updates *stream to detect its current compression format.
// srcInfo is only used for error messages.
// Returns data for other steps.
func blobPipelineDetectCompressionStep(stream *sourceStream, srcInfo types.BlobInfo) (bpDetectCompressionStepData, error) {
	// This requires us to “peek ahead” into the stream to read the initial part, which requires us to chain through another io.Reader returned by DetectCompression.
	format, decompressor, reader, err := compression.DetectCompressionFormat(stream.reader) // We could skip this in some cases, but let's keep the code path uniform
	if err != nil {
		return bpDetectCompressionStepData{}, errors.Wrapf(err, "reading blob %s", srcInfo.Digest)
	}
	stream.reader = reader

	res := bpDetectCompressionStepData{
		isCompressed: decompressor != nil,
		format:       format,
		decompressor: decompressor,
	}
	if res.isCompressed {
		res.srcCompressorName = format.Name()
	} else {
		res.srcCompressorName = internalblobinfocache.Uncompressed
	}

	if expectedFormat, known := expectedCompressionFormats[stream.info.MediaType]; known && res.isCompressed && format.Name() != expectedFormat.Name() {
		logrus.Debugf("blob %s with type %s should be compressed with %s, but compressor appears to be %s", srcInfo.Digest.String(), srcInfo.MediaType, expectedFormat.Name(), format.Name())
	}
	return res, nil
}

// bpCompressionStepData contains data that the copy pipeline needs about the compression step.
type bpCompressionStepData struct {
	operation              types.LayerCompression      // Operation to use for updating the blob metadata.
	uploadedAlgorithm      *compressiontypes.Algorithm // An algorithm parameter for the compressionOperation edits.
	uploadedAnnotations    map[string]string           // Annotations that should be set on the uploaded blob. WARNING: This is only set after the srcStream.reader is fully consumed.
	srcCompressorName      string                      // Compressor name to record in the blob info cache for the source blob.
	uploadedCompressorName string                      // Compressor name to record in the blob info cache for the uploaded blob.
	closers                []io.Closer                 // Objects to close after the upload is done, if any.
}

// blobPipelineCompressionStep updates *stream to compress and/or decompress it.
// srcInfo is only used for error messages.
// Returns data for other steps; the caller should eventually call updateCompressionEdits and perhaps recordValidatedBlobData,
// and must eventually call close.
func (c *copier) blobPipelineCompressionStep(stream *sourceStream, canModifyBlob bool,
	detected bpDetectCompressionStepData) (*bpCompressionStepData, error) {
	// WARNING: If you are adding new reasons to change the blob, update also the OptimizeDestinationImageAlreadyExists
	// short-circuit conditions
	var closers []io.Closer
	succeeded := false
	defer func() {
		if !succeeded {
			for _, c := range closers {
				c.Close()
			}
		}
	}()
	if canModifyBlob && isOciEncrypted(stream.info.MediaType) {
		// PreserveOriginal due to any compression not being able to be done on an encrypted blob unless decrypted
		logrus.Debugf("Using original blob without modification for encrypted blob")
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.PreserveOriginal,
			uploadedAlgorithm:      nil,
			srcCompressorName:      internalblobinfocache.UnknownCompression,
			uploadedCompressorName: internalblobinfocache.UnknownCompression,
			closers:                closers,
		}, nil
	} else if canModifyBlob && c.dest.DesiredLayerCompression() == types.Compress && !detected.isCompressed {
		logrus.Debugf("Compressing blob on the fly")
		pipeReader, pipeWriter := io.Pipe()
		closers = append(closers, pipeReader)

		var uploadedAlgorithm *compressiontypes.Algorithm
		if c.compressionFormat != nil {
			uploadedAlgorithm = c.compressionFormat
		} else {
			uploadedAlgorithm = defaultCompressionFormat
		}
		annotations := map[string]string{}
		// If this fails while writing data, it will do pipeWriter.CloseWithError(); if it fails otherwise,
		// e.g. because we have exited and due to pipeReader.Close() above further writing to the pipe has failed,
		// we don’t care.
		go c.compressGoroutine(pipeWriter, stream.reader, annotations, *uploadedAlgorithm) // Closes pipeWriter
		stream.reader = pipeReader
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.Compress,
			uploadedAlgorithm:      uploadedAlgorithm,
			uploadedAnnotations:    annotations,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: uploadedAlgorithm.Name(),
			closers:                closers,
		}, nil
	}
	if canModifyBlob && c.dest.DesiredLayerCompression() == types.Compress && detected.isCompressed &&
		c.compressionFormat != nil && c.compressionFormat.Name() != detected.format.Name() {
		// When the blob is compressed, but the desired format is different, it first needs to be decompressed and finally
		// re-compressed using the desired format.
		logrus.Debugf("Blob will be converted")

		decompressed, err := detected.decompressor(stream.reader)
		if err != nil {
			return nil, err
		}
		closers = append(closers, decompressed)

		pipeReader, pipeWriter := io.Pipe()
		closers = append(closers, pipeReader)

		annotations := map[string]string{}
		go c.compressGoroutine(pipeWriter, decompressed, annotations, *c.compressionFormat) // Closes pipeWriter

		stream.reader = pipeReader
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.PreserveOriginal,
			uploadedAlgorithm:      c.compressionFormat,
			uploadedAnnotations:    annotations,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: c.compressionFormat.Name(),
			closers:                closers,
		}, nil
	}
	if canModifyBlob && c.dest.DesiredLayerCompression() == types.Decompress && detected.isCompressed {
		logrus.Debugf("Blob will be decompressed")
		s, err := detected.decompressor(stream.reader)
		if err != nil {
			return nil, err
		}
		closers = append(closers, s)
		stream.reader = s
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.Decompress,
			uploadedAlgorithm:      nil,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: internalblobinfocache.Uncompressed,
			closers:                closers,
		}, nil
	}
	// PreserveOriginal might also need to recompress the original blob if the desired compression format is different.
	logrus.Debugf("Using original blob without modification")
	// Remember if the original blob was compressed, and if so how, so that if
	// LayerInfosForCopy() returned something that differs from what was in the
	// source's manifest, and UpdatedImage() needs to call UpdateLayerInfos(),
	// it will be able to correctly derive the MediaType for the copied blob.
	var algorithm *compressiontypes.Algorithm
	if detected.isCompressed {
		algorithm = &detected.format
	} else {
		algorithm = nil
	}
	succeeded = true
	return &bpCompressionStepData{
		operation:              types.PreserveOriginal,
		uploadedAlgorithm:      algorithm,
		srcCompressorName:      detected.srcCompressorName,
		uploadedCompressorName: detected.srcCompressorName,
		closers:                closers,
	}, nil
}

// updateCompressionEdits sets *operation, *algorithm and updates *annotations, if necessary.
func (d *bpCompressionStepData) updateCompressionEdits(operation *types.LayerCompression, algorithm **compressiontypes.Algorithm, annotations *map[string]string) {
	*operation = d.operation
	// If we can modify the layer's blob, set the desired algorithm for it to be set in the manifest.
	*algorithm = d.uploadedAlgorithm
	if *annotations == nil {
		*annotations = map[string]string{}
	}
	for k, v := range d.uploadedAnnotations {
		(*annotations)[k] = v
	}
}

// recordValidatedBlobData updates b.blobInfoCache with data about the created uploadedInfo adnd the original srcInfo.
// This must ONLY be called if all data has been validated by OUR code, and is not comming from third parties.
func (d *bpCompressionStepData) recordValidatedDigestData(c *copier, uploadedInfo types.BlobInfo, srcInfo types.BlobInfo,
	encryptionStep *bpEncryptionStepData, decryptionStep *bpDecryptionStepData) error {
	// Don’t record any associations that involve encrypted data. This is a bit crude,
	// some blob substitutions (replacing pulls of encrypted data with local reuse of known decryption outcomes)
	// might be safe, but it’s not trivially obvious, so let’s be conservative for now.
	// This crude approach also means we don’t need to record whether a blob is encrypted
	// in the blob info cache (which would probably be necessary for any more complex logic),
	// and the simplicity is attractive.
	if !encryptionStep.encrypting && !decryptionStep.decrypting {
		// If d.operation != types.PreserveOriginal, we now have two reliable digest values:
		// srcinfo.Digest describes the pre-d.operation input, verified by digestingReader
		// uploadedInfo.Digest describes the post-d.operation output, computed by PutBlob
		// (because stream.info.Digest == "", this must have been computed afresh).
		switch d.operation {
		case types.PreserveOriginal:
			break // Do nothing, we have only one digest and we might not have even verified it.
		case types.Compress:
			c.blobInfoCache.RecordDigestUncompressedPair(uploadedInfo.Digest, srcInfo.Digest)
		case types.Decompress:
			c.blobInfoCache.RecordDigestUncompressedPair(srcInfo.Digest, uploadedInfo.Digest)
		default:
			return errors.Errorf("Internal error: Unexpected d.operation value %#v", d.operation)
		}
	}
	if d.uploadedCompressorName != "" && d.uploadedCompressorName != internalblobinfocache.UnknownCompression {
		c.blobInfoCache.RecordDigestCompressorName(uploadedInfo.Digest, d.uploadedCompressorName)
	}
	if srcInfo.Digest != "" && d.srcCompressorName != "" && d.srcCompressorName != internalblobinfocache.UnknownCompression {
		c.blobInfoCache.RecordDigestCompressorName(srcInfo.Digest, d.srcCompressorName)
	}
	return nil
}

// close closes objects that carry state throughout the compression/decompression operation.
func (d *bpCompressionStepData) close() {
	for _, c := range d.closers {
		c.Close()
	}
}

// doCompression reads all input from src and writes its compressed equivalent to dest.
func doCompression(dest io.Writer, src io.Reader, metadata map[string]string, compressionFormat compressiontypes.Algorithm, compressionLevel *int) error {
	compressor, err := compression.CompressStreamWithMetadata(dest, metadata, compressionFormat, compressionLevel)
	if err != nil {
		return err
	}

	buf := make([]byte, compressionBufferSize)

	_, err = io.CopyBuffer(compressor, src, buf) // Sets err to nil, i.e. causes dest.Close()
	if err != nil {
		compressor.Close()
		return err
	}

	return compressor.Close()
}

// compressGoroutine reads all input from src and writes its compressed equivalent to dest.
func (c *copier) compressGoroutine(dest *io.PipeWriter, src io.Reader, metadata map[string]string, compressionFormat compressiontypes.Algorithm) {
	err := errors.New("Internal error: unexpected panic in compressGoroutine")
	defer func() { // Note that this is not the same as {defer dest.CloseWithError(err)}; we need err to be evaluated lazily.
		_ = dest.CloseWithError(err) // CloseWithError(nil) is equivalent to Close(), always returns nil
	}()

	err = doCompression(dest, src, metadata, compressionFormat, c.compressionLevel)
}
<commit_msg>Factor out copier.compressedStream from copier.blobPipelineCompressionStep<commit_after>package copy

import (
	"io"

	internalblobinfocache "github.com/containers/image/v5/internal/blobinfocache"
	"github.com/containers/image/v5/pkg/compression"
	compressiontypes "github.com/containers/image/v5/pkg/compression/types"
	"github.com/containers/image/v5/types"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// bpDetectCompressionStepData contains data that the copy pipeline needs about the “detect compression” step.
type bpDetectCompressionStepData struct {
	isCompressed      bool
	format            compressiontypes.Algorithm        // Valid if isCompressed
	decompressor      compressiontypes.DecompressorFunc // Valid if isCompressed
	srcCompressorName string                            // Compressor name to possibly record in the blob info cache for the source blob.
}

// blobPipelineDetectCompressionStep updates *stream to detect its current compression format.
// srcInfo is only used for error messages.
// Returns data for other steps.
func blobPipelineDetectCompressionStep(stream *sourceStream, srcInfo types.BlobInfo) (bpDetectCompressionStepData, error) {
	// This requires us to “peek ahead” into the stream to read the initial part, which requires us to chain through another io.Reader returned by DetectCompression.
	format, decompressor, reader, err := compression.DetectCompressionFormat(stream.reader) // We could skip this in some cases, but let's keep the code path uniform
	if err != nil {
		return bpDetectCompressionStepData{}, errors.Wrapf(err, "reading blob %s", srcInfo.Digest)
	}
	stream.reader = reader

	res := bpDetectCompressionStepData{
		isCompressed: decompressor != nil,
		format:       format,
		decompressor: decompressor,
	}
	if res.isCompressed {
		res.srcCompressorName = format.Name()
	} else {
		res.srcCompressorName = internalblobinfocache.Uncompressed
	}

	if expectedFormat, known := expectedCompressionFormats[stream.info.MediaType]; known && res.isCompressed && format.Name() != expectedFormat.Name() {
		logrus.Debugf("blob %s with type %s should be compressed with %s, but compressor appears to be %s", srcInfo.Digest.String(), srcInfo.MediaType, expectedFormat.Name(), format.Name())
	}
	return res, nil
}

// bpCompressionStepData contains data that the copy pipeline needs about the compression step.
type bpCompressionStepData struct {
	operation              types.LayerCompression      // Operation to use for updating the blob metadata.
	uploadedAlgorithm      *compressiontypes.Algorithm // An algorithm parameter for the compressionOperation edits.
	uploadedAnnotations    map[string]string           // Annotations that should be set on the uploaded blob. WARNING: This is only set after the srcStream.reader is fully consumed.
	srcCompressorName      string                      // Compressor name to record in the blob info cache for the source blob.
	uploadedCompressorName string                      // Compressor name to record in the blob info cache for the uploaded blob.
	closers                []io.Closer                 // Objects to close after the upload is done, if any.
}

// blobPipelineCompressionStep updates *stream to compress and/or decompress it.
// srcInfo is only used for error messages.
// Returns data for other steps; the caller should eventually call updateCompressionEdits and perhaps recordValidatedBlobData,
// and must eventually call close.
func (c *copier) blobPipelineCompressionStep(stream *sourceStream, canModifyBlob bool,
	detected bpDetectCompressionStepData) (*bpCompressionStepData, error) {
	// WARNING: If you are adding new reasons to change the blob, update also the OptimizeDestinationImageAlreadyExists
	// short-circuit conditions
	var closers []io.Closer
	succeeded := false
	defer func() {
		if !succeeded {
			for _, c := range closers {
				c.Close()
			}
		}
	}()
	if canModifyBlob && isOciEncrypted(stream.info.MediaType) {
		// PreserveOriginal due to any compression not being able to be done on an encrypted blob unless decrypted
		logrus.Debugf("Using original blob without modification for encrypted blob")
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.PreserveOriginal,
			uploadedAlgorithm:      nil,
			srcCompressorName:      internalblobinfocache.UnknownCompression,
			uploadedCompressorName: internalblobinfocache.UnknownCompression,
			closers:                closers,
		}, nil
	} else if canModifyBlob && c.dest.DesiredLayerCompression() == types.Compress && !detected.isCompressed {
		logrus.Debugf("Compressing blob on the fly")
		var uploadedAlgorithm *compressiontypes.Algorithm
		if c.compressionFormat != nil {
			uploadedAlgorithm = c.compressionFormat
		} else {
			uploadedAlgorithm = defaultCompressionFormat
		}
		reader, annotations := c.compressedStream(stream.reader, *uploadedAlgorithm)
		closers = append(closers, reader)
		stream.reader = reader
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.Compress,
			uploadedAlgorithm:      uploadedAlgorithm,
			uploadedAnnotations:    annotations,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: uploadedAlgorithm.Name(),
			closers:                closers,
		}, nil
	}
	if canModifyBlob && c.dest.DesiredLayerCompression() == types.Compress && detected.isCompressed &&
		c.compressionFormat != nil && c.compressionFormat.Name() != detected.format.Name() {
		// When the blob is compressed, but the desired format is different, it first needs to be decompressed and finally
		// re-compressed using the desired format.
		logrus.Debugf("Blob will be converted")

		decompressed, err := detected.decompressor(stream.reader)
		if err != nil {
			return nil, err
		}
		closers = append(closers, decompressed)

		recompressed, annotations := c.compressedStream(decompressed, *c.compressionFormat)
		closers = append(closers, recompressed)
		stream.reader = recompressed
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.PreserveOriginal,
			uploadedAlgorithm:      c.compressionFormat,
			uploadedAnnotations:    annotations,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: c.compressionFormat.Name(),
			closers:                closers,
		}, nil
	}
	if canModifyBlob && c.dest.DesiredLayerCompression() == types.Decompress && detected.isCompressed {
		logrus.Debugf("Blob will be decompressed")
		s, err := detected.decompressor(stream.reader)
		if err != nil {
			return nil, err
		}
		closers = append(closers, s)
		stream.reader = s
		stream.info = types.BlobInfo{ // FIXME? Should we preserve more data in src.info?
			Digest: "",
			Size:   -1,
		}
		succeeded = true
		return &bpCompressionStepData{
			operation:              types.Decompress,
			uploadedAlgorithm:      nil,
			srcCompressorName:      detected.srcCompressorName,
			uploadedCompressorName: internalblobinfocache.Uncompressed,
			closers:                closers,
		}, nil
	}
	// PreserveOriginal might also need to recompress the original blob if the desired compression format is different.
	logrus.Debugf("Using original blob without modification")
	// Remember if the original blob was compressed, and if so how, so that if
	// LayerInfosForCopy() returned something that differs from what was in the
	// source's manifest, and UpdatedImage() needs to call UpdateLayerInfos(),
	// it will be able to correctly derive the MediaType for the copied blob.
	var algorithm *compressiontypes.Algorithm
	if detected.isCompressed {
		algorithm = &detected.format
	} else {
		algorithm = nil
	}
	succeeded = true
	return &bpCompressionStepData{
		operation:              types.PreserveOriginal,
		uploadedAlgorithm:      algorithm,
		srcCompressorName:      detected.srcCompressorName,
		uploadedCompressorName: detected.srcCompressorName,
		closers:                closers,
	}, nil
}

// updateCompressionEdits sets *operation, *algorithm and updates *annotations, if necessary.
func (d *bpCompressionStepData) updateCompressionEdits(operation *types.LayerCompression, algorithm **compressiontypes.Algorithm, annotations *map[string]string) {
	*operation = d.operation
	// If we can modify the layer's blob, set the desired algorithm for it to be set in the manifest.
	*algorithm = d.uploadedAlgorithm
	if *annotations == nil {
		*annotations = map[string]string{}
	}
	for k, v := range d.uploadedAnnotations {
		(*annotations)[k] = v
	}
}

// recordValidatedBlobData updates b.blobInfoCache with data about the created uploadedInfo adnd the original srcInfo.
// This must ONLY be called if all data has been validated by OUR code, and is not comming from third parties.
func (d *bpCompressionStepData) recordValidatedDigestData(c *copier, uploadedInfo types.BlobInfo, srcInfo types.BlobInfo,
	encryptionStep *bpEncryptionStepData, decryptionStep *bpDecryptionStepData) error {
	// Don’t record any associations that involve encrypted data. This is a bit crude,
	// some blob substitutions (replacing pulls of encrypted data with local reuse of known decryption outcomes)
	// might be safe, but it’s not trivially obvious, so let’s be conservative for now.
	// This crude approach also means we don’t need to record whether a blob is encrypted
	// in the blob info cache (which would probably be necessary for any more complex logic),
	// and the simplicity is attractive.
	if !encryptionStep.encrypting && !decryptionStep.decrypting {
		// If d.operation != types.PreserveOriginal, we now have two reliable digest values:
		// srcinfo.Digest describes the pre-d.operation input, verified by digestingReader
		// uploadedInfo.Digest describes the post-d.operation output, computed by PutBlob
		// (because stream.info.Digest == "", this must have been computed afresh).
		switch d.operation {
		case types.PreserveOriginal:
			break // Do nothing, we have only one digest and we might not have even verified it.
		case types.Compress:
			c.blobInfoCache.RecordDigestUncompressedPair(uploadedInfo.Digest, srcInfo.Digest)
		case types.Decompress:
			c.blobInfoCache.RecordDigestUncompressedPair(srcInfo.Digest, uploadedInfo.Digest)
		default:
			return errors.Errorf("Internal error: Unexpected d.operation value %#v", d.operation)
		}
	}
	if d.uploadedCompressorName != "" && d.uploadedCompressorName != internalblobinfocache.UnknownCompression {
		c.blobInfoCache.RecordDigestCompressorName(uploadedInfo.Digest, d.uploadedCompressorName)
	}
	if srcInfo.Digest != "" && d.srcCompressorName != "" && d.srcCompressorName != internalblobinfocache.UnknownCompression {
		c.blobInfoCache.RecordDigestCompressorName(srcInfo.Digest, d.srcCompressorName)
	}
	return nil
}

// close closes objects that carry state throughout the compression/decompression operation.
func (d *bpCompressionStepData) close() {
	for _, c := range d.closers {
		c.Close()
	}
}

// doCompression reads all input from src and writes its compressed equivalent to dest.
func doCompression(dest io.Writer, src io.Reader, metadata map[string]string, compressionFormat compressiontypes.Algorithm, compressionLevel *int) error {
	compressor, err := compression.CompressStreamWithMetadata(dest, metadata, compressionFormat, compressionLevel)
	if err != nil {
		return err
	}

	buf := make([]byte, compressionBufferSize)

	_, err = io.CopyBuffer(compressor, src, buf) // Sets err to nil, i.e. causes dest.Close()
	if err != nil {
		compressor.Close()
		return err
	}

	return compressor.Close()
}

// compressGoroutine reads all input from src and writes its compressed equivalent to dest.
func (c *copier) compressGoroutine(dest *io.PipeWriter, src io.Reader, metadata map[string]string, compressionFormat compressiontypes.Algorithm) {
	err := errors.New("Internal error: unexpected panic in compressGoroutine")
	defer func() { // Note that this is not the same as {defer dest.CloseWithError(err)}; we need err to be evaluated lazily.
		_ = dest.CloseWithError(err) // CloseWithError(nil) is equivalent to Close(), always returns nil
	}()

	err = doCompression(dest, src, metadata, compressionFormat, c.compressionLevel)
}

// compressedStream returns a stream the input reader compressed using format, and a metadata map.
// The caller must close the returned reader.
// AFTER the stream is consumed, metadata will be updated with annotations to use on the data.
func (c *copier) compressedStream(reader io.Reader, algorithm compressiontypes.Algorithm) (io.ReadCloser, map[string]string) {
	pipeReader, pipeWriter := io.Pipe()
	annotations := map[string]string{}
	// If this fails while writing data, it will do pipeWriter.CloseWithError(); if it fails otherwise,
	// e.g. because we have exited and due to pipeReader.Close() above further writing to the pipe has failed,
	// we don’t care.
	go c.compressGoroutine(pipeWriter, reader, annotations, algorithm) // Closes pipeWriter
	return pipeReader, annotations
}
<|endoftext|>


<commit_before>package melody

import (
	"github.com/gorilla/websocket"
	"net/http"
)

type handleMessageFunc func(*Session, []byte)
type handleErrorFunc func(*Session, error)
type handleSessionFunc func(*Session)
type filterFunc func(*Session) bool

type Melody struct {
	Config               *Config
	Upgrader             *websocket.Upgrader
	messageHandler       handleMessageFunc
	messageHandlerBinary handleMessageFunc
	errorHandler         handleErrorFunc
	connectHandler       handleSessionFunc
	disconnectHandler    handleSessionFunc
	hub                  *hub
}

// Returns a new melody instance with default Upgrader and Config.
func New() *Melody {
	upgrader := &websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}

	hub := newHub()

	go hub.run()

	return &Melody{
		Config:               newConfig(),
		Upgrader:             upgrader,
		messageHandler:       func(*Session, []byte) {},
		messageHandlerBinary: func(*Session, []byte) {},
		errorHandler:         func(*Session, error) {},
		connectHandler:       func(*Session) {},
		disconnectHandler:    func(*Session) {},
		hub:                  hub,
	}
}

// Fires fn when a session connects.
func (m *Melody) HandleConnect(fn func(*Session)) {
	m.connectHandler = fn
}

// Fires fn when a session disconnects.
func (m *Melody) HandleDisconnect(fn func(*Session)) {
	m.disconnectHandler = fn
}

// Callback when a text message comes in.
func (m *Melody) HandleMessage(fn func(*Session, []byte)) {
	m.messageHandler = fn
}

// Callback when a binary message comes in.
func (m *Melody) HandleMessageBinary(fn func(*Session, []byte)) {
	m.messageHandlerBinary = fn
}

// Fires when a session has an error.
func (m *Melody) HandleError(fn func(*Session, error)) {
	m.errorHandler = fn
}

// Handles http requests and upgrades them to websocket connections.
func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) {
	conn, err := m.Upgrader.Upgrade(w, r, nil)

	if err != nil {
		m.errorHandler(nil, err)
		return
	}

	session := &Session{
		Request: r,
		params:  make(map[string]string),
		conn:    conn,
		output:  make(chan *envelope, m.Config.MessageBufferSize),
		melody:  m,
	}

	m.hub.register <- session

	go m.connectHandler(session)

	go session.writePump()

	session.readPump()

	if m.hub.open {
		m.hub.unregister <- session
	}

	go m.disconnectHandler(session)
}

// Broadcasts a text message to all sessions.
func (m *Melody) Broadcast(msg []byte) {
	message := &envelope{t: websocket.TextMessage, msg: msg}
	m.hub.broadcast <- message
}

// Broadcasts a text message to all sessions that fn returns true for.
func (m *Melody) BroadcastFilter(msg []byte, fn func(*Session) bool) {
	message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn}
	m.hub.broadcast <- message
}

// Broadcasts a text message to all sessions except session s.
func (m *Melody) BroadcastOthers(msg []byte, s *Session) {
	m.BroadcastFilter(msg, func(q *Session) bool {
		return s != q
	})
}

// Broadcasts a binary message to all sessions.
func (m *Melody) BroadcastBinary(msg []byte) {
	message := &envelope{t: websocket.BinaryMessage, msg: msg}
	m.hub.broadcast <- message
}

// Broadcasts a binary message to all sessions that fn returns true for.
func (m *Melody) BroadcastBinaryFilter(msg []byte, fn func(*Session) bool) {
	message := &envelope{t: websocket.BinaryMessage, msg: msg, filter: fn}
	m.hub.broadcast <- message
}

// Broadcasts a binary message to all sessions except session s.
func (m *Melody) BroadcastBinaryOthers(msg []byte, s *Session) {
	m.BroadcastBinaryFilter(msg, func(q *Session) bool {
		return s != q
	})
}

// Closes the melody instance and all connected sessions.
func (m *Melody) Close() {
	m.hub.exit <- true
}
<commit_msg>Always call the connect handler before any message handler.<commit_after>package melody

import (
	"github.com/gorilla/websocket"
	"net/http"
)

type handleMessageFunc func(*Session, []byte)
type handleErrorFunc func(*Session, error)
type handleSessionFunc func(*Session)
type filterFunc func(*Session) bool

type Melody struct {
	Config               *Config
	Upgrader             *websocket.Upgrader
	messageHandler       handleMessageFunc
	messageHandlerBinary handleMessageFunc
	errorHandler         handleErrorFunc
	connectHandler       handleSessionFunc
	disconnectHandler    handleSessionFunc
	hub                  *hub
}

// Returns a new melody instance with default Upgrader and Config.
func New() *Melody {
	upgrader := &websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}

	hub := newHub()

	go hub.run()

	return &Melody{
		Config:               newConfig(),
		Upgrader:             upgrader,
		messageHandler:       func(*Session, []byte) {},
		messageHandlerBinary: func(*Session, []byte) {},
		errorHandler:         func(*Session, error) {},
		connectHandler:       func(*Session) {},
		disconnectHandler:    func(*Session) {},
		hub:                  hub,
	}
}

// Fires fn when a session connects.
func (m *Melody) HandleConnect(fn func(*Session)) {
	m.connectHandler = fn
}

// Fires fn when a session disconnects.
func (m *Melody) HandleDisconnect(fn func(*Session)) {
	m.disconnectHandler = fn
}

// Callback when a text message comes in.
func (m *Melody) HandleMessage(fn func(*Session, []byte)) {
	m.messageHandler = fn
}

// Callback when a binary message comes in.
func (m *Melody) HandleMessageBinary(fn func(*Session, []byte)) {
	m.messageHandlerBinary = fn
}

// Fires when a session has an error.
func (m *Melody) HandleError(fn func(*Session, error)) {
	m.errorHandler = fn
}

// Handles http requests and upgrades them to websocket connections.
func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) {
	conn, err := m.Upgrader.Upgrade(w, r, nil)

	if err != nil {
		m.errorHandler(nil, err)
		return
	}

	session := &Session{
		Request: r,
		params:  make(map[string]string),
		conn:    conn,
		output:  make(chan *envelope, m.Config.MessageBufferSize),
		melody:  m,
	}

	m.hub.register <- session

	m.connectHandler(session)

	go session.writePump()

	session.readPump()

	if m.hub.open {
		m.hub.unregister <- session
	}

	go m.disconnectHandler(session)
}

// Broadcasts a text message to all sessions.
func (m *Melody) Broadcast(msg []byte) {
	message := &envelope{t: websocket.TextMessage, msg: msg}
	m.hub.broadcast <- message
}

// Broadcasts a text message to all sessions that fn returns true for.
func (m *Melody) BroadcastFilter(msg []byte, fn func(*Session) bool) {
	message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn}
	m.hub.broadcast <- message
}

// Broadcasts a text message to all sessions except session s.
func (m *Melody) BroadcastOthers(msg []byte, s *Session) {
	m.BroadcastFilter(msg, func(q *Session) bool {
		return s != q
	})
}

// Broadcasts a binary message to all sessions.
func (m *Melody) BroadcastBinary(msg []byte) {
	message := &envelope{t: websocket.BinaryMessage, msg: msg}
	m.hub.broadcast <- message
}

// Broadcasts a binary message to all sessions that fn returns true for.
func (m *Melody) BroadcastBinaryFilter(msg []byte, fn func(*Session) bool) {
	message := &envelope{t: websocket.BinaryMessage, msg: msg, filter: fn}
	m.hub.broadcast <- message
}

// Broadcasts a binary message to all sessions except session s.
func (m *Melody) BroadcastBinaryOthers(msg []byte, s *Session) {
	m.BroadcastBinaryFilter(msg, func(q *Session) bool {
		return s != q
	})
}

// Closes the melody instance and all connected sessions.
func (m *Melody) Close() {
	m.hub.exit <- true
}
<|endoftext|>