<commit_before>package resolves

import (
	"strconv"
	"strings"
	"time"

	"github.com/hysios/apiai-go"
	"github.com/wanliu/brain_data/database"
	"github.com/wanliu/flow/builtin/ai"

	. "github.com/wanliu/flow/context"
)

// 处理开单的逻辑结构, 不需要是组件
// 作为context的一个部分，或者存在一个Value中
type OrderResolve struct {
	AiParams  ai.AiOrder
	Products  ItemsResolve
	Gifts     ItemsResolve
	Address   string
	Customer  string
	Time      time.Time
	DefTime   string
	Current   Resolve
	Note      string
	UpdatedAt time.Time
	Editing   bool
	Canceled  bool

	User *database.User
}

func NewOrderResolve(ctx Context) *OrderResolve {
	resolve := new(OrderResolve)
	resolve.Touch()

	aiResult := ctx.Value("Result").(apiai.Result)

	resolve.AiParams = ai.ApiAiOrder{AiResult: aiResult}
	resolve.ExtractFromParams()

	if viewer := ctx.Value("Viewer"); viewer != nil {
		user := viewer.(*database.User)
		resolve.User = user
	}

	return resolve
}

func (r *OrderResolve) Solve(aiResult apiai.Result) string {
	return r.Answer()
}

func (r *OrderResolve) Touch() {
	r.UpdatedAt = time.Now()
}

func (r OrderResolve) Modifable(expireMin int) bool {
	return !r.Expired(expireMin) || r.Submited()
}

// TODO
func (r OrderResolve) Cancelable() bool {
	return true
}

// TODO
func (r *OrderResolve) Cancel() bool {
	r.Canceled = true
	return true
}

func (r OrderResolve) Fulfiled() bool {
	return len(r.Products.Products) > 0 && (r.Address != "" || r.Customer != "")
}

func (r OrderResolve) Expired(expireMin int) bool {
	return r.UpdatedAt.Add(time.Duration(expireMin)*time.Minute).UnixNano() < time.Now().UnixNano()
}

// TODO
func (r OrderResolve) Submited() bool {
	return false
}

// 从ｌｕｉｓ数据构造结构数据
func (r *OrderResolve) ExtractFromParams() {
	r.ExtractItems()
	r.ExtractGiftItems()
	r.ExtractAddress()
	r.ExtractCustomer()
	r.ExtractTime()
	r.ExtractNote()
}

func (r *OrderResolve) ExtractItems() {
	for _, i := range r.AiParams.Items() {
		name := strings.Replace(i.Product, "%", "%%", -1)
		item := &ItemResolve{
			Resolved: true,
			Name:     name,
			Price:    i.Price,
			Quantity: i.Quantity,
			Product:  name,
		}

		r.Products.Products = append(r.Products.Products, item)
	}
}

func (r *OrderResolve) ExtractGiftItems() {
	for _, i := range r.AiParams.GiftItems() {
		name := strings.Replace(i.Product, "%", "%%", -1)
		item := &ItemResolve{
			Resolved: true,
			Name:     name,
			Price:    i.Price,
			Quantity: i.Quantity,
			Product:  name,
		}

		r.Gifts.Products = append(r.Gifts.Products, item)
	}
}

func (r *OrderResolve) ExtractAddress() {
	r.Address = r.AiParams.Address()
}

func (r *OrderResolve) ExtractCustomer() {
	r.Customer = r.AiParams.Customer()
}

func (r *OrderResolve) ExtractTime() {
	r.Time = r.AiParams.Time()
}

func (r *OrderResolve) ExtractNote() {
	r.Note = r.AiParams.Note()
}

func (r *OrderResolve) SetDefTime(t string) {
	r.DefTime = t

	if r.Time.IsZero() && r.DefTime != "" {
		r.SetTimeByDef()
	}
}

func (r *OrderResolve) SetTimeByDef() {
	if r.DefTime == "今天" {
		r.Time = time.Now()
	} else if r.DefTime == "明天" {
		r.Time = time.Now().Add(24 * time.Hour)
	}
}

func (r OrderResolve) EmptyProducts() bool {
	return len(r.Products.Products) == 0
}

func (r OrderResolve) Answer() string {
	if r.Fulfiled() {
		return r.PostOrderAndAnswer()
	} else {
		return r.AnswerHead() + r.AnswerFooter("", "")
	}
}

func (r *OrderResolve) PostOrderAndAnswer() string {
	items := make([]database.OrderItem, 0, 0)
	gifts := make([]database.GiftItem, 0, 0)

	for _, pr := range r.Products.Products {
		 NewOrderItem(productId, proName string, quantity uint, price float64)
		item, err := database.NewOrderItem("", pr.Product, uint(pr.Quantity), pr.Price)
		if err != nil {
			return err.Error()
		}
		items = append(items, *item)
	}

	for _, pr := range r.Gifts.Products {
		gift, err := database.NewGiftItem("", pr.Product, uint(pr.Quantity))
		if err != nil {
			return err.Error()
		}

		gifts = append(gifts, *gift)
	}

	order, err := r.User.CreateSaledOrder(r.Address, r.Note, r.Time, 0, items, gifts)

	if err != nil {
		return err.Error()
	} else {
		return r.AnswerHead() + r.AnswerBody() + r.AnswerFooter(order.ID, order.GlobelId())
	}
}

func (r OrderResolve) AddressInfo() string {
	if r.Address != "" && r.Customer != "" {
		return "地址:" + r.Address + r.Customer + "\n"
	} else if r.Address != "" {
		return "地址:" + r.Address + "\n"
	} else if r.Customer != "" {
		return "客户:" + r.Customer + "\n"
	} else {
		return ""
	}
}

func (r OrderResolve) AnswerHead() string {
	desc := "订单正在处理, 已经添加" + CnNum(len(r.Products.Products)) + "种产品"

	if r.Fulfiled() {
		desc = "订单已经生成, 共" + CnNum(len(r.Products.Products)) + "种产品"
	}

	if len(r.Gifts.Products) > 0 {
		desc = desc + ", " + CnNum(len(r.Gifts.Products)) + "种赠品" + "\n"
	} else {
		desc = desc + "\n"
	}

	return desc
}

func (r OrderResolve) AnswerBody() string {
	desc := ""

	for _, p := range r.Products.Products {
		desc = desc + p.Product + " " + strconv.Itoa(p.Quantity) + "件\n"
	}

	if len(r.Gifts.Products) > 0 {
		desc = desc + "申请的赠品:\n"

		for _, g := range r.Gifts.Products {
			desc = desc + g.Product + " " + strconv.Itoa(g.Quantity) + "件\n"
		}
	}

	desc = desc + "时间:" + r.Time.Format("2006年01月02日") + "\n"

	if r.Note != "" {
		desc = desc + "备注：" + r.Note + "\n"
	}

	return desc
}

func (r OrderResolve) AnswerFooter(no, id interface{}) string {
	desc := ""

	if r.Fulfiled() {
		desc = desc + r.AddressInfo()
		desc = desc + "订单已经生成，订单号为：" + fmt.Sprint(no) + "\n"
		desc = desc + "订单入口: http://wanliu.biz/orders/" + fmt.Sprint(id)
	} else {
		desc = desc + "还缺少收货地址或客户信息\n"
	}

	return desc
}

func CnNum(num int) string {
	switch num {
	case 1:
		return "一"
	case 2:
		return "两"
	case 3:
		return "三"
	case 4:
		return "四"
	case 5:
		return "五"
	case 6:
		return "六"
	case 7:
		return "七"
	case 8:
		return "八"
	case 9:
		return "九"
	case 10:
		return "十"
	default:
		return strconv.Itoa(num)
	}
}
<commit_msg>create order for user<commit_after>package resolves

import (
	"strconv"
	"strings"
	"time"

	"github.com/hysios/apiai-go"
	"github.com/wanliu/brain_data/database"
	"github.com/wanliu/flow/builtin/ai"

	. "github.com/wanliu/flow/context"
)

// 处理开单的逻辑结构, 不需要是组件
// 作为context的一个部分，或者存在一个Value中
type OrderResolve struct {
	AiParams  ai.AiOrder
	Products  ItemsResolve
	Gifts     ItemsResolve
	Address   string
	Customer  string
	Time      time.Time
	DefTime   string
	Current   Resolve
	Note      string
	UpdatedAt time.Time
	Editing   bool
	Canceled  bool

	User *database.User
}

func NewOrderResolve(ctx Context) *OrderResolve {
	resolve := new(OrderResolve)
	resolve.Touch()

	aiResult := ctx.Value("Result").(apiai.Result)

	resolve.AiParams = ai.ApiAiOrder{AiResult: aiResult}
	resolve.ExtractFromParams()

	if viewer := ctx.Value("Viewer"); viewer != nil {
		user := viewer.(*database.User)
		resolve.User = user
	}

	return resolve
}

func (r *OrderResolve) Solve(aiResult apiai.Result) string {
	return r.Answer()
}

func (r *OrderResolve) Touch() {
	r.UpdatedAt = time.Now()
}

func (r OrderResolve) Modifable(expireMin int) bool {
	return !r.Expired(expireMin) || r.Submited()
}

// TODO
func (r OrderResolve) Cancelable() bool {
	return true
}

// TODO
func (r *OrderResolve) Cancel() bool {
	r.Canceled = true
	return true
}

func (r OrderResolve) Fulfiled() bool {
	return len(r.Products.Products) > 0 && (r.Address != "" || r.Customer != "")
}

func (r OrderResolve) Expired(expireMin int) bool {
	return r.UpdatedAt.Add(time.Duration(expireMin)*time.Minute).UnixNano() < time.Now().UnixNano()
}

// TODO
func (r OrderResolve) Submited() bool {
	return false
}

// 从ｌｕｉｓ数据构造结构数据
func (r *OrderResolve) ExtractFromParams() {
	r.ExtractItems()
	r.ExtractGiftItems()
	r.ExtractAddress()
	r.ExtractCustomer()
	r.ExtractTime()
	r.ExtractNote()
}

func (r *OrderResolve) ExtractItems() {
	for _, i := range r.AiParams.Items() {
		name := strings.Replace(i.Product, "%", "%%", -1)
		item := &ItemResolve{
			Resolved: true,
			Name:     name,
			Price:    i.Price,
			Quantity: i.Quantity,
			Product:  name,
		}

		r.Products.Products = append(r.Products.Products, item)
	}
}

func (r *OrderResolve) ExtractGiftItems() {
	for _, i := range r.AiParams.GiftItems() {
		name := strings.Replace(i.Product, "%", "%%", -1)
		item := &ItemResolve{
			Resolved: true,
			Name:     name,
			Price:    i.Price,
			Quantity: i.Quantity,
			Product:  name,
		}

		r.Gifts.Products = append(r.Gifts.Products, item)
	}
}

func (r *OrderResolve) ExtractAddress() {
	r.Address = r.AiParams.Address()
}

func (r *OrderResolve) ExtractCustomer() {
	r.Customer = r.AiParams.Customer()
}

func (r *OrderResolve) ExtractTime() {
	r.Time = r.AiParams.Time()
}

func (r *OrderResolve) ExtractNote() {
	r.Note = r.AiParams.Note()
}

func (r *OrderResolve) SetDefTime(t string) {
	r.DefTime = t

	if r.Time.IsZero() && r.DefTime != "" {
		r.SetTimeByDef()
	}
}

func (r *OrderResolve) SetTimeByDef() {
	if r.DefTime == "今天" {
		r.Time = time.Now()
	} else if r.DefTime == "明天" {
		r.Time = time.Now().Add(24 * time.Hour)
	}
}

func (r OrderResolve) EmptyProducts() bool {
	return len(r.Products.Products) == 0
}

func (r OrderResolve) Answer() string {
	if r.Fulfiled() {
		return r.PostOrderAndAnswer()
	} else {
		return r.AnswerHead() + r.AnswerFooter("", "")
	}
}

func (r *OrderResolve) PostOrderAndAnswer() string {
	items := make([]database.OrderItem, 0, 0)
	gifts := make([]database.GiftItem, 0, 0)

	for _, pr := range r.Products.Products {
		item, err := database.NewOrderItem("", pr.Product, uint(pr.Quantity), pr.Price)
		if err != nil {
			return err.Error()
		}
		items = append(items, *item)
	}

	for _, pr := range r.Gifts.Products {
		gift, err := database.NewGiftItem("", pr.Product, uint(pr.Quantity))
		if err != nil {
			return err.Error()
		}

		gifts = append(gifts, *gift)
	}

	order, err := r.User.CreateSaledOrder(r.Address, r.Note, r.Time, 0, items, gifts)

	if err != nil {
		return err.Error()
	} else {
		return r.AnswerHead() + r.AnswerBody() + r.AnswerFooter(order.ID, order.GlobelId())
	}
}

func (r OrderResolve) AddressInfo() string {
	if r.Address != "" && r.Customer != "" {
		return "地址:" + r.Address + r.Customer + "\n"
	} else if r.Address != "" {
		return "地址:" + r.Address + "\n"
	} else if r.Customer != "" {
		return "客户:" + r.Customer + "\n"
	} else {
		return ""
	}
}

func (r OrderResolve) AnswerHead() string {
	desc := "订单正在处理, 已经添加" + CnNum(len(r.Products.Products)) + "种产品"

	if r.Fulfiled() {
		desc = "订单已经生成, 共" + CnNum(len(r.Products.Products)) + "种产品"
	}

	if len(r.Gifts.Products) > 0 {
		desc = desc + ", " + CnNum(len(r.Gifts.Products)) + "种赠品" + "\n"
	} else {
		desc = desc + "\n"
	}

	return desc
}

func (r OrderResolve) AnswerBody() string {
	desc := ""

	for _, p := range r.Products.Products {
		desc = desc + p.Product + " " + strconv.Itoa(p.Quantity) + "件\n"
	}

	if len(r.Gifts.Products) > 0 {
		desc = desc + "申请的赠品:\n"

		for _, g := range r.Gifts.Products {
			desc = desc + g.Product + " " + strconv.Itoa(g.Quantity) + "件\n"
		}
	}

	desc = desc + "时间:" + r.Time.Format("2006年01月02日") + "\n"

	if r.Note != "" {
		desc = desc + "备注：" + r.Note + "\n"
	}

	return desc
}

func (r OrderResolve) AnswerFooter(no, id interface{}) string {
	desc := ""

	if r.Fulfiled() {
		desc = desc + r.AddressInfo()
		desc = desc + "订单已经生成，订单号为：" + fmt.Sprint(no) + "\n"
		desc = desc + "订单入口: http://wanliu.biz/orders/" + fmt.Sprint(id)
	} else {
		desc = desc + "还缺少收货地址或客户信息\n"
	}

	return desc
}

func CnNum(num int) string {
	switch num {
	case 1:
		return "一"
	case 2:
		return "两"
	case 3:
		return "三"
	case 4:
		return "四"
	case 5:
		return "五"
	case 6:
		return "六"
	case 7:
		return "七"
	case 8:
		return "八"
	case 9:
		return "九"
	case 10:
		return "十"
	default:
		return strconv.Itoa(num)
	}
}
<|endoftext|>


<commit_before>package tablestorageproxy

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"
)

type GoHaveStorage interface {
	GetKey() []byte
	GetAccount() string
}

type TableStorageProxy struct {
	goHaveStorage GoHaveStorage
	baseUrl string
}

func New(goHaveStorage GoHaveStorage) *TableStorageProxy {
	var tableStorageProxy TableStorageProxy

	tableStorageProxy.goHaveStorage = goHaveStorage
	tableStorageProxy.baseUrl = "https://"+goHaveStorage.GetAccount()+".table.core.windows.net/"

	return &tableStorageProxy
}

func (tableStorageProxy *TableStorageProxy) QueryTables() {
	tableStorageProxy.get("Tables", "")
}

func (tableStorageProxy *TableStorageProxy) QueryEntity(tableName string, partitionKey string, rowKey string, selects string) {
	tableStorageProxy.get(tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", "?$select="+selects)
}

func (tableStorageProxy *TableStorageProxy) QueryEntities(tableName string, selects string, filter string, top string) {
	tableStorageProxy.get(tableName, "?$filter="+filter + "&$select=" + selects+"&$top="+top)
}

func (tableStorageProxy *TableStorageProxy) DeleteEntity(tableName string, partitionKey string, rowKey string) {
	tableStorageProxy.executeEntityRequest("DELETE",tableName, partitionKey, rowKey, nil, true)
}

func (tableStorageProxy *TableStorageProxy) UpdateEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("PUT",tableName, partitionKey, rowKey, json, true)
}

func (tableStorageProxy *TableStorageProxy) MergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("MERGE",tableName, partitionKey, rowKey, json, true)
}

func (tableStorageProxy *TableStorageProxy) InsertOrMergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("MERGE",tableName, partitionKey, rowKey, json, false)
}

func (tableStorageProxy *TableStorageProxy) InsertOrReplaceEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("PUT",tableName, partitionKey, rowKey, json, false)
}

func (tableStorageProxy *TableStorageProxy) DeleteTable(tableName string) {
	target := "Tables%28%27" + tableName + "%27%29"

	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Content-Type", "application/atom+xml")

	tableStorageProxy.executeRequest(request, client, target)
}

type CreateTableArgs struct {
	TableName string
}

func (tableStorageProxy *TableStorageProxy) CreateTable(tableName string) {
	json, _ := json.Marshal(CreateTableArgs{TableName: tableName})
	tableStorageProxy.executeCommonRequest("POST", "Tables", "", json, false)
}

func (tableStorageProxy *TableStorageProxy) InsertEntity(tableName string, json []byte) {
	tableStorageProxy.executeCommonRequest("POST", tableName, "", json, false)
}

func (tableStorageProxy *TableStorageProxy) get(target string, query string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+target + query, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, target)
}

func addPayloadHeaders(request *http.Request, bodyLength int) {
	request.Header.Set("Content-Type", "application/json")
	request.Header.Set("Content-Length", string(bodyLength))
}

func (tableStorageProxy *TableStorageProxy) executeRequest(request *http.Request, client *http.Client, target string) {
	xmsdate, Authentication := tableStorageProxy.calculateDateAndAuthentication(target)

	request.Header.Set("x-ms-date", xmsdate)
	request.Header.Set("x-ms-version", "2013-08-15")
	request.Header.Set("Authorization", Authentication)

	requestDump, _ := httputil.DumpRequest(request, true)

	fmt.Printf("Request: %s\n", requestDump)

	response, _ := client.Do(request)

	responseDump, _ := httputil.DumpResponse(response, true)
	fmt.Printf("Response: %s\n", responseDump)
}

func (tableStorageProxy *TableStorageProxy)  executeEntityRequest(httpVerb string, tableName string, partitionKey string, rowKey string, json []byte, useIfMatch bool) {
	tableStorageProxy.executeCommonRequest(httpVerb, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", "", json, useIfMatch)
}

func (tableStorageProxy *TableStorageProxy)  executeCommonRequest(httpVerb string, target string, query string, json []byte, useIfMatch bool) {
	client := &http.Client{}
	request, _ := http.NewRequest(httpVerb, tableStorageProxy.baseUrl+target+query, bytes.NewBuffer(json))

	if json != nil {
		addPayloadHeaders(request, len(json))
	}

	if useIfMatch {
		request.Header.Set("If-Match", "*")
	}

	tableStorageProxy.executeRequest(request, client, target)
}

func (tableStorageProxy *TableStorageProxy) calculateDateAndAuthentication(target string) (string, string) {
	xmsdate := strings.Replace(time.Now().UTC().Add(-time.Minute).Format(time.RFC1123), "UTC", "GMT", -1)
	SignatureString := xmsdate + "\n/" + tableStorageProxy.goHaveStorage.GetAccount() + "/" + target
	Authentication := "SharedKeyLite " + tableStorageProxy.goHaveStorage.GetAccount() + ":" + computeHmac256(SignatureString, tableStorageProxy.goHaveStorage.GetKey())
	return xmsdate, Authentication
}

func computeHmac256(message string, key []byte) string {
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
<commit_msg>Omitting get<commit_after>package tablestorageproxy

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"
)

type GoHaveStorage interface {
	GetKey() []byte
	GetAccount() string
}

type TableStorageProxy struct {
	goHaveStorage GoHaveStorage
	baseUrl string
}

func New(goHaveStorage GoHaveStorage) *TableStorageProxy {
	var tableStorageProxy TableStorageProxy

	tableStorageProxy.goHaveStorage = goHaveStorage
	tableStorageProxy.baseUrl = "https://"+goHaveStorage.GetAccount()+".table.core.windows.net/"

	return &tableStorageProxy
}

func (tableStorageProxy *TableStorageProxy) QueryTables() {
	tableStorageProxy.executeCommonRequest("GET", "Tables", "", nil, false)
}

func (tableStorageProxy *TableStorageProxy) QueryEntity(tableName string, partitionKey string, rowKey string, selects string) {
	tableStorageProxy.executeCommonRequest("GET", tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", "?$select="+selects, nil, false)
}

func (tableStorageProxy *TableStorageProxy) QueryEntities(tableName string, selects string, filter string, top string) {
	tableStorageProxy.executeCommonRequest("GET", tableName, "?$filter="+filter + "&$select=" + selects+"&$top="+top, nil, false)
}

func (tableStorageProxy *TableStorageProxy) DeleteEntity(tableName string, partitionKey string, rowKey string) {
	tableStorageProxy.executeEntityRequest("DELETE",tableName, partitionKey, rowKey, nil, true)
}

func (tableStorageProxy *TableStorageProxy) UpdateEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("PUT",tableName, partitionKey, rowKey, json, true)
}

func (tableStorageProxy *TableStorageProxy) MergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("MERGE",tableName, partitionKey, rowKey, json, true)
}

func (tableStorageProxy *TableStorageProxy) InsertOrMergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("MERGE",tableName, partitionKey, rowKey, json, false)
}

func (tableStorageProxy *TableStorageProxy) InsertOrReplaceEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("PUT",tableName, partitionKey, rowKey, json, false)
}

func (tableStorageProxy *TableStorageProxy) DeleteTable(tableName string) {
	target := "Tables%28%27" + tableName + "%27%29"

	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Content-Type", "application/atom+xml")

	tableStorageProxy.executeRequest(request, client, target)
}

type CreateTableArgs struct {
	TableName string
}

func (tableStorageProxy *TableStorageProxy) CreateTable(tableName string) {
	json, _ := json.Marshal(CreateTableArgs{TableName: tableName})
	tableStorageProxy.executeCommonRequest("POST", "Tables", "", json, false)
}

func (tableStorageProxy *TableStorageProxy) InsertEntity(tableName string, json []byte) {
	tableStorageProxy.executeCommonRequest("POST", tableName, "", json, false)
}

func addPayloadHeaders(request *http.Request, bodyLength int) {
	request.Header.Set("Content-Type", "application/json")
	request.Header.Set("Content-Length", string(bodyLength))
}

func (tableStorageProxy *TableStorageProxy) executeRequest(request *http.Request, client *http.Client, target string) {
	xmsdate, Authentication := tableStorageProxy.calculateDateAndAuthentication(target)

	request.Header.Set("x-ms-date", xmsdate)
	request.Header.Set("x-ms-version", "2013-08-15")
	request.Header.Set("Authorization", Authentication)

	requestDump, _ := httputil.DumpRequest(request, true)

	fmt.Printf("Request: %s\n", requestDump)

	response, _ := client.Do(request)

	responseDump, _ := httputil.DumpResponse(response, true)
	fmt.Printf("Response: %s\n", responseDump)
}

func (tableStorageProxy *TableStorageProxy)  executeEntityRequest(httpVerb string, tableName string, partitionKey string, rowKey string, json []byte, useIfMatch bool) {
	tableStorageProxy.executeCommonRequest(httpVerb, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", "", json, useIfMatch)
}

func (tableStorageProxy *TableStorageProxy)  executeCommonRequest(httpVerb string, target string, query string, json []byte, useIfMatch bool) {
	client := &http.Client{}
	request, _ := http.NewRequest(httpVerb, tableStorageProxy.baseUrl+target+query, bytes.NewBuffer(json))

	if json != nil {
		addPayloadHeaders(request, len(json))
	}

	if useIfMatch {
		request.Header.Set("If-Match", "*")
	}

	tableStorageProxy.executeRequest(request, client, target)
}

func (tableStorageProxy *TableStorageProxy) calculateDateAndAuthentication(target string) (string, string) {
	xmsdate := strings.Replace(time.Now().UTC().Add(-time.Minute).Format(time.RFC1123), "UTC", "GMT", -1)
	SignatureString := xmsdate + "\n/" + tableStorageProxy.goHaveStorage.GetAccount() + "/" + target
	Authentication := "SharedKeyLite " + tableStorageProxy.goHaveStorage.GetAccount() + ":" + computeHmac256(SignatureString, tableStorageProxy.goHaveStorage.GetKey())
	return xmsdate, Authentication
}

func computeHmac256(message string, key []byte) string {
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
<|endoftext|>


<commit_before>// Copyright 2017 Istio 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 server

import (
	"context"
	"errors"
	"io"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"testing"

	"google.golang.org/grpc"

	mixerpb "istio.io/api/mixer/v1"
	"istio.io/istio/mixer/pkg/config/storetest"
	"istio.io/istio/mixer/pkg/runtime"
	generatedTmplRepo "istio.io/istio/mixer/template"
	"istio.io/istio/pkg/log"
	"istio.io/istio/pkg/tracing"
	"istio.io/istio/pkg/version"
)

const (
	globalCfg = `
apiVersion: "config.istio.io/v1alpha2"
kind: attributemanifest
metadata:
  name: istio-proxy
  namespace: default
spec:
    attributes:
      source.name:
        value_type: STRING
      destination.name:
        value_type: STRING
      response.count:
        value_type: INT64
      attr.bool:
        value_type: BOOL
      attr.string:
        value_type: STRING
      attr.double:
        value_type: DOUBLE
      attr.int64:
        value_type: INT64
---
`
	serviceCfg = `
apiVersion: "config.istio.io/v1alpha2"
kind: fakeHandler
metadata:
  name: fakeHandlerConfig
  namespace: istio-system

---

apiVersion: "config.istio.io/v1alpha2"
kind: samplereport
metadata:
  name: reportInstance
  namespace: istio-system
spec:
  value: "2"
  dimensions:
    source: source.name | "mysrc"
    target_ip: destination.name | "mytarget"

---

apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
  name: rule1
  namespace: istio-system
spec:
  selector: match(destination.name, "*")
  actions:
  - handler: fakeHandlerConfig.fakeHandler
    instances:
    - reportInstance.samplereport

---
`
)

// createClient returns a Mixer gRPC client, useful for tests
func createClient(addr net.Addr) (mixerpb.MixerClient, error) {
	conn, err := grpc.Dial(addr.String(), grpc.WithInsecure())
	if err != nil {
		return nil, err
	}

	return mixerpb.NewMixerClient(conn), nil
}

func newTestServer(globalCfg, serviceCfg string) (*Server, error) {
	a := DefaultArgs()
	a.APIPort = 0
	a.MonitoringPort = 0
	a.LoggingOptions.LogGrpc = false // Avoid introducing a race to the server tests.
	a.EnableProfiling = true
	a.Templates = generatedTmplRepo.SupportedTmplInfo
	a.LivenessProbeOptions.Path = "abc"
	a.LivenessProbeOptions.UpdateInterval = 2
	a.ReadinessProbeOptions.Path = "def"
	a.ReadinessProbeOptions.UpdateInterval = 3

	var err error
	if a.ConfigStore, err = storetest.SetupStoreForTest(globalCfg, serviceCfg); err != nil {
		return nil, err
	}

	return New(a)
}

func TestBasic(t *testing.T) {
	s, err := newTestServer(globalCfg, serviceCfg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}

	d := s.Dispatcher()
	if d != s.dispatcher {
		t.Fatalf("returned dispatcher is incorrect")
	}

	err = s.Close()
	if err != nil {
		t.Errorf("Got error during Close: %v", err)
	}
}

func TestClient(t *testing.T) {
	s, err := newTestServer(globalCfg, serviceCfg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}

	s.Run()

	c, err := createClient(s.Addr())
	if err != nil {
		t.Errorf("Creating client failed: %v", err)
	}

	req := &mixerpb.ReportRequest{}
	_, err = c.Report(context.Background(), req)

	if err != nil {
		t.Errorf("Got error during Report: %v", err)
	}

	err = s.Close()
	if err != nil {
		t.Errorf("Got error during Close: %v", err)
	}

	err = s.Wait()
	if err == nil {
		t.Errorf("Got success, expecting failure")
	}
}

func TestErrors(t *testing.T) {
	a := DefaultArgs()
	a.APIWorkerPoolSize = -1
	a.LoggingOptions.LogGrpc = false // Avoid introducing a race to the server tests.
	configStore, cerr := storetest.SetupStoreForTest(globalCfg, serviceCfg)
	if cerr != nil {
		t.Fatal(cerr)
	}
	a.ConfigStore = configStore

	s, err := New(a)
	if s != nil || err == nil {
		t.Errorf("Got success, expecting error")
	}

	a = DefaultArgs()
	a.APIPort = 0
	a.MonitoringPort = 0
	a.TracingOptions.LogTraceSpans = true
	a.LoggingOptions.LogGrpc = false // Avoid introducing a race to the server tests.

	// This test is designed to exercise the many failure paths in the server creation
	// code. This is mostly about replacing methods in the patch table with methods that
	// return failures in order to make sure the failure recovery code is working right.
	// There are also some cases that tweak some parameters to tickle particular execution paths.
	// So for all these cases, we expect to get a failure when trying to create the server instance.

	for i := 0; i < 20; i++ {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			a.ConfigStore = configStore
			a.ConfigStoreURL = ""
			pt := newPatchTable()
			switch i {
			case 1:
				a.ConfigStore = nil
				a.ConfigStoreURL = ""
			case 2:
				a.ConfigStore = nil
				a.ConfigStoreURL = "DEADBEEF"
			case 3:
				pt.configTracing = func(_ string, _ *tracing.Options) (io.Closer, error) {
					return nil, errors.New("BAD")
				}
			case 4:
				pt.startMonitor = func(port uint16, enableProfiling bool, lf listenFunc) (*monitor, error) {
					return nil, errors.New("BAD")
				}
			case 5:
				a.MonitoringPort = 1234
				pt.listen = func(network string, address string) (net.Listener, error) {
					// fail any net.Listen call that's not for the monitoring port.
					if address != ":1234" {
						return nil, errors.New("BAD")
					}
					return net.Listen(network, address)
				}
			case 6:
				a.MonitoringPort = 1234
				pt.listen = func(network string, address string) (net.Listener, error) {
					// fail the net.Listen call that's for the monitoring port.
					if address == ":1234" {
						return nil, errors.New("BAD")
					}
					return net.Listen(network, address)
				}
			case 7:
				a.ConfigStoreURL = "http://abogusurl.com"
			case 8:
				pt.configLog = func(options *log.Options) error {
					return errors.New("BAD")
				}
			case 9:
				pt.runtimeListen = func(rt *runtime.Runtime) error {
					return errors.New("BAD")
				}
			default:
				return
			}

			s, err = newServer(a, pt)
			if s != nil || err == nil {
				t.Errorf("Got success, expecting error")
			}
		})
	}
}

func TestMonitoringMux(t *testing.T) {
	configStore, _ := storetest.SetupStoreForTest(globalCfg, serviceCfg)

	a := DefaultArgs()
	a.ConfigStore = configStore
	a.MonitoringPort = 0
	a.APIPort = 0
	s, err := New(a)
	if err != nil {
		t.Fatalf("Got %v, expecting success", err)
	}

	r := &http.Request{}
	r.Method = "GET"
	r.URL, _ = url.Parse("http://localhost/version")
	rw := &responseWriter{}

	// this is exercising the mux handler code in monitoring.go. The supplied rw is used to return
	// an error which causes all code paths in the mux handler code to be visited.
	s.monitor.monitoringServer.Handler.ServeHTTP(rw, r)

	v := string(rw.payload)
	if v != version.Info.String() {
		t.Errorf("Got version %v, expecting %v", v, version.Info.String())
	}

	_ = s.Close()
}

type responseWriter struct {
	payload []byte
}

func (rw *responseWriter) Header() http.Header {
	return nil
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	rw.payload = b
	return -1, errors.New("BAD")
}

func (rw *responseWriter) WriteHeader(int) {
}
<commit_msg>Fix data race in server_test.go (#4828)<commit_after>// Copyright 2017 Istio 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 server

import (
	"context"
	"errors"
	"io"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"testing"

	"google.golang.org/grpc"

	mixerpb "istio.io/api/mixer/v1"
	"istio.io/istio/mixer/pkg/config/storetest"
	"istio.io/istio/mixer/pkg/runtime"
	generatedTmplRepo "istio.io/istio/mixer/template"
	"istio.io/istio/pkg/log"
	"istio.io/istio/pkg/tracing"
	"istio.io/istio/pkg/version"
)

const (
	globalCfg = `
apiVersion: "config.istio.io/v1alpha2"
kind: attributemanifest
metadata:
  name: istio-proxy
  namespace: default
spec:
    attributes:
      source.name:
        value_type: STRING
      destination.name:
        value_type: STRING
      response.count:
        value_type: INT64
      attr.bool:
        value_type: BOOL
      attr.string:
        value_type: STRING
      attr.double:
        value_type: DOUBLE
      attr.int64:
        value_type: INT64
---
`
	serviceCfg = `
apiVersion: "config.istio.io/v1alpha2"
kind: fakeHandler
metadata:
  name: fakeHandlerConfig
  namespace: istio-system

---

apiVersion: "config.istio.io/v1alpha2"
kind: samplereport
metadata:
  name: reportInstance
  namespace: istio-system
spec:
  value: "2"
  dimensions:
    source: source.name | "mysrc"
    target_ip: destination.name | "mytarget"

---

apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
  name: rule1
  namespace: istio-system
spec:
  selector: match(destination.name, "*")
  actions:
  - handler: fakeHandlerConfig.fakeHandler
    instances:
    - reportInstance.samplereport

---
`
)

// defaultTestArgs returns result of DefaultArgs(), except with a modification to the LoggingOptions
// to avoid a data race between gRpc and the logging code.
func defaultTestArgs() *Args {
	a := DefaultArgs()
	a.LoggingOptions.LogGrpc = false // Avoid introducing a race to the server tests.
	return a
}

// createClient returns a Mixer gRPC client, useful for tests
func createClient(addr net.Addr) (mixerpb.MixerClient, error) {
	conn, err := grpc.Dial(addr.String(), grpc.WithInsecure())
	if err != nil {
		return nil, err
	}

	return mixerpb.NewMixerClient(conn), nil
}

func newTestServer(globalCfg, serviceCfg string) (*Server, error) {
	a := defaultTestArgs()
	a.APIPort = 0
	a.MonitoringPort = 0
	a.EnableProfiling = true
	a.Templates = generatedTmplRepo.SupportedTmplInfo
	a.LivenessProbeOptions.Path = "abc"
	a.LivenessProbeOptions.UpdateInterval = 2
	a.ReadinessProbeOptions.Path = "def"
	a.ReadinessProbeOptions.UpdateInterval = 3

	var err error
	if a.ConfigStore, err = storetest.SetupStoreForTest(globalCfg, serviceCfg); err != nil {
		return nil, err
	}

	return New(a)
}

func TestBasic(t *testing.T) {
	s, err := newTestServer(globalCfg, serviceCfg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}

	d := s.Dispatcher()
	if d != s.dispatcher {
		t.Fatalf("returned dispatcher is incorrect")
	}

	err = s.Close()
	if err != nil {
		t.Errorf("Got error during Close: %v", err)
	}
}

func TestClient(t *testing.T) {
	s, err := newTestServer(globalCfg, serviceCfg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}

	s.Run()

	c, err := createClient(s.Addr())
	if err != nil {
		t.Errorf("Creating client failed: %v", err)
	}

	req := &mixerpb.ReportRequest{}
	_, err = c.Report(context.Background(), req)

	if err != nil {
		t.Errorf("Got error during Report: %v", err)
	}

	err = s.Close()
	if err != nil {
		t.Errorf("Got error during Close: %v", err)
	}

	err = s.Wait()
	if err == nil {
		t.Errorf("Got success, expecting failure")
	}
}

func TestErrors(t *testing.T) {
	a := defaultTestArgs()
	a.APIWorkerPoolSize = -1
	configStore, cerr := storetest.SetupStoreForTest(globalCfg, serviceCfg)
	if cerr != nil {
		t.Fatal(cerr)
	}
	a.ConfigStore = configStore

	s, err := New(a)
	if s != nil || err == nil {
		t.Errorf("Got success, expecting error")
	}

	a = defaultTestArgs()
	a.APIPort = 0
	a.MonitoringPort = 0
	a.TracingOptions.LogTraceSpans = true

	// This test is designed to exercise the many failure paths in the server creation
	// code. This is mostly about replacing methods in the patch table with methods that
	// return failures in order to make sure the failure recovery code is working right.
	// There are also some cases that tweak some parameters to tickle particular execution paths.
	// So for all these cases, we expect to get a failure when trying to create the server instance.

	for i := 0; i < 20; i++ {
		t.Run(strconv.Itoa(i), func(t *testing.T) {
			a.ConfigStore = configStore
			a.ConfigStoreURL = ""
			pt := newPatchTable()
			switch i {
			case 1:
				a.ConfigStore = nil
				a.ConfigStoreURL = ""
			case 2:
				a.ConfigStore = nil
				a.ConfigStoreURL = "DEADBEEF"
			case 3:
				pt.configTracing = func(_ string, _ *tracing.Options) (io.Closer, error) {
					return nil, errors.New("BAD")
				}
			case 4:
				pt.startMonitor = func(port uint16, enableProfiling bool, lf listenFunc) (*monitor, error) {
					return nil, errors.New("BAD")
				}
			case 5:
				a.MonitoringPort = 1234
				pt.listen = func(network string, address string) (net.Listener, error) {
					// fail any net.Listen call that's not for the monitoring port.
					if address != ":1234" {
						return nil, errors.New("BAD")
					}
					return net.Listen(network, address)
				}
			case 6:
				a.MonitoringPort = 1234
				pt.listen = func(network string, address string) (net.Listener, error) {
					// fail the net.Listen call that's for the monitoring port.
					if address == ":1234" {
						return nil, errors.New("BAD")
					}
					return net.Listen(network, address)
				}
			case 7:
				a.ConfigStoreURL = "http://abogusurl.com"
			case 8:
				pt.configLog = func(options *log.Options) error {
					return errors.New("BAD")
				}
			case 9:
				pt.runtimeListen = func(rt *runtime.Runtime) error {
					return errors.New("BAD")
				}
			default:
				return
			}

			s, err = newServer(a, pt)
			if s != nil || err == nil {
				t.Errorf("Got success, expecting error")
			}
		})
	}
}

func TestMonitoringMux(t *testing.T) {
	configStore, _ := storetest.SetupStoreForTest(globalCfg, serviceCfg)

	a := defaultTestArgs()
	a.ConfigStore = configStore
	a.MonitoringPort = 0
	a.APIPort = 0
	s, err := New(a)
	if err != nil {
		t.Fatalf("Got %v, expecting success", err)
	}

	r := &http.Request{}
	r.Method = "GET"
	r.URL, _ = url.Parse("http://localhost/version")
	rw := &responseWriter{}

	// this is exercising the mux handler code in monitoring.go. The supplied rw is used to return
	// an error which causes all code paths in the mux handler code to be visited.
	s.monitor.monitoringServer.Handler.ServeHTTP(rw, r)

	v := string(rw.payload)
	if v != version.Info.String() {
		t.Errorf("Got version %v, expecting %v", v, version.Info.String())
	}

	_ = s.Close()
}

type responseWriter struct {
	payload []byte
}

func (rw *responseWriter) Header() http.Header {
	return nil
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	rw.payload = b
	return -1, errors.New("BAD")
}

func (rw *responseWriter) WriteHeader(int) {
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type Bongo struct {
	ConstructorName string `json:"constructorName"`
	InstanceId      string `json:"instanceId"`
}

type MachineContainer struct {
	Bongo Bongo           `json:"bongo_"`
	Data  *models.Machine `json:"data"`
	*models.Machine
}

var (
	MachineColl            = "jMachines"
	MachineConstructorName = "JMachine"
)

func GetMachines(userId bson.ObjectId) ([]*MachineContainer, error) {
	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"users.id": userId}).All(&machines)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	containers := []*MachineContainer{}

	for _, machine := range machines {
		bongo := Bongo{
			ConstructorName: MachineConstructorName,
			InstanceId:      "1", // TODO: what should go here?
		}
		container := &MachineContainer{bongo, machine, machine}

		containers = append(containers, container)
	}

	return containers, nil
}

var (
	MachineStateRunning = "Running"
)

func GetRunningVms() ([]*models.Machine, error) {
	query := bson.M{"status.state": MachineStateRunning}
	return findMachine(query)
}

func GetMachinesByUsername(username string) ([]*models.Machine, error) {
	user, err := GetUser(username)
	if err != nil {
		return nil, err
	}

	return GetOwnMachines(user.ObjectId)
}

func GetOwnMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": true},
	}}

	return findMachine(query)
}

func GetSharedMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": false, "permanent": true},
	}}

	return findMachine(query)
}

func GetCollabMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": false, "permanent": false},
	}}

	return findMachine(query)
}

func findMachine(query bson.M) ([]*models.Machine, error) {
	machines := []*models.Machine{}

	queryFn := func(c *mgo.Collection) error {
		iter := c.Find(query).Iter()

		var machine models.Machine
		for iter.Next(&machine) {
			machines = append(machines, &machine)
		}

		return iter.Close()
	}

	if err := Mongo.Run(MachineColl, queryFn); err != nil {
		return nil, err
	}

	return machines, nil
}

func UpdateMachineAlwaysOn(machineId bson.ObjectId, alwaysOn bool) error {
	query := func(c *mgo.Collection) error {
		return c.Update(
			bson.M{"_id": machineId},
			bson.M{"$set": bson.M{"meta.alwaysOn": alwaysOn}},
		)
	}

	return Mongo.Run(MachineColl, query)
}

func CreateMachine(m *models.Machine) error {
	query := func(c *mgo.Collection) error {
		return c.Insert(m)
	}

	return Mongo.Run(MachineColl, query)
}
<commit_msg>modelhelper: fix bug where machines are duplicated due to pointer use<commit_after>package modelhelper

import (
	"koding/db/models"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type Bongo struct {
	ConstructorName string `json:"constructorName"`
	InstanceId      string `json:"instanceId"`
}

type MachineContainer struct {
	Bongo Bongo           `json:"bongo_"`
	Data  *models.Machine `json:"data"`
	*models.Machine
}

var (
	MachineColl            = "jMachines"
	MachineConstructorName = "JMachine"
)

func GetMachines(userId bson.ObjectId) ([]*MachineContainer, error) {
	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"users.id": userId}).All(&machines)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	containers := []*MachineContainer{}

	for _, machine := range machines {
		bongo := Bongo{
			ConstructorName: MachineConstructorName,
			InstanceId:      "1", // TODO: what should go here?
		}
		container := &MachineContainer{bongo, machine, machine}

		containers = append(containers, container)
	}

	return containers, nil
}

var (
	MachineStateRunning = "Running"
)

func GetRunningVms() ([]*models.Machine, error) {
	query := bson.M{"status.state": MachineStateRunning}
	return findMachine(query)
}

func GetMachinesByUsername(username string) ([]*models.Machine, error) {
	user, err := GetUser(username)
	if err != nil {
		return nil, err
	}

	return GetOwnMachines(user.ObjectId)
}

func GetOwnMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": true},
	}}

	return findMachine(query)
}

func GetSharedMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": false, "permanent": true},
	}}

	return findMachine(query)
}

func GetCollabMachines(userId bson.ObjectId) ([]*models.Machine, error) {
	query := bson.M{"users": bson.M{
		"$elemMatch": bson.M{"id": userId, "owner": false, "permanent": false},
	}}

	return findMachine(query)
}

func findMachine(query bson.M) ([]*models.Machine, error) {
	machines := []*models.Machine{}

	queryFn := func(c *mgo.Collection) error {
		iter := c.Find(query).Iter()

		var machine models.Machine
		for iter.Next(&machine) {
			var newMachine models.Machine
			newMachine = machine

			machines = append(machines, &newMachine)
		}

		return iter.Close()
	}

	if err := Mongo.Run(MachineColl, queryFn); err != nil {
		return nil, err
	}

	return machines, nil
}

func UpdateMachineAlwaysOn(machineId bson.ObjectId, alwaysOn bool) error {
	query := func(c *mgo.Collection) error {
		return c.Update(
			bson.M{"_id": machineId},
			bson.M{"$set": bson.M{"meta.alwaysOn": alwaysOn}},
		)
	}

	return Mongo.Run(MachineColl, query)
}

func CreateMachine(m *models.Machine) error {
	query := func(c *mgo.Collection) error {
		return c.Insert(m)
	}

	return Mongo.Run(MachineColl, query)
}
<|endoftext|>


<commit_before>package models

import "time"

type NotificationSettings struct {
	// unique idetifier of the notification setting
	Id int64 `json:"id,string"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string"       sql:"NOT NULL"`

	// Creator of the notification settting
	AccountId int64 `json:"accountId,string"               sql:"NOT NULL"`

	// Holds dektop setting type
	DesktopSetting string `json:"desktopSetting"	sql:"NOT NULL"`

	// Holds mobile setting type
	MobileSetting string `json:"mobileSetting"			sql:"NOT NULL"`

	// Holds the data if channel is muted or not
	IsMuted bool `json:"isMuted"`

	// Holds data that getting notification when @channel is written
	// If user doesn't want to get notification
	// when written to channel @channel, @here or name of the user.
	// User uses 'suppress' feature and doesn't get notification
	IsSuppressed bool `json:"isSuppressed"`

	// Creation date of the notification settings
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the notification settings
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

const (
	// Describes that user want to be notified for all notifications
	NotificationSettings_STATUS_ALL = "all"
	// Describes that user want to be notified
	// for user's own name or with highlighted words
	NotificationSettings_STATUS_PERSONAL = "personal"
	// Describes that user doesn't want to get any notification
	NotificationSettings_STATUS_NEVER = "never"
)

func NewNotificationSettings() *NotificationSettings {
	now := time.Now().UTC()
	return &NotificationSettings{
		DesktopSetting: NotificationSettings_STATUS_ALL,
		MobileSetting:  NotificationSettings_STATUS_ALL,
		CreatedAt:      now,
		UpdatedAt:      now,
	}
}
<commit_msg>socialapi: notification settings defaults are added<commit_after>package models

import "time"

type NotificationSettings struct {
	// unique idetifier of the notification setting
	Id int64 `json:"id,string"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string"       sql:"NOT NULL"`

	// Creator of the notification settting
	AccountId int64 `json:"accountId,string"               sql:"NOT NULL"`

	// Holds dektop setting type
	DesktopSetting string `json:"desktopSetting"	sql:"NOT NULL"`

	// Holds mobile setting type
	MobileSetting string `json:"mobileSetting"			sql:"NOT NULL"`

	// Holds the data if channel is muted or not
	IsMuted bool `json:"isMuted"`

	// Holds data that getting notification when @channel is written
	// If user doesn't want to get notification
	// when written to channel @channel, @here or name of the user.
	// User uses 'suppress' feature and doesn't get notification
	IsSuppressed bool `json:"isSuppressed"`

	// Creation date of the notification settings
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the notification settings
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

const (
	// Describes that user want to be notified for all notifications
	NotificationSettings_STATUS_ALL = "all"
	// Describes that user want to be notified
	// for user's own name or with highlighted words
	NotificationSettings_STATUS_PERSONAL = "personal"
	// Describes that user doesn't want to get any notification
	NotificationSettings_STATUS_NEVER = "never"
)

func NewNotificationSettings() *NotificationSettings {
	now := time.Now().UTC()
	return &NotificationSettings{
		DesktopSetting: NotificationSettings_STATUS_ALL,
		MobileSetting:  NotificationSettings_STATUS_ALL,
		CreatedAt:      now,
		UpdatedAt:      now,
	}
}

func (ns *NotificationSettings) Defaults() *NotificationSettings {
	if ns.DesktopSetting == "" {
		ns.DesktopSetting = NotificationSettings_STATUS_ALL
	}

	if ns.MobileSetting == "" {
		ns.MobileSetting = NotificationSettings_STATUS_ALL
	}

	ns.IsMuted = false
	ns.IsSuppressed = false

	return ns
}
<|endoftext|>


<commit_before>package api

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/common/response"

	"github.com/codahale/sneaker"
)

var (
	ErrPathNotFound           = errors.New("required a path name to store keys")
	ErrRequiredValuesNotFound = errors.New("required fields not found to store")
	ErrPathContentNotFound    = errors.New("Path content not found")
)

// KeyValue holds the credentials whatever you want as key-value pair
type KeyValue map[string]interface{}

type SneakerS3 struct {
	*sneaker.Manager
}

// Store stores the given credentials on s3
func (s *SneakerS3) Store(u *url.URL, h http.Header, kv KeyValue, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")
	if pathName == "" {
		return response.NewBadRequest(ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	if kv == nil {
		return response.NewBadRequest(ErrRequiredValuesNotFound)
	}

	// convert credentials to bytes
	byt, err := json.Marshal(kv)
	if err != nil {
		return response.NewBadRequest(err)
	}

	// bytes need to imlement io.Reader interface
	// then we can use struct as 2.parameter of manager.Upload function
	aa := bytes.NewReader(byt)

	// if another requeest comes to same pathName, its data will be updated.
	// and new incoming data is gonna override the old data
	err = s.Manager.Upload(pathName, aa)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(nil)
}

func (s *SneakerS3) Get(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")
	if pathName == "" {
		return response.NewBadRequest(ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	downArray := []string{pathName}
	down, err := s.Manager.Download(downArray)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if down[pathName] == nil {
		return response.NewBadRequest(ErrPathContentNotFound)
	}

	var kv KeyValue

	downX := bytes.NewReader(down[pathName])
	if err := json.NewDecoder(downX).Decode(&kv); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(kv)
}

func (s *SneakerS3) Delete(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")
	if pathName == "" {
		return response.NewBadRequest(ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	err := s.Manager.Rm(pathName)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewDeleted()
}
<commit_msg>go: create log add suppport for handlers<commit_after>package api

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/common/response"

	"github.com/codahale/sneaker"
	"github.com/koding/logging"
)

var (
	ErrPathNotFound           = errors.New("required a path name to store keys")
	ErrRequiredValuesNotFound = errors.New("required fields not found to store")
	ErrPathContentNotFound    = errors.New("Path content not found")
)

// KeyValue holds the credentials whatever you want as key-value pair
type KeyValue map[string]interface{}

type SneakerS3 struct {
	*sneaker.Manager
	log logging.Logger
}

func createLog(context *models.Context, operation, path string, code int) string {

	log := fmt.Sprintf("Logged with IP: %v, requester: %s, operation: %s, key path: %s, response code: %d",
		context.Client.IP,
		context.Client.Account.OldId,
		operation,
		path,
		code,
	)
	return log
}

// Store stores the given credentials on s3
func (s *SneakerS3) Store(u *url.URL, h http.Header, kv KeyValue, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")

	detailedLog := createLog(context, "POST", pathName, http.StatusBadRequest)

	if pathName == "" {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, models.ErrNotLoggedIn)
	}

	if kv == nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, ErrRequiredValuesNotFound)
	}

	// convert credentials to bytes
	byt, err := json.Marshal(kv)
	if err != nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, err)
	}

	// bytes need to imlement io.Reader interface
	// then we can use struct as 2.parameter of manager.Upload function
	aa := bytes.NewReader(byt)

	// if another requeest comes to same pathName, its data will be updated.
	// and new incoming data is gonna override the old data
	err = s.Manager.Upload(pathName, aa)
	if err != nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, err)
	}

	detailedLog = createLog(context, "POST", pathName, http.StatusOK)

	s.log.Info(detailedLog)
	return response.NewOK(nil)
}

func (s *SneakerS3) Get(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")
	detailedLog := createLog(context, "GET", pathName, http.StatusBadRequest)
	if pathName == "" {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, models.ErrNotLoggedIn)
	}

	downArray := []string{pathName}
	down, err := s.Manager.Download(downArray)
	if err != nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, err)
	}

	if down[pathName] == nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, ErrPathContentNotFound)
	}

	var kv KeyValue

	downX := bytes.NewReader(down[pathName])
	if err := json.NewDecoder(downX).Decode(&kv); err != nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, err)
	}

	detailedLog = createLog(context, "GET", pathName, http.StatusOK)
	return response.NewOK(kv)
}

func (s *SneakerS3) Delete(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	pathName := u.Query().Get("pathName")
	detailedLog := createLog(context, "DELETE", pathName, http.StatusBadRequest)

	if pathName == "" {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, ErrPathNotFound)
	}

	if !context.IsLoggedIn() {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, models.ErrNotLoggedIn)
	}

	err := s.Manager.Rm(pathName)
	if err != nil {
		return response.NewBadRequestWithDetailedLogger(s.log, detailedLog, err)
	}

	detailedLog = createLog(context, "DELETE", pathName, http.StatusOK)
	return response.NewDeleted()
}
<|endoftext|>


<commit_before>// Copyright 2021 The Bazel Authors. 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 main

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"
)

type BazelJSONBuilder struct {
	bazel    *Bazel
	requests []string
}

const (
	RulesGoStdlibLabel = "@io_bazel_rules_go//:stdlib"
)

var _defaultKinds = []string{"go_library", "go_test", "go_binary"}

func (b *BazelJSONBuilder) fileQuery(filename string) string {
	if filepath.IsAbs(filename) {
		fp, _ := filepath.Rel(b.bazel.WorkspaceRoot(), filename)
		filename = fp
	}
	kinds := append(_defaultKinds, additionalKinds...)
	return fmt.Sprintf(`kind("%s", same_pkg_direct_rdeps("%s"))`, strings.Join(kinds, "|"), filename)
}

func (b *BazelJSONBuilder) packageQuery(importPath string) string {
	if strings.HasSuffix(importPath, "/...") {
		importPath = fmt.Sprintf(`^%s(/.+)?$`, strings.TrimSuffix(importPath, "/..."))
	}
	return fmt.Sprintf(`kind("go_library", attr(importpath, "%s", deps(%s)))`, importPath, bazelQueryScope)
}

func (b *BazelJSONBuilder) queryFromRequests(requests ...string) string {
	ret := make([]string, 0, len(requests))
	for _, request := range requests {
		result := ""
		if request == "." || request == "./..." {
			if bazelQueryScope != "" {
				result = fmt.Sprintf(`kind("go_library", %s)`, bazelQueryScope)
			} else {
				result = fmt.Sprintf(RulesGoStdlibLabel)
			}
		} else if request == "builtin" || request == "std" {
			result = fmt.Sprintf(RulesGoStdlibLabel)
		} else if strings.HasPrefix(request, "file=") {
			f := strings.TrimPrefix(request, "file=")
			result = b.fileQuery(f)
		} else if bazelQueryScope != "" {
			result = b.packageQuery(request)
		}
		if result != "" {
			ret = append(ret, result)
		}
	}
	if len(ret) == 0 {
		return RulesGoStdlibLabel
	}
	return strings.Join(ret, " union ")
}

func NewBazelJSONBuilder(bazel *Bazel, requests ...string) (*BazelJSONBuilder, error) {
	return &BazelJSONBuilder{
		bazel:    bazel,
		requests: requests,
	}, nil
}

func (b *BazelJSONBuilder) outputGroupsForMode(mode LoadMode) string {
	og := "go_pkg_driver_json_file,go_pkg_driver_stdlib_json_file,go_pkg_driver_srcs"
	if mode&NeedExportsFile != 0 {
		og += ",go_pkg_driver_export_file"
	}
	return og
}

func (b *BazelJSONBuilder) query(ctx context.Context, query string) ([]string, error) {
	queryArgs := concatStringsArrays(bazelFlags, bazelQueryFlags, []string{
		"--ui_event_filters=-info,-stderr",
		"--noshow_progress",
		"--order_output=no",
		"--output=label",
		"--nodep_deps",
		"--noimplicit_deps",
		"--notool_deps",
		query,
	})
	labels, err := b.bazel.Query(ctx, queryArgs...)
	if err != nil {
		return nil, fmt.Errorf("unable to query: %w", err)
	}
	return labels, nil
}

func (b *BazelJSONBuilder) Build(ctx context.Context, mode LoadMode) ([]string, error) {
	labels, err := b.query(ctx, b.queryFromRequests(b.requests...))
	if err != nil {
		return nil, fmt.Errorf("query failed: %w", err)
	}

	if len(labels) == 0 {
		return nil, fmt.Errorf("found no labels matching the requests")
	}

	aspects := append(additionalAspects, goDefaultAspect)

	buildArgs := concatStringsArrays([]string{
		"--experimental_convenience_symlinks=ignore",
		"--ui_event_filters=-info,-stderr",
		"--noshow_progress",
		"--aspects=" + strings.Join(aspects, ","),
		"--output_groups=" + b.outputGroupsForMode(mode),
		"--keep_going", // Build all possible packages
	}, bazelFlags, bazelBuildFlags, labels)
	files, err := b.bazel.Build(ctx, buildArgs...)
	if err != nil {
		return nil, fmt.Errorf("unable to bazel build %v: %w", buildArgs, err)
	}

	ret := []string{}
	for _, f := range files {
		if strings.HasSuffix(f, ".pkg.json") {
			ret = append(ret, f)
		}
	}

	return ret, nil
}

func (b *BazelJSONBuilder) PathResolver() PathResolverFunc {
	return func(p string) string {
		p = strings.Replace(p, "__BAZEL_EXECROOT__", b.bazel.ExecutionRoot(), 1)
		p = strings.Replace(p, "__BAZEL_WORKSPACE__", b.bazel.WorkspaceRoot(), 1)
		p = strings.Replace(p, "__BAZEL_OUTPUT_BASE__", b.bazel.OutputBase(), 1)
		return p
	}
}
<commit_msg>fix(packagesdrv): resolve `external/` go packages (#3332)<commit_after>// Copyright 2021 The Bazel Authors. 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 main

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"
	"regexp"
)

type BazelJSONBuilder struct {
	bazel    *Bazel
	requests []string
}

const (
	RulesGoStdlibLabel = "@io_bazel_rules_go//:stdlib"
)

var _defaultKinds = []string{"go_library", "go_test", "go_binary"}

var externalRe = regexp.MustCompile(".*\\/external\\/([^\\/]+)(\\/(.*))?\\/([^\\/]+.go)")

func (b *BazelJSONBuilder) fileQuery(filename string) string {
	label := filename

	if filepath.IsAbs(filename) {
		label, _ = filepath.Rel(b.bazel.WorkspaceRoot(), filename)
	}

	if matches := externalRe.FindStringSubmatch(filename); len(matches) == 5 {
		// if filepath is for a third party lib, we need to know, what external
		// library this file is part of.
		matches = append(matches[:2], matches[3:]...)
		label = fmt.Sprintf("@%s//%s", matches[1], strings.Join(matches[2:], ":"))
	}

	kinds := append(_defaultKinds, additionalKinds...)
	return fmt.Sprintf(`kind("%s", same_pkg_direct_rdeps("%s"))`, strings.Join(kinds, "|"), label)
}

func (b *BazelJSONBuilder) packageQuery(importPath string) string {
	if strings.HasSuffix(importPath, "/...") {
		importPath = fmt.Sprintf(`^%s(/.+)?$`, strings.TrimSuffix(importPath, "/..."))
	}
	return fmt.Sprintf(`kind("go_library", attr(importpath, "%s", deps(%s)))`, importPath, bazelQueryScope)
}

func (b *BazelJSONBuilder) queryFromRequests(requests ...string) string {
	ret := make([]string, 0, len(requests))
	for _, request := range requests {
		result := ""
		if request == "." || request == "./..." {
			if bazelQueryScope != "" {
				result = fmt.Sprintf(`kind("go_library", %s)`, bazelQueryScope)
			} else {
				result = fmt.Sprintf(RulesGoStdlibLabel)
			}
		} else if request == "builtin" || request == "std" {
			result = fmt.Sprintf(RulesGoStdlibLabel)
		} else if strings.HasPrefix(request, "file=") {
			f := strings.TrimPrefix(request, "file=")
			result = b.fileQuery(f)
		} else if bazelQueryScope != "" {
			result = b.packageQuery(request)
		}
		if result != "" {
			ret = append(ret, result)
		}
	}
	if len(ret) == 0 {
		return RulesGoStdlibLabel
	}
	return strings.Join(ret, " union ")
}

func NewBazelJSONBuilder(bazel *Bazel, requests ...string) (*BazelJSONBuilder, error) {
	return &BazelJSONBuilder{
		bazel:    bazel,
		requests: requests,
	}, nil
}

func (b *BazelJSONBuilder) outputGroupsForMode(mode LoadMode) string {
	og := "go_pkg_driver_json_file,go_pkg_driver_stdlib_json_file,go_pkg_driver_srcs"
	if mode&NeedExportsFile != 0 {
		og += ",go_pkg_driver_export_file"
	}
	return og
}

func (b *BazelJSONBuilder) query(ctx context.Context, query string) ([]string, error) {
	queryArgs := concatStringsArrays(bazelFlags, bazelQueryFlags, []string{
		"--ui_event_filters=-info,-stderr",
		"--noshow_progress",
		"--order_output=no",
		"--output=label",
		"--nodep_deps",
		"--noimplicit_deps",
		"--notool_deps",
		query,
	})
	labels, err := b.bazel.Query(ctx, queryArgs...)
	if err != nil {
		return nil, fmt.Errorf("unable to query: %w", err)
	}
	return labels, nil
}

func (b *BazelJSONBuilder) Build(ctx context.Context, mode LoadMode) ([]string, error) {
	labels, err := b.query(ctx, b.queryFromRequests(b.requests...))
	if err != nil {
		return nil, fmt.Errorf("query failed: %w", err)
	}

	if len(labels) == 0 {
		return nil, fmt.Errorf("found no labels matching the requests")
	}

	aspects := append(additionalAspects, goDefaultAspect)

	buildArgs := concatStringsArrays([]string{
		"--experimental_convenience_symlinks=ignore",
		"--ui_event_filters=-info,-stderr",
		"--noshow_progress",
		"--aspects=" + strings.Join(aspects, ","),
		"--output_groups=" + b.outputGroupsForMode(mode),
		"--keep_going", // Build all possible packages
	}, bazelFlags, bazelBuildFlags, labels)
	files, err := b.bazel.Build(ctx, buildArgs...)
	if err != nil {
		return nil, fmt.Errorf("unable to bazel build %v: %w", buildArgs, err)
	}

	ret := []string{}
	for _, f := range files {
		if strings.HasSuffix(f, ".pkg.json") {
			ret = append(ret, f)
		}
	}

	return ret, nil
}

func (b *BazelJSONBuilder) PathResolver() PathResolverFunc {
	return func(p string) string {
		p = strings.Replace(p, "__BAZEL_EXECROOT__", b.bazel.ExecutionRoot(), 1)
		p = strings.Replace(p, "__BAZEL_WORKSPACE__", b.bazel.WorkspaceRoot(), 1)
		p = strings.Replace(p, "__BAZEL_OUTPUT_BASE__", b.bazel.OutputBase(), 1)
		return p
	}
}
<|endoftext|>


<commit_before>// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX - License - Identifier: Apache - 2.0
// snippet-start:[iam.go-v2.AttachUserPolicy]
package main

import (
	"context"
	"flag"
	"fmt"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/iam"
)

// IAMAttachRolePolicyAPI defines the interface for the AttachRolePolicy function.
// We use this interface to test the function using a mocked service.
type IAMAttachRolePolicyAPI interface {
	AttachRolePolicy(ctx context.Context,
		params *iam.AttachRolePolicyInput,
		optFns ...func(*iam.Options)) (*iam.AttachRolePolicyOutput, error)
}

// AttachDynamoFullPolicy attaches an Amazon DynamoDB full-access policy to an AWS Identity and Access Management (IAM) role.
// Inputs:
//     c is the context of the method call, which includes the AWS Region.
//     api is the interface that defines the method call.
//     input defines the input arguments to the service call.
// Output:
//     If successful, an AttachRolePolicyOutput object containing the result of the service call and nil.
//     Otherwise, nil and an error from the call to AttachRolePolicy.
func AttachDynamoFullPolicy(c context.Context, api IAMAttachRolePolicyAPI, input *iam.AttachRolePolicyInput) (*iam.AttachRolePolicyOutput, error) {
	return api.AttachRolePolicy(c, input)
}

func main() {
	roleName := flag.String("r", "", "The name of the IAM role")
	flag.Parse()

	if *roleName == "" {
		fmt.Println("You must supply a role name (-r ROLE)")
		return
	}

	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		panic("configuration error, " + err.Error())
	}

	client := iam.NewFromConfig(cfg)

	policyArn := "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"

	input := &iam.AttachRolePolicyInput{
		PolicyArn: &policyArn,
		RoleName:  roleName,
	}

	_, err = AttachDynamoFullPolicy(context.TODO(), client, input)
	if err != nil {
		fmt.Println("Unable to attach DynamoDB full-access role policy to role")
		return
	}

	fmt.Println("Role attached successfully")
}

// snippet-end:[iam.go-v2.AttachUserPolicy]
<commit_msg>Updated Go IAM code example for attaching policy to a role<commit_after>// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX - License - Identifier: Apache - 2.0
// snippet-start:[iam.go-v2.AttachUserPolicy]
package main

import (
	"context"
	"flag"
	"fmt"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/iam"
)

// IAMAttachRolePolicyAPI defines the interface for the AttachRolePolicy function.
// We use this interface to test the function using a mocked service.
type IAMAttachRolePolicyAPI interface {
	AttachRolePolicy(ctx context.Context,
		params *iam.AttachRolePolicyInput,
		optFns ...func(*iam.Options)) (*iam.AttachRolePolicyOutput, error)
}

// AttachDynamoFullPolicy attaches an Amazon DynamoDB full-access policy to an AWS Identity and Access Management (IAM) role.
// Inputs:
//     c is the context of the method call, which includes the AWS Region.
//     api is the interface that defines the method call.
//     input defines the input arguments to the service call.
// Output:
//     If successful, an AttachRolePolicyOutput object containing the result of the service call and nil.
//     Otherwise, nil and an error from the call to AttachRolePolicy.
func AttachDynamoFullPolicy(c context.Context, api IAMAttachRolePolicyAPI, input *iam.AttachRolePolicyInput) (*iam.AttachRolePolicyOutput, error) {
	return api.AttachRolePolicy(c, input)
}

func main() {
	roleName := flag.String("r", "", "The name of the IAM role")
	policyName := flag.String("p", "", "The name of the policy to attach to the role")
	flag.Parse()

	if *roleName == "" || *policyName == "" {
		fmt.Println("You must supply a role and policy name (-r ROLE -p POLICY)")
		return
	}

	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		panic("configuration error, " + err.Error())
	}

	client := iam.NewFromConfig(cfg)

	policyArn := "arn:aws:iam::aws:policy/" + *policyName

	input := &iam.AttachRolePolicyInput{
		PolicyArn: &policyArn,
		RoleName:  roleName,
	}

	_, err = AttachDynamoFullPolicy(context.TODO(), client, input)
	if err != nil {
		fmt.Println("Unable to attach policy " + *policyName + " to role " + *roleName)
		return
	}

	fmt.Println("Policy " + *policyName + " attached to role " + *roleName)
}

// snippet-end:[iam.go-v2.AttachUserPolicy]
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"errors"
	"strings"
	"strconv"
	"math"
	"os"
	"path"
	"io"
	"bufio"
	"container/list"
	"github.com/jessevdk/go-flags"
)

const (
	version = "0.1.1"
)

type subtitle struct {
	text string
	start uint
	end uint
}

func die(err error) {
	fmt.Fprintf(os.Stderr, "%v\n", err)
	os.Exit(1)
}

func roundFloat64(f float64) float64 {
	val := f - float64(int64(f))
	if val >= 0.5 {
		return math.Ceil(f)
	} else if val > 0 {
		return math.Floor(f)
	} else if val <= -0.5 {
		return math.Floor(f)
	} else if val < 0 {
		return math.Ceil(f)
	}
	return f
}

/* converts hh:mm:ss,mss to milliseconds */
func time_to_msecs(tm string) (uint, error) {
	var msecs uint
	var h, m, s, ms uint

	tm = strings.Replace(tm, ".", ",", 1)
	num, err := fmt.Sscanf(tm, "%d:%d:%d,%d", &h, &m, &s, &ms)

	if num != 4 || err != nil {
		return 0, errors.New("Parsing error: Can not covert `" + tm + "' to milliseconds.")
	}

	msecs = h * 60 * 60 * 1000
	msecs += m * 60 * 1000
	msecs += s * 1000
	msecs += ms

	return msecs, nil
}

/* converts milliseconds to hh:mm:ss,mss */
func msecs_to_time(msecs uint) string {
	var h, m, s, ms uint

	h = msecs / (60 * 60 * 1000)
	msecs %= 60 * 60 * 1000
	m = msecs / (60 * 1000)
	msecs %= 60 * 1000
	s = msecs / 1000
	ms = msecs % 1000

	tm := fmt.Sprintf("%02d:%02d:%02d,%03d", h, m, s, ms)

	return tm
}

/* read SubRip (srt) file */
func read_srt(filename string) (*list.List, error) {
	var state int = 0
	var subs *list.List
	var sub *subtitle

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	r := bufio.NewReader(f)
	subs = list.New()
	sub = new(subtitle)

	for {
		var (
			isprefix bool = true
			err error = nil
			ln, line []byte
		)

		for isprefix && err == nil {
			line, isprefix, err = r.ReadLine()
			if err != nil && err != io.EOF {
				return nil, err
			}
			ln = append(ln, line...)
		}

		/* parse subtitle id */
		if state == 0 {
			/* avoid false-positive parsing error */
			if err == io.EOF && len(ln) == 0 {
				break;
			}
			id := strings.Split(string(ln), " ")
			if len(id) != 1 {
				return nil, errors.New("Parsing error: Wrong file format")
			}
			_, err = strconv.ParseUint(id[0], 10, 0)
			if err != nil {
				return nil, errors.New("Parsing error: Wrong file format")
			}
			state = 1
		/* parse start, end times */
		} else if state == 1 {
			tm := strings.Split(string(ln), " ")
			if len(tm) != 3 || tm[1] != "-->" {
				return nil, errors.New("Parsing error: Wrong file format")
			}
			sub.start, err = time_to_msecs(tm[0])
			if err != nil {
				return nil, err
			}
			sub.end, err = time_to_msecs(tm[2])
			if err != nil {
				return nil, err
			}
			state = 2
		/* parse the actual subtitle text */
		} else if state == 2 {
			if len(ln) == 0 {
				subs.PushBack(sub)
				sub = new(subtitle)
				state = 0
			} else {
				sub.text += string(ln) + "\r\n"
			}
		}

		if err == io.EOF {
			break;
		}
	}

	return subs, nil
}

/* write SubRip (srt) file */
func write_srt(filename string, subs *list.List) error {
	var id int = 0

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	w := bufio.NewWriter(f)
	defer w.Flush()

	for e := subs.Front(); e != nil; e = e.Next() {
		id++
		sub := e.Value.(*subtitle)
		fmt.Fprintf(w, "%d\r\n", id)
		fmt.Fprintf(w, "%s --> %s\r\n", msecs_to_time(sub.start), msecs_to_time(sub.end))
		fmt.Fprintf(w, "%s\r\n", sub.text)
	}

	return nil
}

/* synchronize subtitles by knowing the time of the first and the last subtitle.
 * to archive this we must use the linear equation: y = mx + b */
func sync_subs(subs *list.List, synced_first_ms uint, synced_last_ms uint) {
	var slope, yint float64

	desynced_first_ms := subs.Front().Value.(*subtitle).start
	desynced_last_ms := subs.Back().Value.(*subtitle).start

	/* m = (y2 - y1) / (x2 - x1)
	 * m: slope
	 * y2: synced_last_ms
	 * y1: synced_first_ms
	 * x2: desynced_last_ms
	 * x1: desynced_first_ms */
	slope = float64(synced_last_ms - synced_first_ms) / float64(desynced_last_ms - desynced_first_ms)
	/* b = y - mx
	 * b: yint
	 * y: synced_last_ms
	 * m: slope
	 * x: desynced_last_ms */
	yint = float64(synced_last_ms) - slope * float64(desynced_last_ms)

	for e := subs.Front(); e != nil; e = e.Next() {
		sub := e.Value.(*subtitle)
		/* y = mx + b
		 * y: sub.start and sub.end
		 * m: slope
		 * x: sub.start and sub.end
		 * b: yint */
		sub.start = uint(roundFloat64(slope * float64(sub.start) + yint))
		sub.end = uint(roundFloat64(slope * float64(sub.end) + yint))
	}
}

func main() {
	var first_ms, last_ms uint

	var opts struct {
		FirstTm string `short:"f" long:"first-sub" description:"Time of first subtitle"`
		LastTm string `short:"l" long:"last-sub" description:"Time of last subtitle"`
		InputFl string `short:"i" long:"input" description:"Input file"`
		OutputFl string `short:"o" long:"output" description:"Output file"`
		PrintVersion bool `short:"v" long:"version" description:"Print version"`
	}

	_, err := flags.Parse(&opts)
	if err != nil {
		if err.(*flags.Error).Type == flags.ErrHelp {
			fmt.Fprintf(os.Stderr, "Example:\n")
			fmt.Fprintf(os.Stderr, "  %s -f 00:01:33,492 -l 01:39:23,561 -i file.srt\n",
				path.Base(os.Args[0]))
			os.Exit(0)
		}
		os.Exit(1)
	}

	if opts.PrintVersion {
		fmt.Printf("subsync v%s\n", version)
		os.Exit(0)
	}

	if opts.InputFl == "" {
		fmt.Fprintf(os.Stderr, "You must specify an input file with -i option.\n")
		os.Exit(1)
	}

	if opts.FirstTm != "" {
		first_ms, err = time_to_msecs(opts.FirstTm)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Please check the value of -f option.\n")
			die(err)
		}
	}

	if opts.LastTm != "" {
		last_ms, err = time_to_msecs(opts.LastTm)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Please check the value of -l option.\n")
			die(err)
		}
	}

	/* if output file is not set, use the input file */
	if opts.OutputFl == "" {
		opts.OutputFl = opts.InputFl
	}

	subs, err := read_srt(opts.InputFl)
	if err != nil {
		die(err)
	}

	/* if time of the first synced subtitle is not set,
	 * use the time of the first desynced subtitle */
	if opts.FirstTm == "" {
		first_ms = subs.Front().Value.(*subtitle).start
	}

	/* if time of the last synced subtitle is not set,
	 * use the time of the last desynced subtitle */
	if opts.LastTm == "" {
		last_ms = subs.Back().Value.(*subtitle).start
	}

	if first_ms > last_ms {
		fmt.Fprintf(os.Stderr, "First subtitle can not be after last subtitle.\n")
		fmt.Fprintf(os.Stderr, "Please check the values of -f and/or -l options.\n")
		os.Exit(1)
	}

	sync_subs(subs, first_ms, last_ms)

	err = write_srt(opts.OutputFl, subs)
	if err != nil {
		die(err)
	}
}<commit_msg>remove subtitle id parsing<commit_after>package main

import (
	"fmt"
	"errors"
	"strings"
	"math"
	"os"
	"path"
	"io"
	"bufio"
	"container/list"
	"github.com/jessevdk/go-flags"
)

const (
	version = "0.1.1"
)

type subtitle struct {
	text string
	start uint
	end uint
}

func die(err error) {
	fmt.Fprintf(os.Stderr, "%v\n", err)
	os.Exit(1)
}

func roundFloat64(f float64) float64 {
	val := f - float64(int64(f))
	if val >= 0.5 {
		return math.Ceil(f)
	} else if val > 0 {
		return math.Floor(f)
	} else if val <= -0.5 {
		return math.Floor(f)
	} else if val < 0 {
		return math.Ceil(f)
	}
	return f
}

/* converts hh:mm:ss,mss to milliseconds */
func time_to_msecs(tm string) (uint, error) {
	var msecs uint
	var h, m, s, ms uint

	tm = strings.Replace(tm, ".", ",", 1)
	num, err := fmt.Sscanf(tm, "%d:%d:%d,%d", &h, &m, &s, &ms)

	if num != 4 || err != nil {
		return 0, errors.New("Parsing error: Can not covert `" + tm + "' to milliseconds.")
	}

	msecs = h * 60 * 60 * 1000
	msecs += m * 60 * 1000
	msecs += s * 1000
	msecs += ms

	return msecs, nil
}

/* converts milliseconds to hh:mm:ss,mss */
func msecs_to_time(msecs uint) string {
	var h, m, s, ms uint

	h = msecs / (60 * 60 * 1000)
	msecs %= 60 * 60 * 1000
	m = msecs / (60 * 1000)
	msecs %= 60 * 1000
	s = msecs / 1000
	ms = msecs % 1000

	tm := fmt.Sprintf("%02d:%02d:%02d,%03d", h, m, s, ms)

	return tm
}

/* read SubRip (srt) file */
func read_srt(filename string) (*list.List, error) {
	var state int = 0
	var subs *list.List
	var sub *subtitle

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	r := bufio.NewReader(f)
	subs = list.New()
	sub = new(subtitle)

	for {
		var (
			isprefix bool = true
			err error = nil
			ln, line []byte
		)

		for isprefix && err == nil {
			line, isprefix, err = r.ReadLine()
			if err != nil && err != io.EOF {
				return nil, err
			}
			ln = append(ln, line...)
		}

		if state == 0 {
			if len(ln) == 0 {
				if err == io.EOF {
					break;
				}
				continue;
			}
			state = 1
		/* parse start, end times */
		} else if state == 1 {
			tm := strings.Split(string(ln), " ")
			if len(tm) != 3 || tm[1] != "-->" {
				return nil, errors.New("Parsing error: Wrong file format")
			}
			sub.start, err = time_to_msecs(tm[0])
			if err != nil {
				return nil, err
			}
			sub.end, err = time_to_msecs(tm[2])
			if err != nil {
				return nil, err
			}
			state = 2
		/* parse the actual subtitle text */
		} else if state == 2 {
			if len(ln) == 0 {
				subs.PushBack(sub)
				sub = new(subtitle)
				state = 0
			} else {
				sub.text += string(ln) + "\r\n"
			}
		}

		if err == io.EOF {
			break;
		}
	}

	return subs, nil
}

/* write SubRip (srt) file */
func write_srt(filename string, subs *list.List) error {
	var id int = 0

	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	w := bufio.NewWriter(f)
	defer w.Flush()

	for e := subs.Front(); e != nil; e = e.Next() {
		id++
		sub := e.Value.(*subtitle)
		fmt.Fprintf(w, "%d\r\n", id)
		fmt.Fprintf(w, "%s --> %s\r\n", msecs_to_time(sub.start), msecs_to_time(sub.end))
		fmt.Fprintf(w, "%s\r\n", sub.text)
	}

	return nil
}

/* synchronize subtitles by knowing the time of the first and the last subtitle.
 * to archive this we must use the linear equation: y = mx + b */
func sync_subs(subs *list.List, synced_first_ms uint, synced_last_ms uint) {
	var slope, yint float64

	desynced_first_ms := subs.Front().Value.(*subtitle).start
	desynced_last_ms := subs.Back().Value.(*subtitle).start

	/* m = (y2 - y1) / (x2 - x1)
	 * m: slope
	 * y2: synced_last_ms
	 * y1: synced_first_ms
	 * x2: desynced_last_ms
	 * x1: desynced_first_ms */
	slope = float64(synced_last_ms - synced_first_ms) / float64(desynced_last_ms - desynced_first_ms)
	/* b = y - mx
	 * b: yint
	 * y: synced_last_ms
	 * m: slope
	 * x: desynced_last_ms */
	yint = float64(synced_last_ms) - slope * float64(desynced_last_ms)

	for e := subs.Front(); e != nil; e = e.Next() {
		sub := e.Value.(*subtitle)
		/* y = mx + b
		 * y: sub.start and sub.end
		 * m: slope
		 * x: sub.start and sub.end
		 * b: yint */
		sub.start = uint(roundFloat64(slope * float64(sub.start) + yint))
		sub.end = uint(roundFloat64(slope * float64(sub.end) + yint))
	}
}

func main() {
	var first_ms, last_ms uint

	var opts struct {
		FirstTm string `short:"f" long:"first-sub" description:"Time of first subtitle"`
		LastTm string `short:"l" long:"last-sub" description:"Time of last subtitle"`
		InputFl string `short:"i" long:"input" description:"Input file"`
		OutputFl string `short:"o" long:"output" description:"Output file"`
		PrintVersion bool `short:"v" long:"version" description:"Print version"`
	}

	_, err := flags.Parse(&opts)
	if err != nil {
		if err.(*flags.Error).Type == flags.ErrHelp {
			fmt.Fprintf(os.Stderr, "Example:\n")
			fmt.Fprintf(os.Stderr, "  %s -f 00:01:33,492 -l 01:39:23,561 -i file.srt\n",
				path.Base(os.Args[0]))
			os.Exit(0)
		}
		os.Exit(1)
	}

	if opts.PrintVersion {
		fmt.Printf("subsync v%s\n", version)
		os.Exit(0)
	}

	if opts.InputFl == "" {
		fmt.Fprintf(os.Stderr, "You must specify an input file with -i option.\n")
		os.Exit(1)
	}

	if opts.FirstTm != "" {
		first_ms, err = time_to_msecs(opts.FirstTm)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Please check the value of -f option.\n")
			die(err)
		}
	}

	if opts.LastTm != "" {
		last_ms, err = time_to_msecs(opts.LastTm)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Please check the value of -l option.\n")
			die(err)
		}
	}

	/* if output file is not set, use the input file */
	if opts.OutputFl == "" {
		opts.OutputFl = opts.InputFl
	}

	subs, err := read_srt(opts.InputFl)
	if err != nil {
		die(err)
	}

	/* if time of the first synced subtitle is not set,
	 * use the time of the first desynced subtitle */
	if opts.FirstTm == "" {
		first_ms = subs.Front().Value.(*subtitle).start
	}

	/* if time of the last synced subtitle is not set,
	 * use the time of the last desynced subtitle */
	if opts.LastTm == "" {
		last_ms = subs.Back().Value.(*subtitle).start
	}

	if first_ms > last_ms {
		fmt.Fprintf(os.Stderr, "First subtitle can not be after last subtitle.\n")
		fmt.Fprintf(os.Stderr, "Please check the values of -f and/or -l options.\n")
		os.Exit(1)
	}

	sync_subs(subs, first_ms, last_ms)

	err = write_srt(opts.OutputFl, subs)
	if err != nil {
		die(err)
	}
}<|endoftext|>


<commit_before>package adapt

import (
	"sync"
)

func approximate(basis Basis, indices []uint64, surpluses, points []float64,
	ni, no, nw uint) []float64 {

	nn, np := uint(len(indices))/ni, uint(len(points))/ni

	values := make([]float64, np*no)

	jobs := make(chan uint, np)
	group := sync.WaitGroup{}
	group.Add(int(np))

	for i := uint(0); i < nw; i++ {
		go func() {
			for j := range jobs {
				point := points[j*ni : (j+1)*ni]
				value := values[j*no : (j+1)*no]

				for k := uint(0); k < nn; k++ {
					weight := basis.Compute(indices[k*ni:(k+1)*ni], point)
					if weight == 0 {
						continue
					}
					for l := uint(0); l < no; l++ {
						value[l] += weight * surpluses[k*no+l]
					}
				}

				group.Done()
			}
		}()
	}

	for i := uint(0); i < np; i++ {
		jobs <- i
	}

	group.Wait()
	close(jobs)

	return values
}

func invoke(compute func([]float64, []float64), nodes []float64, ni, no, nw uint) []float64 {
	nn := uint(len(nodes)) / ni

	values := make([]float64, nn*no)

	jobs := make(chan uint, nn)
	group := sync.WaitGroup{}
	group.Add(int(nn))

	for i := uint(0); i < nw; i++ {
		go func() {
			for j := range jobs {
				compute(nodes[j*ni:(j+1)*ni], values[j*no:(j+1)*no])
				group.Done()
			}
		}()
	}

	for i := uint(0); i < nn; i++ {
		jobs <- i
	}

	group.Wait()
	close(jobs)

	return values
}

func compact(indices []uint64, surpluses, scores []float64,
	ni, no, nn uint) ([]uint64, []float64, []float64) {

	na, ne := uint(0), nn
	for i, j := uint(0), uint(0); i < nn; i++ {
		if scores[j] < 0 {
			j++
			continue
		}

		if j > na {
			copy(indices[j*ni:], indices[(j+1)*ni:ne*ni])
			copy(surpluses[j*no:], surpluses[(j+1)*no:ne*no])
			copy(scores[j:], scores[(j+1):ne])
			ne -= j - na
			j = na
		}

		na++
		j++
	}

	return indices[:na*ni], surpluses[:na*no], scores[:na]
}

func cumulate(basis Basis, indices []uint64, surpluses []float64, ni, no, nn uint,
	integral []float64) {

	for i := uint(0); i < nn; i++ {
		volume := basis.Integrate(indices[i*ni : (i+1)*ni])
		for j := uint(0); j < no; j++ {
			integral[j] += surpluses[i*no+j] * volume
		}
	}
}

func measure(basis Basis, indices []uint64, ni uint) []float64 {
	nn := uint(len(indices)) / ni

	volumes := make([]float64, nn)
	for i := uint(0); i < nn; i++ {
		volumes[i] = basis.Integrate(indices[i*ni : (i+1)*ni])
	}

	return volumes
}

func balance(grid Grid, history *hash, indices []uint64) []uint64 {
	neighbors := make([]uint64, 0)

	for {
		indices = socialize(grid, history, indices)

		if len(indices) == 0 {
			break
		}

		neighbors = append(neighbors, indices...)
	}

	return neighbors
}

func socialize(grid Grid, history *hash, indices []uint64) []uint64 {
	ni := history.ni
	nn := uint(len(indices)) / ni

	siblings := make([]uint64, 0, ni)
	for i := uint(0); i < nn; i++ {
		index := indices[i*ni : (i+1)*ni]

		for j := uint(0); j < ni; j++ {
			pair := index[j]

			grid.Parent(index, j)
			if !history.find(index) {
				index[j] = pair
				continue
			}
			index[j] = pair

			grid.Sibling(index, j)
			if !history.find(index) {
				history.push(index)
				siblings = append(siblings, index...)
			}
			index[j] = pair
		}
	}

	return siblings
}

func subtract(minuend, subtrahend []float64) []float64 {
	difference := make([]float64, len(minuend))
	for i := range minuend {
		difference[i] = minuend[i] - subtrahend[i]
	}
	return difference
}
<commit_msg>Reorder a couple of functions<commit_after>package adapt

import (
	"sync"
)

func approximate(basis Basis, indices []uint64, surpluses, points []float64,
	ni, no, nw uint) []float64 {

	nn, np := uint(len(indices))/ni, uint(len(points))/ni

	values := make([]float64, np*no)

	jobs := make(chan uint, np)
	group := sync.WaitGroup{}
	group.Add(int(np))

	for i := uint(0); i < nw; i++ {
		go func() {
			for j := range jobs {
				point := points[j*ni : (j+1)*ni]
				value := values[j*no : (j+1)*no]

				for k := uint(0); k < nn; k++ {
					weight := basis.Compute(indices[k*ni:(k+1)*ni], point)
					if weight == 0 {
						continue
					}
					for l := uint(0); l < no; l++ {
						value[l] += weight * surpluses[k*no+l]
					}
				}

				group.Done()
			}
		}()
	}

	for i := uint(0); i < np; i++ {
		jobs <- i
	}

	group.Wait()
	close(jobs)

	return values
}

func balance(grid Grid, history *hash, indices []uint64) []uint64 {
	neighbors := make([]uint64, 0)

	for {
		indices = socialize(grid, history, indices)

		if len(indices) == 0 {
			break
		}

		neighbors = append(neighbors, indices...)
	}

	return neighbors
}

func compact(indices []uint64, surpluses, scores []float64,
	ni, no, nn uint) ([]uint64, []float64, []float64) {

	na, ne := uint(0), nn
	for i, j := uint(0), uint(0); i < nn; i++ {
		if scores[j] < 0 {
			j++
			continue
		}

		if j > na {
			copy(indices[j*ni:], indices[(j+1)*ni:ne*ni])
			copy(surpluses[j*no:], surpluses[(j+1)*no:ne*no])
			copy(scores[j:], scores[(j+1):ne])
			ne -= j - na
			j = na
		}

		na++
		j++
	}

	return indices[:na*ni], surpluses[:na*no], scores[:na]
}

func cumulate(basis Basis, indices []uint64, surpluses []float64, ni, no, nn uint,
	integral []float64) {

	for i := uint(0); i < nn; i++ {
		volume := basis.Integrate(indices[i*ni : (i+1)*ni])
		for j := uint(0); j < no; j++ {
			integral[j] += surpluses[i*no+j] * volume
		}
	}
}

func invoke(compute func([]float64, []float64), nodes []float64, ni, no, nw uint) []float64 {
	nn := uint(len(nodes)) / ni

	values := make([]float64, nn*no)

	jobs := make(chan uint, nn)
	group := sync.WaitGroup{}
	group.Add(int(nn))

	for i := uint(0); i < nw; i++ {
		go func() {
			for j := range jobs {
				compute(nodes[j*ni:(j+1)*ni], values[j*no:(j+1)*no])
				group.Done()
			}
		}()
	}

	for i := uint(0); i < nn; i++ {
		jobs <- i
	}

	group.Wait()
	close(jobs)

	return values
}

func measure(basis Basis, indices []uint64, ni uint) []float64 {
	nn := uint(len(indices)) / ni

	volumes := make([]float64, nn)
	for i := uint(0); i < nn; i++ {
		volumes[i] = basis.Integrate(indices[i*ni : (i+1)*ni])
	}

	return volumes
}

func socialize(grid Grid, history *hash, indices []uint64) []uint64 {
	ni := history.ni
	nn := uint(len(indices)) / ni

	siblings := make([]uint64, 0, ni)
	for i := uint(0); i < nn; i++ {
		index := indices[i*ni : (i+1)*ni]

		for j := uint(0); j < ni; j++ {
			pair := index[j]

			grid.Parent(index, j)
			if !history.find(index) {
				index[j] = pair
				continue
			}
			index[j] = pair

			grid.Sibling(index, j)
			if !history.find(index) {
				history.push(index)
				siblings = append(siblings, index...)
			}
			index[j] = pair
		}
	}

	return siblings
}

func subtract(minuend, subtrahend []float64) []float64 {
	difference := make([]float64, len(minuend))
	for i := range minuend {
		difference[i] = minuend[i] - subtrahend[i]
	}
	return difference
}
<|endoftext|>


<commit_before>// Package api has type definitions for pcloud
//
// Converted from the API docs with help from https://mholt.github.io/json-to-go/
package api

import (
	"fmt"
	"time"
)

const (
	// Sun, 16 Mar 2014 17:26:04 +0000
	timeFormat = `"` + time.RFC1123Z + `"`
)

// Time represents represents date and time information for the
// pcloud API, by using RFC1123Z
type Time time.Time

// MarshalJSON turns a Time into JSON (in UTC)
func (t *Time) MarshalJSON() (out []byte, err error) {
	timeString := (*time.Time)(t).Format(timeFormat)
	return []byte(timeString), nil
}

// UnmarshalJSON turns JSON into a Time
func (t *Time) UnmarshalJSON(data []byte) error {
	newT, err := time.Parse(timeFormat, string(data))
	if err != nil {
		return err
	}
	*t = Time(newT)
	return nil
}

// Error is returned from pcloud when things go wrong
//
// If result is 0 then everything is OK
type Error struct {
	Result      int    `json:"result"`
	ErrorString string `json:"error"`
}

// Error returns a string for the error and satisfies the error interface
func (e *Error) Error() string {
	return fmt.Sprintf("pcloud error: %s (%d)", e.ErrorString, e.Result)
}

// Update returns err directly if it was != nil, otherwise it returns
// an Error or nil if no error was detected
func (e *Error) Update(err error) error {
	if err != nil {
		return err
	}
	if e.Result == 0 {
		return nil
	}
	return e
}

// Check Error satisfies the error interface
var _ error = (*Error)(nil)

// Item describes a folder or a file as returned by Get Folder Items and others
type Item struct {
	Path           string `json:"path"`
	Name           string `json:"name"`
	Created        Time   `json:"created"`
	IsMine         bool   `json:"ismine"`
	Thumb          bool   `json:"thumb"`
	Modified       Time   `json:"modified"`
	Comments       int    `json:"comments"`
	ID             string `json:"id"`
	IsShared       bool   `json:"isshared"`
	IsDeleted      bool   `json:"isdeleted"`
	Icon           string `json:"icon"`
	IsFolder       bool   `json:"isfolder"`
	ParentFolderID int64  `json:"parentfolderid"`
	FolderID       int64  `json:"folderid,omitempty"`
	Height         int    `json:"height,omitempty"`
	FileID         int64  `json:"fileid,omitempty"`
	Width          int    `json:"width,omitempty"`
	Hash           uint64 `json:"hash,omitempty"`
	Category       int    `json:"category,omitempty"`
	Size           int64  `json:"size,omitempty"`
	ContentType    string `json:"contenttype,omitempty"`
	Contents       []Item `json:"contents"`
}

// ModTime returns the modification time of the item
func (i *Item) ModTime() (t time.Time) {
	t = time.Time(i.Modified)
	if t.IsZero() {
		t = time.Time(i.Created)
	}
	return t
}

// ItemResult is returned from the /listfolder, /createfolder, /deletefolder, /deletefile etc methods
type ItemResult struct {
	Error
	Metadata Item `json:"metadata"`
}

// Hashes contains the supported hashes
type Hashes struct {
	SHA1 string `json:"sha1"`
	MD5  string `json:"md5"`
}

// UploadFileResponse is the response from /uploadfile
type UploadFileResponse struct {
	Error
	Items     []Item   `json:"metadata"`
	Checksums []Hashes `json:"checksums"`
	Fileids   []int64  `json:"fileids"`
}

// GetFileLinkResult is returned from /getfilelink
type GetFileLinkResult struct {
	Error
	Dwltag  string   `json:"dwltag"`
	Hash    uint64   `json:"hash"`
	Size    int64    `json:"size"`
	Expires Time     `json:"expires"`
	Path    string   `json:"path"`
	Hosts   []string `json:"hosts"`
}

// IsValid returns whether the link is valid and has not expired
func (g *GetFileLinkResult) IsValid() bool {
	if g == nil {
		return false
	}
	if len(g.Hosts) == 0 {
		return false
	}
	return time.Time(g.Expires).Sub(time.Now()) > 30*time.Second
}

// URL returns a URL from the Path and Hosts.  Check with IsValid
// before calling.
func (g *GetFileLinkResult) URL() string {
	// FIXME rotate the hosts?
	return "https://" + g.Hosts[0] + g.Path
}

// ChecksumFileResult is returned from /checksumfile
type ChecksumFileResult struct {
	Error
	Hashes
	Metadata Item `json:"metadata"`
}

// UserInfo is returned from /userinfo
type UserInfo struct {
	Error
	Cryptosetup           bool   `json:"cryptosetup"`
	Plan                  int    `json:"plan"`
	CryptoSubscription    bool   `json:"cryptosubscription"`
	PublicLinkQuota       int64  `json:"publiclinkquota"`
	Email                 string `json:"email"`
	UserID                int    `json:"userid"`
	Result                int    `json:"result"`
	Quota                 int64  `json:"quota"`
	TrashRevretentionDays int    `json:"trashrevretentiondays"`
	Premium               bool   `json:"premium"`
	PremiumLifetime       bool   `json:"premiumlifetime"`
	EmailVerified         bool   `json:"emailverified"`
	UsedQuota             int64  `json:"usedquota"`
	Language              string `json:"language"`
	Business              bool   `json:"business"`
	CryptoLifetime        bool   `json:"cryptolifetime"`
	Registered            string `json:"registered"`
	Journey               struct {
		Claimed bool `json:"claimed"`
		Steps   struct {
			VerifyMail    bool `json:"verifymail"`
			UploadFile    bool `json:"uploadfile"`
			AutoUpload    bool `json:"autoupload"`
			DownloadApp   bool `json:"downloadapp"`
			DownloadDrive bool `json:"downloaddrive"`
		} `json:"steps"`
	} `json:"journey"`
}
<commit_msg>pcloud: remove duplicated UserInfo.Result field spotted by go vet<commit_after>// Package api has type definitions for pcloud
//
// Converted from the API docs with help from https://mholt.github.io/json-to-go/
package api

import (
	"fmt"
	"time"
)

const (
	// Sun, 16 Mar 2014 17:26:04 +0000
	timeFormat = `"` + time.RFC1123Z + `"`
)

// Time represents represents date and time information for the
// pcloud API, by using RFC1123Z
type Time time.Time

// MarshalJSON turns a Time into JSON (in UTC)
func (t *Time) MarshalJSON() (out []byte, err error) {
	timeString := (*time.Time)(t).Format(timeFormat)
	return []byte(timeString), nil
}

// UnmarshalJSON turns JSON into a Time
func (t *Time) UnmarshalJSON(data []byte) error {
	newT, err := time.Parse(timeFormat, string(data))
	if err != nil {
		return err
	}
	*t = Time(newT)
	return nil
}

// Error is returned from pcloud when things go wrong
//
// If result is 0 then everything is OK
type Error struct {
	Result      int    `json:"result"`
	ErrorString string `json:"error"`
}

// Error returns a string for the error and satisfies the error interface
func (e *Error) Error() string {
	return fmt.Sprintf("pcloud error: %s (%d)", e.ErrorString, e.Result)
}

// Update returns err directly if it was != nil, otherwise it returns
// an Error or nil if no error was detected
func (e *Error) Update(err error) error {
	if err != nil {
		return err
	}
	if e.Result == 0 {
		return nil
	}
	return e
}

// Check Error satisfies the error interface
var _ error = (*Error)(nil)

// Item describes a folder or a file as returned by Get Folder Items and others
type Item struct {
	Path           string `json:"path"`
	Name           string `json:"name"`
	Created        Time   `json:"created"`
	IsMine         bool   `json:"ismine"`
	Thumb          bool   `json:"thumb"`
	Modified       Time   `json:"modified"`
	Comments       int    `json:"comments"`
	ID             string `json:"id"`
	IsShared       bool   `json:"isshared"`
	IsDeleted      bool   `json:"isdeleted"`
	Icon           string `json:"icon"`
	IsFolder       bool   `json:"isfolder"`
	ParentFolderID int64  `json:"parentfolderid"`
	FolderID       int64  `json:"folderid,omitempty"`
	Height         int    `json:"height,omitempty"`
	FileID         int64  `json:"fileid,omitempty"`
	Width          int    `json:"width,omitempty"`
	Hash           uint64 `json:"hash,omitempty"`
	Category       int    `json:"category,omitempty"`
	Size           int64  `json:"size,omitempty"`
	ContentType    string `json:"contenttype,omitempty"`
	Contents       []Item `json:"contents"`
}

// ModTime returns the modification time of the item
func (i *Item) ModTime() (t time.Time) {
	t = time.Time(i.Modified)
	if t.IsZero() {
		t = time.Time(i.Created)
	}
	return t
}

// ItemResult is returned from the /listfolder, /createfolder, /deletefolder, /deletefile etc methods
type ItemResult struct {
	Error
	Metadata Item `json:"metadata"`
}

// Hashes contains the supported hashes
type Hashes struct {
	SHA1 string `json:"sha1"`
	MD5  string `json:"md5"`
}

// UploadFileResponse is the response from /uploadfile
type UploadFileResponse struct {
	Error
	Items     []Item   `json:"metadata"`
	Checksums []Hashes `json:"checksums"`
	Fileids   []int64  `json:"fileids"`
}

// GetFileLinkResult is returned from /getfilelink
type GetFileLinkResult struct {
	Error
	Dwltag  string   `json:"dwltag"`
	Hash    uint64   `json:"hash"`
	Size    int64    `json:"size"`
	Expires Time     `json:"expires"`
	Path    string   `json:"path"`
	Hosts   []string `json:"hosts"`
}

// IsValid returns whether the link is valid and has not expired
func (g *GetFileLinkResult) IsValid() bool {
	if g == nil {
		return false
	}
	if len(g.Hosts) == 0 {
		return false
	}
	return time.Time(g.Expires).Sub(time.Now()) > 30*time.Second
}

// URL returns a URL from the Path and Hosts.  Check with IsValid
// before calling.
func (g *GetFileLinkResult) URL() string {
	// FIXME rotate the hosts?
	return "https://" + g.Hosts[0] + g.Path
}

// ChecksumFileResult is returned from /checksumfile
type ChecksumFileResult struct {
	Error
	Hashes
	Metadata Item `json:"metadata"`
}

// UserInfo is returned from /userinfo
type UserInfo struct {
	Error
	Cryptosetup           bool   `json:"cryptosetup"`
	Plan                  int    `json:"plan"`
	CryptoSubscription    bool   `json:"cryptosubscription"`
	PublicLinkQuota       int64  `json:"publiclinkquota"`
	Email                 string `json:"email"`
	UserID                int    `json:"userid"`
	Quota                 int64  `json:"quota"`
	TrashRevretentionDays int    `json:"trashrevretentiondays"`
	Premium               bool   `json:"premium"`
	PremiumLifetime       bool   `json:"premiumlifetime"`
	EmailVerified         bool   `json:"emailverified"`
	UsedQuota             int64  `json:"usedquota"`
	Language              string `json:"language"`
	Business              bool   `json:"business"`
	CryptoLifetime        bool   `json:"cryptolifetime"`
	Registered            string `json:"registered"`
	Journey               struct {
		Claimed bool `json:"claimed"`
		Steps   struct {
			VerifyMail    bool `json:"verifymail"`
			UploadFile    bool `json:"uploadfile"`
			AutoUpload    bool `json:"autoupload"`
			DownloadApp   bool `json:"downloadapp"`
			DownloadDrive bool `json:"downloaddrive"`
		} `json:"steps"`
	} `json:"journey"`
}
<|endoftext|>