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

package main

import (
	"errors"
	"fmt"
	"strconv"
	"time"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// BienChaincode is  a Chaincode for bien application implementation
type BienChaincode struct {
}
var orderIndexStr ="_orderindex"

type Bien struct{
		id int64 `json:"orderId"`
		name string `json:"name"`
		state string `json:"state"`
		price int `json:"price"`
		postage int `json:"postage"`
		owner string `json:"owner"`
}
var logger = shim.NewLogger("SimpleChaincode")
func main() {
    logger.SetLevel(shim.LogInfo)
	err := shim.Start(new(BienChaincode))
	if err != nil {
		fmt.Printf("Error starting BienChaincode chaincode: %s", err)
	}
}

// Init resets all the things
func (t *BienChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Printf("hello init chaincode, it is for testing")
	var Aval int
	var err error
    logger.Warning("init logger should be 1 string")
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	// Initialize the chaincode
	Aval, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}

	// Write the state to the ledger
	err = stub.PutState("abc", []byte(strconv.Itoa(Aval)))				//making a test var "abc", I find it handy to read/write to it right away to test the network
	if err != nil {
		return nil, err
	}
	logger.Infof("init logger arg0=%v", args[0])
	var empty []string
	jsonAsBytes, _ := json.Marshal(empty)								//marshal an emtpy array of strings to clear the index
	err = stub.PutState(orderIndexStr, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *BienChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	} else if function == "set_owner" {
		return t.set_owner(stub, args)
	} else if function == "change_state" {
		return t.change_state(stub, args)
	} else if function == "add_goods" {
		return t.add_goods(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *BienChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

// write - invoke function to write key/value pair
func (t *BienChaincode) write(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, value string
	var err error
	fmt.Println("running write()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0]
	value = args[1]
	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// read - query function to read key/value pair
func (t *BienChaincode) read(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query")
	}

	key = args[0]

	valAsbytes, err := stub.GetState(key)
	logger.Infof("query.read logger valAsbytes=%v", valAsbytes)
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return nil, errors.New(jsonResp)
	}

	return valAsbytes, nil
}

// read - query function to read key/value pair
func (t *BienChaincode) set_owner(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	if len(args)<2 {
	 return nil,errors.New("Incorrect number of arguments. Expecting 2")
	}

	fmt.Println("- start set owner-")
	fmt.Println(args[0] + " - " + args[1])
	bienAsBytes, err := stub.GetState(args[0])
	if err != nil {
			return nil, errors.New("Failed to get item")
		}
		res := Bien{}
		json.Unmarshal(bienAsBytes, &res)										//un stringify it aka JSON.parse()
		res.owner = args[1]

		jsonAsBytes, _ := json.Marshal(res)
		err = stub.PutState(args[0], jsonAsBytes)								//rewrite the marble with id as key
		if err != nil {
			return nil, err
		}

		fmt.Println("- end set owner-")

		return nil, nil
}

// read - query function to read key/value pair, then change the data structure's state field
func (t *BienChaincode) change_state(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
//   0       1       2          3       4     5
	//id  "name", "owner", "state", "price"  "postage"
	var err error

	if len(args)<2 {
	 return nil,errors.New("Incorrect number of arguments. Expecting 2")
	}

	bienAsBytes, err := stub.GetState(args[0])
	logger.Infof("change_state getState: logger bienAsBytes=%v", bienAsBytes)
	if err != nil {
			return nil, errors.New("Failed to get thing")
		}

    var res Bien
   //	res := Bien{}
		json.Unmarshal(bienAsBytes, &res)
		logger.Infof("change_state before set res: logger res=%v", res)									//un stringify it aka JSON.parse()
		res.state = args[1]

		logger.Infof("change_state res: logger res=%v", res)
		fmt.Println(res.id, ":",res.name, ":", res.owner, ":", res.state, ":", res.price, ":", res.postage)
		jsonAsBytes, _ := json.Marshal(res)
		err = stub.PutState(args[0], jsonAsBytes)								//rewrite the goods with name as key

		if err != nil {
			return nil, err
		}

		fmt.Println("- end change state-")

		//valAsbytes, err := stub.GetState(args[0])
	//logger.Infof("query.read logger valAsbytes=%v", valAsbytes)
	return nil, nil

}

func (t *BienChaincode) add_goods(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
var err error
fmt.Println("hello add goods")
	//   0       1       2          3       4
	// "name", "owner", "state", "price"  "postage"
	if len(args) != 5 {
		return nil, errors.New("Incorrect number of arguments. Expecting 4")
	}

	fmt.Println("- start add goods")
	if len(args[0]) <= 0 {
		return nil, errors.New("1st argument must be a non-empty string")
	}
	if len(args[1]) <= 0 {
		return nil, errors.New("2nd argument must be a non-empty string")
	}
	if len(args[2]) <= 0 {
		return nil, errors.New("3rd argument must be a non-empty string")
	}
	if len(args[3]) <= 0 {
		return nil, errors.New("4th argument must be a non-empty string")
	}
	if len(args[4]) <= 0 {
		return nil, errors.New("5th argument must be a non-empty string")
	}

	timestamp := time.Now().Unix()
	//str := `{"id":"`+strconv.FormatInt(timestamp , 10)+`","name": "` + args[0] + `", "owner": "` + args[1] + `", "state": "` + args[2]+ `", "price": ` + args[3] + `, "postage": ` + args[4] +`}`

//======
    _price, _ := strconv.Atoi(args[3])
    _postaget,_:=strconv.Atoi(args[4])
	var res = Bien{id:timestamp,name:args[0],owner:args[1],state:args[2],price:_price,postage:_postaget}

//	res.id      = timestamp
//	res.name    = args[0]
//	res.owner   = args[1]
//	res.state   = args[2]
//	res.price, err   = strconv.Atoi(args[3])
//	res.postage, err = strconv.Atoi(args[4])

	if err != nil {
		return nil, err
	}

	goodBytes, _ := json.Marshal(&res)
	err = stub.PutState("test", goodBytes)
	err = stub.PutState(strconv.FormatInt(timestamp , 10), goodBytes)

	//=======
	//err = stub.PutState(strconv.FormatInt(timestamp , 10), []byte(str))								//store marble with id as key
	if err != nil {
		return nil, err
	}

	//get the  index
	bienAsBytes, err := stub.GetState(orderIndexStr)
	if err != nil {
		return nil, errors.New("Failed to get bien index")
	}
	var orderIndex []string
	json.Unmarshal(bienAsBytes, &orderIndex)							//un stringify it aka JSON.parse()
	fmt.Println("get order(bien) index: ", orderIndex)
	//append
	orderIndex = append(orderIndex,strconv.FormatInt(timestamp , 10))								//add bien id to index list
	fmt.Println("append:! order(bien) index: ", orderIndex)
	jsonAsBytes, _ := json.Marshal(orderIndex)
	err = stub.PutState(orderIndexStr, jsonAsBytes)						//store id of bien

	fmt.Println("- end add goods")
	return nil, nil
}<commit_msg>FIX STRUCTS FOR BIEN<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
		 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	"strconv"
	"time"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// BienChaincode is  a Chaincode for bien application implementation
type BienChaincode struct {
}
var orderIndexStr ="_orderindex"

type Bien struct{
		ID int64 `json:"orderId"`
		Name string `json:"name"`
		State string `json:"state"`
		Price int `json:"price"`
		Postage int `json:"postage"`
		Owner string `json:"owner"`
}
var logger = shim.NewLogger("SimpleChaincode")
func main() {
    logger.SetLevel(shim.LogInfo)
	err := shim.Start(new(BienChaincode))
	if err != nil {
		fmt.Printf("Error starting BienChaincode chaincode: %s", err)
	}
}

// Init resets all the things
func (t *BienChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Printf("hello init chaincode, it is for testing")
	var Aval int
	var err error
    logger.Warning("init logger should be 1 string")
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	// Initialize the chaincode
	Aval, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}

	// Write the state to the ledger
	err = stub.PutState("abc", []byte(strconv.Itoa(Aval)))				//making a test var "abc", I find it handy to read/write to it right away to test the network
	if err != nil {
		return nil, err
	}
	logger.Infof("init logger arg0=%v", args[0])
	var empty []string
	jsonAsBytes, _ := json.Marshal(empty)								//marshal an emtpy array of strings to clear the index
	err = stub.PutState(orderIndexStr, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *BienChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "write" {
		return t.write(stub, args)
	} else if function == "set_owner" {
		return t.set_owner(stub, args)
	} else if function == "change_state" {
		return t.change_state(stub, args)
	} else if function == "add_goods" {
		return t.add_goods(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *BienChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

// write - invoke function to write key/value pair
func (t *BienChaincode) write(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, value string
	var err error
	fmt.Println("running write()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0]
	value = args[1]
	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// read - query function to read key/value pair
func (t *BienChaincode) read(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query")
	}

	key = args[0]

	valAsbytes, err := stub.GetState(key)
	logger.Infof("query.read logger valAsbytes=%v", valAsbytes)
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return nil, errors.New(jsonResp)
	}

	return valAsbytes, nil
}

// read - query function to read key/value pair
func (t *BienChaincode) set_owner(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var err error

	if len(args)<2 {
	 return nil,errors.New("Incorrect number of arguments. Expecting 2")
	}

	fmt.Println("- start set owner-")
	fmt.Println(args[0] + " - " + args[1])
	bienAsBytes, err := stub.GetState(args[0])
	if err != nil {
			return nil, errors.New("Failed to get item")
		}
		res := Bien{}
		json.Unmarshal(bienAsBytes, &res)										//un stringify it aka JSON.parse()
		res.Owner = args[1]

		jsonAsBytes, _ := json.Marshal(res)
		err = stub.PutState(args[0], jsonAsBytes)								//rewrite the marble with id as key
		if err != nil {
			return nil, err
		}

		fmt.Println("- end set owner-")

		return nil, nil
}

// read - query function to read key/value pair, then change the data structure's state field
func (t *BienChaincode) change_state(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
//   0       1       2          3       4     5
	//id  "name", "owner", "state", "price"  "postage"
	var err error

	if len(args)<2 {
	 return nil,errors.New("Incorrect number of arguments. Expecting 2")
	}

	bienAsBytes, err := stub.GetState(args[0])
	logger.Infof("change_state getState: logger bienAsBytes=%v", bienAsBytes)
	if err != nil {
			return nil, errors.New("Failed to get thing")
		}

    var res Bien
   //	res := Bien{}
		json.Unmarshal(bienAsBytes, &res)
		logger.Infof("change_state before set res: logger res=%v", res)									//un stringify it aka JSON.parse()
		res.State = args[1]

		logger.Infof("change_state res: logger res=%v", res)

		jsonAsBytes, _ := json.Marshal(res)
		err = stub.PutState(args[0], jsonAsBytes)								//rewrite the goods with name as key

		if err != nil {
			return nil, err
		}

		fmt.Println("- end change state-")

		//valAsbytes, err := stub.GetState(args[0])
	//logger.Infof("query.read logger valAsbytes=%v", valAsbytes)
	return nil, nil

}

func (t *BienChaincode) add_goods(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
var err error
fmt.Println("hello add goods")
	//   0       1       2          3       4
	// "name", "owner", "state", "price"  "postage"
	if len(args) != 5 {
		return nil, errors.New("Incorrect number of arguments. Expecting 4")
	}

	fmt.Println("- start add goods")
	if len(args[0]) <= 0 {
		return nil, errors.New("1st argument must be a non-empty string")
	}
	if len(args[1]) <= 0 {
		return nil, errors.New("2nd argument must be a non-empty string")
	}
	if len(args[2]) <= 0 {
		return nil, errors.New("3rd argument must be a non-empty string")
	}
	if len(args[3]) <= 0 {
		return nil, errors.New("4th argument must be a non-empty string")
	}
	if len(args[4]) <= 0 {
		return nil, errors.New("5th argument must be a non-empty string")
	}

	timestamp := time.Now().Unix()
	//str := `{"id":"`+strconv.FormatInt(timestamp , 10)+`","name": "` + args[0] + `", "owner": "` + args[1] + `", "state": "` + args[2]+ `", "price": ` + args[3] + `, "postage": ` + args[4] +`}`

//======
    _price, _ := strconv.Atoi(args[3])
    _postaget,_:=strconv.Atoi(args[4])
	var res = Bien{ID:timestamp,Name:args[0],Owner:args[1],State:args[2],Price:_price,Postage:_postaget}

//	res.id      = timestamp
//	res.name    = args[0]
//	res.owner   = args[1]
//	res.state   = args[2]
//	res.price, err   = strconv.Atoi(args[3])
//	res.postage, err = strconv.Atoi(args[4])

	if err != nil {
		return nil, err
	}

	goodBytes, _ := json.Marshal(&res)
	err = stub.PutState("test", goodBytes)
	err = stub.PutState(strconv.FormatInt(timestamp , 10), goodBytes)

	//=======
	//err = stub.PutState(strconv.FormatInt(timestamp , 10), []byte(str))								//store marble with id as key
	if err != nil {
		return nil, err
	}

	//get the  index
	bienAsBytes, err := stub.GetState(orderIndexStr)
	if err != nil {
		return nil, errors.New("Failed to get bien index")
	}
	var orderIndex []string
	json.Unmarshal(bienAsBytes, &orderIndex)							//un stringify it aka JSON.parse()
	fmt.Println("get order(bien) index: ", orderIndex)
	//append
	orderIndex = append(orderIndex,strconv.FormatInt(timestamp , 10))								//add bien id to index list
	fmt.Println("append:! order(bien) index: ", orderIndex)
	jsonAsBytes, _ := json.Marshal(orderIndex)
	err = stub.PutState(orderIndexStr, jsonAsBytes)						//store id of bien

	fmt.Println("- end add goods")
	return nil, nil
}<|endoftext|>


<commit_before>// Copyright 2015 Eleme Inc. All rights reserved.

package webapp

import (
	"github.com/eleme/banshee/models"
	"github.com/julienschmidt/httprouter"
	"math"
	"net/http"
	"sort"
	"strconv"
	"time"
)

type indexByScore []*models.Index

func (l indexByScore) Len() int { return len(l) }

func (l indexByScore) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

func (l indexByScore) Less(i, j int) bool {
	now := time.Now().Unix()
	// by `score / ((now - stamp + 2) ^ 1.5)`
	return l[i].Score/math.Pow(float64(uint32(2+now)-l[i].Stamp), 1.5) <
		l[j].Score/math.Pow(float64(uint32(2+now)-l[j].Stamp), 1.5)
}

// getMetricIndexes returns metric names.
func getMetricIndexes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	// Options
	limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
	if err != nil {
		limit = 50
	}
	order := r.URL.Query().Get("sort")
	if order != "up" && order != "down" {
		order = "up"
	}
	projID, err := strconv.Atoi(r.URL.Query().Get("project"))
	if err != nil {
		projID = 0
	}
	pattern := r.URL.Query().Get("pattern")
	if pattern == "" {
		pattern = "*"
	}
	// Index
	var idxs []*models.Index
	if projID > 0 {
		// Rules
		var rules []models.Rule
		if err := db.Admin.DB().Model(&models.Project{ID: projID}).Related(&rules).Error; err != nil {
			ResponseError(w, NewUnexceptedWebError(err))
			return
		}
		// Filter
		for _, rule := range rules {
			idxs = append(idxs, db.Index.Filter(rule.Pattern)...)
		}
	} else {
		// Filter
		idxs = db.Index.Filter(pattern)
	}
	// Sort
	sort.Sort(indexByScore(idxs))
	if order == "down" {
		// Reverse
		for i := 0; 2*i < len(idxs); i++ {
			idxs[len(idxs)-1-i], idxs[i] = idxs[i], idxs[len(idxs)-1-i]
		}
	}
	// http://danott.co/posts/json-marshalling-empty-slices-to-empty-arrays-in-go.html
	if len(idxs) == 0 {
		idxs = make([]*models.Index, 0)
	}
	// Limit
	if limit < len(idxs) {
		ResponseJSONOK(w, idxs[:limit])
	} else {
		ResponseJSONOK(w, idxs)
	}
}

// getMetrics returns metric values.
func getMetrics(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	// Options
	name := r.URL.Query().Get("name")
	if len(name) == 0 {
		ResponseError(w, ErrBadRequest)
		return
	}
	start, err := strconv.ParseUint(r.URL.Query().Get("start"), 10, 32)
	if err != nil {
		ResponseError(w, ErrBadRequest)
		return
	}
	stop, err := strconv.ParseUint(r.URL.Query().Get("stop"), 10, 32)
	if err != nil {
		ResponseError(w, ErrBadRequest)
		return
	}
	// Query
	metrics, err := db.Metric.Get(name, uint32(start), uint32(stop))
	if err != nil {
		ResponseError(w, NewUnexceptedWebError(err))
		return
	}
	// http://danott.co/posts/json-marshalling-empty-slices-to-empty-arrays-in-go.html
	if len(metrics) == 0 {
		metrics = make([]*models.Metric, 0)
	}
	ResponseJSONOK(w, metrics)
}
<commit_msg>Fix metric indexes sorting<commit_after>// Copyright 2015 Eleme Inc. All rights reserved.

package webapp

import (
	"github.com/eleme/banshee/models"
	"github.com/julienschmidt/httprouter"
	"math"
	"net/http"
	"sort"
	"strconv"
	"time"
)

type indexByScore []*models.Index

func (l indexByScore) Len() int { return len(l) }

func (l indexByScore) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

func (l indexByScore) Less(i, j int) bool {
	now := time.Now().Unix()
	// by `score / ((now - stamp + 2) ^ 1.5)`
	return l[i].Score/math.Pow(float64(uint32(2+now)-l[i].Stamp), 1.5) <
		l[j].Score/math.Pow(float64(uint32(2+now)-l[j].Stamp), 1.5)
}

// getMetricIndexes returns metric names.
func getMetricIndexes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	// Options
	limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
	if err != nil {
		limit = 50
	}
	order := r.URL.Query().Get("sort")
	if order != "up" && order != "down" {
		order = "up"
	}
	projID, err := strconv.Atoi(r.URL.Query().Get("project"))
	if err != nil {
		projID = 0
	}
	pattern := r.URL.Query().Get("pattern")
	if pattern == "" {
		pattern = "*"
	}
	// Index
	var idxs []*models.Index
	if projID > 0 {
		// Rules
		var rules []models.Rule
		if err := db.Admin.DB().Model(&models.Project{ID: projID}).Related(&rules).Error; err != nil {
			ResponseError(w, NewUnexceptedWebError(err))
			return
		}
		// Filter
		for _, rule := range rules {
			idxs = append(idxs, db.Index.Filter(rule.Pattern)...)
		}
	} else {
		// Filter
		idxs = db.Index.Filter(pattern)
	}
	// Sort
	sort.Sort(indexByScore(idxs))
	if order == "up" {
		// Reverse
		for i := 0; 2*i < len(idxs); i++ {
			idxs[len(idxs)-1-i], idxs[i] = idxs[i], idxs[len(idxs)-1-i]
		}
	}
	// http://danott.co/posts/json-marshalling-empty-slices-to-empty-arrays-in-go.html
	if len(idxs) == 0 {
		idxs = make([]*models.Index, 0)
	}
	// Limit
	if limit < len(idxs) {
		ResponseJSONOK(w, idxs[:limit])
	} else {
		ResponseJSONOK(w, idxs)
	}
}

// getMetrics returns metric values.
func getMetrics(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	// Options
	name := r.URL.Query().Get("name")
	if len(name) == 0 {
		ResponseError(w, ErrBadRequest)
		return
	}
	start, err := strconv.ParseUint(r.URL.Query().Get("start"), 10, 32)
	if err != nil {
		ResponseError(w, ErrBadRequest)
		return
	}
	stop, err := strconv.ParseUint(r.URL.Query().Get("stop"), 10, 32)
	if err != nil {
		ResponseError(w, ErrBadRequest)
		return
	}
	// Query
	metrics, err := db.Metric.Get(name, uint32(start), uint32(stop))
	if err != nil {
		ResponseError(w, NewUnexceptedWebError(err))
		return
	}
	// http://danott.co/posts/json-marshalling-empty-slices-to-empty-arrays-in-go.html
	if len(metrics) == 0 {
		metrics = make([]*models.Metric, 0)
	}
	ResponseJSONOK(w, metrics)
}
<|endoftext|>


<commit_before>package rpc

import (
	"context"
	"sync"

	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
)

// Call represents an active RPC. Calls are used to indicate completion
// of RPC requests and are returned within the provided channel in
// the Go() functions.
type Call struct {
	ctx    context.Context
	cancel func()

	finishedMu sync.RWMutex
	finished   bool

	Dest  peer.ID
	SvcID ServiceID   // The name of the service and method to call.
	Args  interface{} // The argument to the function (*struct).
	Reply interface{} // The reply from the function (*struct).
	Done  chan *Call  // Strobes when call is complete.

	errorMu sync.Mutex
	Error   error // After completion, the error status.
}

func newCall(ctx context.Context, dest peer.ID, svcName, svcMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
	ctx2, cancel := context.WithCancel(ctx)
	return &Call{
		ctx:    ctx2,
		cancel: cancel,
		Dest:   dest,
		SvcID:  ServiceID{svcName, svcMethod},
		Args:   args,
		Reply:  reply,
		Error:  nil,
		Done:   done,
	}
}

// done places the completed call in the done channel.
func (call *Call) done() {
	call.finishedMu.Lock()
	call.finished = true
	call.finishedMu.Unlock()

	select {
	case call.Done <- call:
		// ok
	default:
		logger.Debugf("discarding %s.%s call reply",
			call.SvcID.Name, call.SvcID.Method)
	}
	call.cancel()
}

func (call *Call) doneWithError(err error) {
	if err != nil {
		logger.Error(err)
		call.setError(err)
	}
	call.done()
}

func (call *Call) isFinished() bool {
	call.finishedMu.RLock()
	defer call.finishedMu.RUnlock()
	return call.finished
}

// watch context will wait for a context cancellation
// and close the stream.
func (call *Call) watchContextWithStream(s network.Stream) {
	select {
	case <-call.ctx.Done():
		if !call.isFinished() { // context was cancelled not by us
			logger.Debug("call context is done before finishing")
			s.Close()
			call.doneWithError(call.ctx.Err())
		}
	}
}

func (call *Call) setError(err error) {
	call.errorMu.Lock()
	defer call.errorMu.Unlock()
	if call.Error == nil {
		call.Error = err
	}
}

func (call *Call) getError() error {
	call.errorMu.Lock()
	defer call.errorMu.Unlock()
	return call.Error
}
<commit_msg>Set context error before closing<commit_after>package rpc

import (
	"context"
	"sync"

	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
)

// Call represents an active RPC. Calls are used to indicate completion
// of RPC requests and are returned within the provided channel in
// the Go() functions.
type Call struct {
	ctx    context.Context
	cancel func()

	finishedMu sync.RWMutex
	finished   bool

	Dest  peer.ID
	SvcID ServiceID   // The name of the service and method to call.
	Args  interface{} // The argument to the function (*struct).
	Reply interface{} // The reply from the function (*struct).
	Done  chan *Call  // Strobes when call is complete.

	errorMu sync.Mutex
	Error   error // After completion, the error status.
}

func newCall(ctx context.Context, dest peer.ID, svcName, svcMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
	ctx2, cancel := context.WithCancel(ctx)
	return &Call{
		ctx:    ctx2,
		cancel: cancel,
		Dest:   dest,
		SvcID:  ServiceID{svcName, svcMethod},
		Args:   args,
		Reply:  reply,
		Error:  nil,
		Done:   done,
	}
}

// done places the completed call in the done channel.
func (call *Call) done() {
	call.finishedMu.Lock()
	call.finished = true
	call.finishedMu.Unlock()

	select {
	case call.Done <- call:
		// ok
	default:
		logger.Debugf("discarding %s.%s call reply",
			call.SvcID.Name, call.SvcID.Method)
	}
	call.cancel()
}

func (call *Call) doneWithError(err error) {
	if err != nil {
		logger.Error(err)
		call.setError(err)
	}
	call.done()
}

func (call *Call) isFinished() bool {
	call.finishedMu.RLock()
	defer call.finishedMu.RUnlock()
	return call.finished
}

// watch context will wait for a context cancellation
// and close the stream.
func (call *Call) watchContextWithStream(s network.Stream) {
	select {
	case <-call.ctx.Done():
		if !call.isFinished() { // context was cancelled not by us
			logger.Debug("call context is done before finishing")
			call.doneWithError(call.ctx.Err())
			s.Close()
		}
	}
}

func (call *Call) setError(err error) {
	call.errorMu.Lock()
	defer call.errorMu.Unlock()
	if call.Error == nil {
		call.Error = err
	}
}

func (call *Call) getError() error {
	call.errorMu.Lock()
	defer call.errorMu.Unlock()
	return call.Error
}
<|endoftext|>


<commit_before>package capnp

import (
	"encoding/binary"
	"errors"
)

// A SegmentID is a numeric identifier for a Segment.
type SegmentID uint32

// A Segment is an allocation arena for Cap'n Proto objects.
// It is part of a Message, which can contain other segments that
// reference each other.
type Segment struct {
	msg  *Message
	id   SegmentID
	data []byte
}

// Message returns the message that contains s.
func (s *Segment) Message() *Message {
	return s.msg
}

// ID returns the segment's ID.
func (s *Segment) ID() SegmentID {
	return s.id
}

// Data returns the raw byte slice for the segment.
func (s *Segment) Data() []byte {
	return s.data
}

func (s *Segment) inBounds(addr Address) bool {
	return addr < Address(len(s.data))
}

func (s *Segment) regionInBounds(base Address, sz Size) bool {
	end, ok := base.addSize(sz)
	if !ok {
		return false
	}
	return end <= Address(len(s.data))
}

// slice returns the segment of data from base to base+sz.
func (s *Segment) slice(base Address, sz Size) []byte {
	// Bounds check should have happened before calling slice.
	return s.data[base : base+Address(sz)]
}

func (s *Segment) readUint8(addr Address) uint8 {
	return s.slice(addr, 1)[0]
}

func (s *Segment) readUint16(addr Address) uint16 {
	return binary.LittleEndian.Uint16(s.slice(addr, 2))
}

func (s *Segment) readUint32(addr Address) uint32 {
	return binary.LittleEndian.Uint32(s.slice(addr, 4))
}

func (s *Segment) readUint64(addr Address) uint64 {
	return binary.LittleEndian.Uint64(s.slice(addr, 8))
}

func (s *Segment) readRawPointer(addr Address) rawPointer {
	return rawPointer(s.readUint64(addr))
}

func (s *Segment) writeUint8(addr Address, val uint8) {
	s.slice(addr, 1)[0] = val
}

func (s *Segment) writeUint16(addr Address, val uint16) {
	binary.LittleEndian.PutUint16(s.slice(addr, 2), val)
}

func (s *Segment) writeUint32(addr Address, val uint32) {
	binary.LittleEndian.PutUint32(s.slice(addr, 4), val)
}

func (s *Segment) writeUint64(addr Address, val uint64) {
	binary.LittleEndian.PutUint64(s.slice(addr, 8), val)
}

func (s *Segment) writeRawPointer(addr Address, val rawPointer) {
	s.writeUint64(addr, uint64(val))
}

// root returns a 1-element pointer list that references the first word
// in the segment.  This only makes sense to call on the first segment
// in a message.
func (s *Segment) root() PointerList {
	sz := ObjectSize{PointerCount: 1}
	if !s.regionInBounds(0, sz.totalSize()) {
		return PointerList{}
	}
	return PointerList{List{
		seg:        s,
		length:     1,
		size:       sz,
		depthLimit: s.msg.depthLimit(),
	}}
}

func (s *Segment) lookupSegment(id SegmentID) (*Segment, error) {
	if s.id == id {
		return s, nil
	}
	return s.msg.Segment(id)
}

func (s *Segment) readPtr(off Address, depthLimit uint) (ptr Ptr, err error) {
	val := s.readRawPointer(off)
	s, off, val, err = s.resolveFarPointer(off, val)
	if err != nil {
		return Ptr{}, err
	}
	if val == 0 {
		return Ptr{}, nil
	}
	if depthLimit == 0 {
		return Ptr{}, errDepthLimit
	}
	// Be wary of overflow. Offset is 30 bits signed. List size is 29 bits
	// unsigned. For both of these we need to check in terms of words if
	// using 32 bit maths as bits or bytes will overflow.
	switch val.pointerType() {
	case structPointer:
		sp, err := s.readStructPtr(off, val)
		if err != nil {
			return Ptr{}, err
		}
		if !s.msg.ReadLimiter().canRead(sp.readSize()) {
			return Ptr{}, errReadLimit
		}
		sp.depthLimit = depthLimit - 1
		return sp.ToPtr(), nil
	case listPointer:
		lp, err := s.readListPtr(off, val)
		if err != nil {
			return Ptr{}, err
		}
		if !s.msg.ReadLimiter().canRead(lp.readSize()) {
			return Ptr{}, errReadLimit
		}
		lp.depthLimit = depthLimit - 1
		return lp.ToPtr(), nil
	case otherPointer:
		if val.otherPointerType() != 0 {
			return Ptr{}, errOtherPointer
		}
		return Interface{
			seg: s,
			cap: val.capabilityIndex(),
		}.ToPtr(), nil
	default:
		// Only other types are far pointers.
		return Ptr{}, errBadLandingPad
	}
}

func (s *Segment) readStructPtr(off Address, val rawPointer) (Struct, error) {
	addr, ok := val.offset().resolve(off)
	if !ok {
		return Struct{}, errPointerAddress
	}
	sz := val.structSize()
	if !s.regionInBounds(addr, sz.totalSize()) {
		return Struct{}, errPointerAddress
	}
	return Struct{
		seg:  s,
		off:  addr,
		size: sz,
	}, nil
}

func (s *Segment) readListPtr(off Address, val rawPointer) (List, error) {
	addr, ok := val.offset().resolve(off)
	if !ok {
		return List{}, errPointerAddress
	}
	lsize, ok := val.totalListSize()
	if !ok {
		return List{}, errOverflow
	}
	if !s.regionInBounds(addr, lsize) {
		return List{}, errPointerAddress
	}
	lt := val.listType()
	if lt == compositeList {
		hdr := s.readRawPointer(addr)
		var ok bool
		addr, ok = addr.addSize(wordSize)
		if !ok {
			return List{}, errOverflow
		}
		if hdr.pointerType() != structPointer {
			return List{}, errBadTag
		}
		sz := hdr.structSize()
		n := int32(hdr.offset())
		// TODO(light): check that this has the same end address
		if tsize, ok := sz.totalSize().times(n); !ok {
			return List{}, errOverflow
		} else if !s.regionInBounds(addr, tsize) {
			return List{}, errPointerAddress
		}
		return List{
			seg:    s,
			size:   sz,
			off:    addr,
			length: n,
			flags:  isCompositeList,
		}, nil
	}
	if lt == bit1List {
		return List{
			seg:    s,
			off:    addr,
			length: val.numListElements(),
			flags:  isBitList,
		}, nil
	}
	return List{
		seg:    s,
		size:   val.elementSize(),
		off:    addr,
		length: val.numListElements(),
	}, nil
}

func (s *Segment) resolveFarPointer(off Address, val rawPointer) (*Segment, Address, rawPointer, error) {
	switch val.pointerType() {
	case doubleFarPointer:
		// A double far pointer points to a double pointer, where the
		// first points to the actual data, and the second is the tag
		// that would normally be placed right before the data (offset
		// == 0).

		faroff, segid := val.farAddress(), val.farSegment()
		s, err := s.lookupSegment(segid)
		if err != nil {
			return nil, 0, 0, err
		}
		if !s.regionInBounds(faroff, wordSize*2) {
			return nil, 0, 0, errPointerAddress
		}
		far := s.readRawPointer(faroff)
		tagStart, ok := faroff.addSize(wordSize)
		if !ok {
			return nil, 0, 0, errOverflow
		}
		tag := s.readRawPointer(tagStart)
		if far.pointerType() != farPointer || tag.offset() != 0 {
			return nil, 0, 0, errPointerAddress
		}
		segid = far.farSegment()
		if s, err = s.lookupSegment(segid); err != nil {
			return nil, 0, 0, errBadLandingPad
		}
		return s, 0, landingPadNearPointer(far, tag), nil
	case farPointer:
		faroff, segid := val.farAddress(), val.farSegment()
		s, err := s.lookupSegment(segid)
		if err != nil {
			return nil, 0, 0, err
		}
		if !s.regionInBounds(faroff, wordSize) {
			return nil, 0, 0, errPointerAddress
		}
		val = s.readRawPointer(faroff)
		return s, faroff, val, nil
	default:
		return s, off, val, nil
	}
}

func (s *Segment) writePtr(off Address, src Ptr, forceCopy bool) error {
	if !src.IsValid() {
		s.writeRawPointer(off, 0)
		return nil
	}

	// Copy src, if needed.  This is type-dependent.
	switch src.flags.ptrType() {
	case structPtrType:
		st := src.Struct()
		if st.size.isZero() {
			// Zero-sized structs should always be encoded with offset -1 in
			// order to avoid conflating with null.  No allocation needed.
			s.writeRawPointer(off, rawStructPointer(-1, ObjectSize{}))
			return nil
		}
		if forceCopy || src.seg.msg != s.msg || st.flags&isListMember != 0 {
			newSeg, newAddr, err := alloc(s, st.size.totalSize())
			if err != nil {
				return err
			}
			dst := Struct{
				seg:        newSeg,
				off:        newAddr,
				size:       st.size,
				depthLimit: maxDepth,
				// clear flags
			}
			if err := copyStruct(dst, st); err != nil {
				return err
			}
			src = dst.ToPtr()
		}
	case listPtrType:
		if forceCopy || src.seg.msg != s.msg {
			l := src.List()
			sz := l.allocSize()
			newSeg, newAddr, err := alloc(s, sz)
			if err != nil {
				return err
			}
			dst := List{
				seg:        newSeg,
				off:        newAddr,
				length:     l.length,
				size:       l.size,
				flags:      l.flags,
				depthLimit: maxDepth,
			}
			if dst.flags&isCompositeList != 0 {
				// Copy tag word
				newSeg.writeRawPointer(newAddr, l.seg.readRawPointer(l.off-Address(wordSize)))
				var ok bool
				dst.off, ok = dst.off.addSize(wordSize)
				if !ok {
					return errOverflow
				}
				sz -= wordSize
			}
			if dst.flags&isBitList != 0 || dst.size.PointerCount == 0 {
				end, _ := l.off.addSize(sz) // list has already validated
				copy(newSeg.data[dst.off:], l.seg.data[l.off:end])
			} else {
				for i := 0; i < l.Len(); i++ {
					err := copyStruct(dst.Struct(i), l.Struct(i))
					if err != nil {
						return err
					}
				}
			}
			src = dst.ToPtr()
		}
	case interfacePtrType:
		i := src.Interface()
		if src.seg.msg != s.msg {
			c := s.msg.AddCap(i.Client())
			i = NewInterface(s, c)
		}
		s.writeRawPointer(off, i.value(off))
		return nil
	default:
		panic("unreachable")
	}

	// Create far pointer if object is in a different segment.
	if src.seg != s {
		if !hasCapacity(src.seg.data, wordSize) {
			// Double far pointer needed.
			const landingSize = wordSize * 2
			t, dstAddr, err := alloc(s, landingSize)
			if err != nil {
				return err
			}

			srcAddr := src.address()
			t.writeRawPointer(dstAddr, rawFarPointer(src.seg.id, srcAddr))
			// alloc guarantees that two words are available.
			t.writeRawPointer(dstAddr+Address(wordSize), src.value(srcAddr-Address(wordSize)))
			s.writeRawPointer(off, rawDoubleFarPointer(t.id, dstAddr))
			return nil
		}
		// Have room in the target for a tag
		_, srcAddr, _ := alloc(src.seg, wordSize)
		src.seg.writeRawPointer(srcAddr, src.value(srcAddr))
		s.writeRawPointer(off, rawFarPointer(src.seg.id, srcAddr))
		return nil
	}

	// Local pointer.
	s.writeRawPointer(off, src.value(off))
	return nil
}

var (
	errPointerAddress = errors.New("capnp: invalid pointer address")
	errBadLandingPad  = errors.New("capnp: invalid far pointer landing pad")
	errBadTag         = errors.New("capnp: invalid tag word")
	errOtherPointer   = errors.New("capnp: unknown pointer type")
	errObjectSize     = errors.New("capnp: invalid object size")
	errElementSize    = errors.New("capnp: mismatched list element size")
	errReadLimit      = errors.New("capnp: read traversal limit reached")
	errDepthLimit     = errors.New("capnp: depth limit reached")
)

var (
	errOverflow    = errors.New("capnp: address or size overflow")
	errOutOfBounds = errors.New("capnp: address out of bounds")
	errCopyDepth   = errors.New("capnp: copy depth too large")
	errOverlap     = errors.New("capnp: overlapping data on copy")
	errListSize    = errors.New("capnp: invalid list size")
)
<commit_msg>capnp: fix typo in writePtr comment<commit_after>package capnp

import (
	"encoding/binary"
	"errors"
)

// A SegmentID is a numeric identifier for a Segment.
type SegmentID uint32

// A Segment is an allocation arena for Cap'n Proto objects.
// It is part of a Message, which can contain other segments that
// reference each other.
type Segment struct {
	msg  *Message
	id   SegmentID
	data []byte
}

// Message returns the message that contains s.
func (s *Segment) Message() *Message {
	return s.msg
}

// ID returns the segment's ID.
func (s *Segment) ID() SegmentID {
	return s.id
}

// Data returns the raw byte slice for the segment.
func (s *Segment) Data() []byte {
	return s.data
}

func (s *Segment) inBounds(addr Address) bool {
	return addr < Address(len(s.data))
}

func (s *Segment) regionInBounds(base Address, sz Size) bool {
	end, ok := base.addSize(sz)
	if !ok {
		return false
	}
	return end <= Address(len(s.data))
}

// slice returns the segment of data from base to base+sz.
func (s *Segment) slice(base Address, sz Size) []byte {
	// Bounds check should have happened before calling slice.
	return s.data[base : base+Address(sz)]
}

func (s *Segment) readUint8(addr Address) uint8 {
	return s.slice(addr, 1)[0]
}

func (s *Segment) readUint16(addr Address) uint16 {
	return binary.LittleEndian.Uint16(s.slice(addr, 2))
}

func (s *Segment) readUint32(addr Address) uint32 {
	return binary.LittleEndian.Uint32(s.slice(addr, 4))
}

func (s *Segment) readUint64(addr Address) uint64 {
	return binary.LittleEndian.Uint64(s.slice(addr, 8))
}

func (s *Segment) readRawPointer(addr Address) rawPointer {
	return rawPointer(s.readUint64(addr))
}

func (s *Segment) writeUint8(addr Address, val uint8) {
	s.slice(addr, 1)[0] = val
}

func (s *Segment) writeUint16(addr Address, val uint16) {
	binary.LittleEndian.PutUint16(s.slice(addr, 2), val)
}

func (s *Segment) writeUint32(addr Address, val uint32) {
	binary.LittleEndian.PutUint32(s.slice(addr, 4), val)
}

func (s *Segment) writeUint64(addr Address, val uint64) {
	binary.LittleEndian.PutUint64(s.slice(addr, 8), val)
}

func (s *Segment) writeRawPointer(addr Address, val rawPointer) {
	s.writeUint64(addr, uint64(val))
}

// root returns a 1-element pointer list that references the first word
// in the segment.  This only makes sense to call on the first segment
// in a message.
func (s *Segment) root() PointerList {
	sz := ObjectSize{PointerCount: 1}
	if !s.regionInBounds(0, sz.totalSize()) {
		return PointerList{}
	}
	return PointerList{List{
		seg:        s,
		length:     1,
		size:       sz,
		depthLimit: s.msg.depthLimit(),
	}}
}

func (s *Segment) lookupSegment(id SegmentID) (*Segment, error) {
	if s.id == id {
		return s, nil
	}
	return s.msg.Segment(id)
}

func (s *Segment) readPtr(off Address, depthLimit uint) (ptr Ptr, err error) {
	val := s.readRawPointer(off)
	s, off, val, err = s.resolveFarPointer(off, val)
	if err != nil {
		return Ptr{}, err
	}
	if val == 0 {
		return Ptr{}, nil
	}
	if depthLimit == 0 {
		return Ptr{}, errDepthLimit
	}
	// Be wary of overflow. Offset is 30 bits signed. List size is 29 bits
	// unsigned. For both of these we need to check in terms of words if
	// using 32 bit maths as bits or bytes will overflow.
	switch val.pointerType() {
	case structPointer:
		sp, err := s.readStructPtr(off, val)
		if err != nil {
			return Ptr{}, err
		}
		if !s.msg.ReadLimiter().canRead(sp.readSize()) {
			return Ptr{}, errReadLimit
		}
		sp.depthLimit = depthLimit - 1
		return sp.ToPtr(), nil
	case listPointer:
		lp, err := s.readListPtr(off, val)
		if err != nil {
			return Ptr{}, err
		}
		if !s.msg.ReadLimiter().canRead(lp.readSize()) {
			return Ptr{}, errReadLimit
		}
		lp.depthLimit = depthLimit - 1
		return lp.ToPtr(), nil
	case otherPointer:
		if val.otherPointerType() != 0 {
			return Ptr{}, errOtherPointer
		}
		return Interface{
			seg: s,
			cap: val.capabilityIndex(),
		}.ToPtr(), nil
	default:
		// Only other types are far pointers.
		return Ptr{}, errBadLandingPad
	}
}

func (s *Segment) readStructPtr(off Address, val rawPointer) (Struct, error) {
	addr, ok := val.offset().resolve(off)
	if !ok {
		return Struct{}, errPointerAddress
	}
	sz := val.structSize()
	if !s.regionInBounds(addr, sz.totalSize()) {
		return Struct{}, errPointerAddress
	}
	return Struct{
		seg:  s,
		off:  addr,
		size: sz,
	}, nil
}

func (s *Segment) readListPtr(off Address, val rawPointer) (List, error) {
	addr, ok := val.offset().resolve(off)
	if !ok {
		return List{}, errPointerAddress
	}
	lsize, ok := val.totalListSize()
	if !ok {
		return List{}, errOverflow
	}
	if !s.regionInBounds(addr, lsize) {
		return List{}, errPointerAddress
	}
	lt := val.listType()
	if lt == compositeList {
		hdr := s.readRawPointer(addr)
		var ok bool
		addr, ok = addr.addSize(wordSize)
		if !ok {
			return List{}, errOverflow
		}
		if hdr.pointerType() != structPointer {
			return List{}, errBadTag
		}
		sz := hdr.structSize()
		n := int32(hdr.offset())
		// TODO(light): check that this has the same end address
		if tsize, ok := sz.totalSize().times(n); !ok {
			return List{}, errOverflow
		} else if !s.regionInBounds(addr, tsize) {
			return List{}, errPointerAddress
		}
		return List{
			seg:    s,
			size:   sz,
			off:    addr,
			length: n,
			flags:  isCompositeList,
		}, nil
	}
	if lt == bit1List {
		return List{
			seg:    s,
			off:    addr,
			length: val.numListElements(),
			flags:  isBitList,
		}, nil
	}
	return List{
		seg:    s,
		size:   val.elementSize(),
		off:    addr,
		length: val.numListElements(),
	}, nil
}

func (s *Segment) resolveFarPointer(off Address, val rawPointer) (*Segment, Address, rawPointer, error) {
	switch val.pointerType() {
	case doubleFarPointer:
		// A double far pointer points to a double pointer, where the
		// first points to the actual data, and the second is the tag
		// that would normally be placed right before the data (offset
		// == 0).

		faroff, segid := val.farAddress(), val.farSegment()
		s, err := s.lookupSegment(segid)
		if err != nil {
			return nil, 0, 0, err
		}
		if !s.regionInBounds(faroff, wordSize*2) {
			return nil, 0, 0, errPointerAddress
		}
		far := s.readRawPointer(faroff)
		tagStart, ok := faroff.addSize(wordSize)
		if !ok {
			return nil, 0, 0, errOverflow
		}
		tag := s.readRawPointer(tagStart)
		if far.pointerType() != farPointer || tag.offset() != 0 {
			return nil, 0, 0, errPointerAddress
		}
		segid = far.farSegment()
		if s, err = s.lookupSegment(segid); err != nil {
			return nil, 0, 0, errBadLandingPad
		}
		return s, 0, landingPadNearPointer(far, tag), nil
	case farPointer:
		faroff, segid := val.farAddress(), val.farSegment()
		s, err := s.lookupSegment(segid)
		if err != nil {
			return nil, 0, 0, err
		}
		if !s.regionInBounds(faroff, wordSize) {
			return nil, 0, 0, errPointerAddress
		}
		val = s.readRawPointer(faroff)
		return s, faroff, val, nil
	default:
		return s, off, val, nil
	}
}

func (s *Segment) writePtr(off Address, src Ptr, forceCopy bool) error {
	if !src.IsValid() {
		s.writeRawPointer(off, 0)
		return nil
	}

	// Copy src, if needed.  This is type-dependent.
	switch src.flags.ptrType() {
	case structPtrType:
		st := src.Struct()
		if st.size.isZero() {
			// Zero-sized structs should always be encoded with offset -1 in
			// order to avoid conflating with null.  No allocation needed.
			s.writeRawPointer(off, rawStructPointer(-1, ObjectSize{}))
			return nil
		}
		if forceCopy || src.seg.msg != s.msg || st.flags&isListMember != 0 {
			newSeg, newAddr, err := alloc(s, st.size.totalSize())
			if err != nil {
				return err
			}
			dst := Struct{
				seg:        newSeg,
				off:        newAddr,
				size:       st.size,
				depthLimit: maxDepth,
				// clear flags
			}
			if err := copyStruct(dst, st); err != nil {
				return err
			}
			src = dst.ToPtr()
		}
	case listPtrType:
		if forceCopy || src.seg.msg != s.msg {
			l := src.List()
			sz := l.allocSize()
			newSeg, newAddr, err := alloc(s, sz)
			if err != nil {
				return err
			}
			dst := List{
				seg:        newSeg,
				off:        newAddr,
				length:     l.length,
				size:       l.size,
				flags:      l.flags,
				depthLimit: maxDepth,
			}
			if dst.flags&isCompositeList != 0 {
				// Copy tag word
				newSeg.writeRawPointer(newAddr, l.seg.readRawPointer(l.off-Address(wordSize)))
				var ok bool
				dst.off, ok = dst.off.addSize(wordSize)
				if !ok {
					return errOverflow
				}
				sz -= wordSize
			}
			if dst.flags&isBitList != 0 || dst.size.PointerCount == 0 {
				end, _ := l.off.addSize(sz) // list was already validated
				copy(newSeg.data[dst.off:], l.seg.data[l.off:end])
			} else {
				for i := 0; i < l.Len(); i++ {
					err := copyStruct(dst.Struct(i), l.Struct(i))
					if err != nil {
						return err
					}
				}
			}
			src = dst.ToPtr()
		}
	case interfacePtrType:
		i := src.Interface()
		if src.seg.msg != s.msg {
			c := s.msg.AddCap(i.Client())
			i = NewInterface(s, c)
		}
		s.writeRawPointer(off, i.value(off))
		return nil
	default:
		panic("unreachable")
	}

	// Create far pointer if object is in a different segment.
	if src.seg != s {
		if !hasCapacity(src.seg.data, wordSize) {
			// Double far pointer needed.
			const landingSize = wordSize * 2
			t, dstAddr, err := alloc(s, landingSize)
			if err != nil {
				return err
			}

			srcAddr := src.address()
			t.writeRawPointer(dstAddr, rawFarPointer(src.seg.id, srcAddr))
			// alloc guarantees that two words are available.
			t.writeRawPointer(dstAddr+Address(wordSize), src.value(srcAddr-Address(wordSize)))
			s.writeRawPointer(off, rawDoubleFarPointer(t.id, dstAddr))
			return nil
		}
		// Have room in the target for a tag
		_, srcAddr, _ := alloc(src.seg, wordSize)
		src.seg.writeRawPointer(srcAddr, src.value(srcAddr))
		s.writeRawPointer(off, rawFarPointer(src.seg.id, srcAddr))
		return nil
	}

	// Local pointer.
	s.writeRawPointer(off, src.value(off))
	return nil
}

var (
	errPointerAddress = errors.New("capnp: invalid pointer address")
	errBadLandingPad  = errors.New("capnp: invalid far pointer landing pad")
	errBadTag         = errors.New("capnp: invalid tag word")
	errOtherPointer   = errors.New("capnp: unknown pointer type")
	errObjectSize     = errors.New("capnp: invalid object size")
	errElementSize    = errors.New("capnp: mismatched list element size")
	errReadLimit      = errors.New("capnp: read traversal limit reached")
	errDepthLimit     = errors.New("capnp: depth limit reached")
)

var (
	errOverflow    = errors.New("capnp: address or size overflow")
	errOutOfBounds = errors.New("capnp: address out of bounds")
	errCopyDepth   = errors.New("capnp: copy depth too large")
	errOverlap     = errors.New("capnp: overlapping data on copy")
	errListSize    = errors.New("capnp: invalid list size")
)
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

type TrustPolicyDocument struct {
	Version    string      `json:",omitempty"`
	Id         string      `json:",omitempty"`
	Statements interface{} `json:"Statement"`
}

func SuppressEquivalentTrustPolicyDiffs(key string, old string, new string, d *schema.ResourceData) bool {
	UnmarshalAndMarshal(&old, &new)
	return old == new
}

//Broken into seperate function to allow for returning of errors.
func UnmarshalAndMarshal(oldPolicy *string, newPolicy *string) error {
	policyOldIntermediate := TrustPolicyDocument{}
	policyNewIntermediate := TrustPolicyDocument{}
	if err := json.Unmarshal([]byte(*oldPolicy), &policyOldIntermediate); err != nil {
		return fmt.Errorf("Error unmarshaling old trust policy: %s", err)
	}
	if err := json.Unmarshal([]byte(*newPolicy), &policyNewIntermediate); err != nil {
		return fmt.Errorf("Error unmarshaling new trust policy: %s", err)
	}

	oldByteArray, err := json.Marshal(policyOldIntermediate)
	if err != nil {
		return fmt.Errorf("Error marshaling old trust policy: %s", err)
	}
	newByteArray, err := json.Marshal(policyNewIntermediate)
	if err != nil {
		return fmt.Errorf("Error marshaling new trust policy: %s", err)
	}
	*oldPolicy = string(oldByteArray)
	*newPolicy = string(newByteArray)
	return nil
}

// Using a diff function is the currently accepted way to compare the configuration of two different attributes at plan time.
func trustPoliciesWithIncludeDefaultPolicies(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error {
	var assumeRolePolicy = diff.Get("assume_role_policy")
	var includeDefaultPolicies = (diff.Get("include_default_policies").(bool))
	if (assumeRolePolicy != nil) && (assumeRolePolicy != "") {
		if includeDefaultPolicies {
			return fmt.Errorf("include_default_policies must be false or excluded if including an assume_role_policy %#v", assumeRolePolicy)
		}
	}
	return nil
}
<commit_msg>Updated suppress diff function to be reusable<commit_after>package main

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

type TrustPolicyDocument struct {
	Version    string      `json:",omitempty"`
	Id         string      `json:",omitempty"`
	Statements interface{} `json:"Statement"`
}

func SuppressEquivalentTrustPolicyDiffs(key string, old string, new string, d *schema.ResourceData) bool {
	oldPolicy, _ := UnmarshalAndMarshal([]byte(old))
	newPolicy, _ := UnmarshalAndMarshal([]byte(new))

	return bytes.Compare(oldPolicy,newPolicy) == 0
}

//Broken into seperate function to allow for returning of errors.
func UnmarshalAndMarshal(policy []byte) ([]byte, error) {
	unmarshaledPolicy := TrustPolicyDocument{}
	if err := json.Unmarshal(policy, &unmarshaledPolicy); err != nil {
		return nil, fmt.Errorf("Error unmarshaling trust policy: %s", err)
	}

	marshaledPolicy, err := json.Marshal(unmarshaledPolicy)
	if err != nil {
		return nil, fmt.Errorf("Error marshaling trust policy: %s", err)
	}

	return marshaledPolicy, nil
}

// Using a diff function is the currently accepted way to compare the configuration of two different attributes at plan time.
func trustPoliciesWithIncludeDefaultPolicies(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error {
	var assumeRolePolicy = diff.Get("assume_role_policy")
	var includeDefaultPolicies = (diff.Get("include_default_policies").(bool))
	if (assumeRolePolicy != nil) && (assumeRolePolicy != "") {
		if includeDefaultPolicies {
			return fmt.Errorf("include_default_policies must be false or excluded if including an assume_role_policy %#v", assumeRolePolicy)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package gen_test

import . "gopkg.in/check.v1"
import "testing"
import "database/sql"
import "github.com/hydrogen18/sillyquill/gen_test/dal"
import "github.com/hydrogen18/sillyquill/rt"
import _ "github.com/lib/pq"
import "os"
import "time"

type TestSuite struct {
	db *sql.DB
}

func Test(t *testing.T) { TestingT(t) }

var _ = Suite(&TestSuite{})

func (s *TestSuite) SetUpSuite(c *C) {
	var err error
	s.db, err = sql.Open("postgres", os.Getenv("DB"))
	c.Assert(err, IsNil)
	err = s.db.Ping()
	c.Assert(err, IsNil)
}
func (s *TestSuite) TearDownSuite(c *C) {
	if s.db != nil {
		s.db.Close()
	}
}

func (s *TestSuite) TestErrOnNonUniquelyIdentifiables(c *C) {
	//This type can never be identified uniquely
	i := new(dal.NotUniquelyIdentifiable)
	i.SetAge(42)
	i.SetId(44)

	err := i.FindOrCreate(s.db)
	c.Assert(err, FitsTypeOf, sillyquill_rt.RowNotUniquelyIdentifiableError{})

	//This instance can not be identified uniquely
	j := new(dal.Incident)
	resolution := "MEOW"
	j.SetResolution(&resolution)
	err = j.FindOrCreate(s.db)
	c.Assert(err, FitsTypeOf, sillyquill_rt.RowNotUniquelyIdentifiableError{})
}

func (s *TestSuite) TestNoOverwritingExistingFields(c *C) {
	i := new(dal.Incident)
	var resolution string
	resolution = "PEBKAC"
	i.SetResolution(&resolution)

	err := i.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(i.IsLoaded.Id, Equals, true)

	j := new(dal.Incident)
	j.SetId(i.Id)
	var notTheResolution string
	notTheResolution = "fatality"
	j.SetResolution(&notTheResolution)
	err = j.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	c.Assert(j.IsLoaded.Resolution, Equals, true)
	c.Assert(*j.Resolution, Equals, *i.Resolution)

}

func (s *TestSuite) TestNumeric(c *C) {
	aNumber := new(dal.Number)
	var v sillyquill_rt.Numeric
	v.SetString("2632624.626332")
	aNumber.SetValue(v)

	err := aNumber.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aNumber.IsLoaded.Id, Equals, true)

	sameNumber := new(dal.Number)
	sameNumber.SetId(aNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, DeepEquals, aNumber.Value)
}

func (s *TestSuite) TestNumericNull(c *C) {
	nullNumber := new(dal.NullNumber)
	nullNumber.SetTitle("mewo")
	err := nullNumber.Create(s.db)
	c.Assert(err, IsNil)

	aNumber := new(dal.NullNumber)
	var v sillyquill_rt.NullNumeric
	aNumber.SetTitle("kitties")
	v.SetString("135135.16136")
	aNumber.SetValue(&v)

	err = aNumber.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aNumber.IsLoaded.Id, Equals, true)

	sameNumber := new(dal.NullNumber)
	sameNumber.SetId(aNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, DeepEquals, aNumber.Value)

	sameNumber = new(dal.NullNumber)
	sameNumber.SetId(nullNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, IsNil)
}

func (s *TestSuite) TestArchiveFiles(c *C) {
	aFile := new(dal.ArchiveFile)
	aFile.SetName("foo.txt")
	var FOO_DATA = []byte{0x1, 0x2, 0x3}
	aFile.SetData(FOO_DATA)
	err := aFile.Create(s.db)
	c.Assert(err, IsNil)
	fooId := aFile.Id

	aFile = new(dal.ArchiveFile)
	aFile.SetName("bar.txt")
	aFile.SetData([]byte{}) //Test that zero-length doesn't violate not-null constraint
	err = aFile.Create(s.db)
	c.Assert(err, IsNil)

	//Test load by unique
	aFile = new(dal.ArchiveFile)
	aFile.SetId(fooId)
	err = aFile.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(aFile.Name, Equals, "foo.txt")
	c.Assert(aFile.Data, DeepEquals, FOO_DATA)
}

func (s *TestSuite) TestPizzaDeliveryGuys(c *C) {
	aGuy := new(dal.PizzaDeliveryGuy)
	aGuy.SetName("bob")
	aGuy.SetGasMileage(16.4)
	err := aGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	/** TODO fixme
	err = aGuy.FindOrCreate(s.db)
	c.Assert(err, Equals,NoColumnsSetError)
	**/
	//Test Reload
	err = aGuy.Reload(s.db)
	c.Assert(err, IsNil)

	//Test find by primary key
	sameGuy := new(dal.PizzaDeliveryGuy)
	sameGuy.SetName(aGuy.Name)
	err = sameGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	//Create another pizza delivery guy
	secondGuy := new(dal.PizzaDeliveryGuy)
	secondGuy.SetName("rufus")
	secondGuy.SetGasMileage(36.0)
	err = secondGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	//Test Save
	aGuy.SetGasMileage(15.0)
	err = aGuy.Save(s.db)
	c.Assert(err, IsNil)

	//Test save w/ no params
	//TODO fixme
	/**
	err = aGuy.Save(s.db)
	c.Assert(err, IsNil)
	**/

	err = aGuy.Reload(s.db)
	c.Assert(err, IsNil)

	err = secondGuy.Reload(s.db)
	c.Assert(err, IsNil)

	//Test for wild where clause in update
	c.Assert(aGuy.GasMileage, Equals, 15.0)
	c.Assert(aGuy.GasMileage, Not(Equals), secondGuy.GasMileage)

}

func (s *TestSuite) TestCreateCar(c *C) {
	aCar := new(dal.Car)
	aCar.SetMake("kia")
	aCar.SetModel("rio")
	aCar.SetPassengers(5)
	err := aCar.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aCar.IsLoaded.UpdatedAt, Equals, true)
	c.Assert(aCar.UpdatedAt, Not(Equals), time.Time{})

	//Test searching by primary key
	sameCar := new(dal.Car)
	sameCar.SetMake(aCar.Make)
	sameCar.SetModel(aCar.Model)
	err = sameCar.Get(s.db)
	c.Assert(err, IsNil)

	//Get loads all columns by default
	c.Assert(sameCar.IsLoaded.Id, Equals, true)
	c.Assert(sameCar.Id, Equals, aCar.Id)

	//Test searching by unique column partial load
	sameCar = new(dal.Car)
	sameCar.SetId(aCar.Id)
	err = sameCar.Get(s.db, dal.Cars.Passengers)
	c.Assert(err, IsNil)
	c.Assert(sameCar.IsLoaded.Passengers, Equals, true)
	c.Assert(sameCar.IsLoaded.Make, Equals, false)
	c.Assert(sameCar.IsLoaded.Model, Equals, false)
	c.Assert(sameCar.Passengers, Equals, aCar.Passengers)

	//Create another car
	aCar = new(dal.Car)
	aCar.SetMake("mazda")
	aCar.SetModel("rx-7")
	aCar.SetPassengers(5)
	err = aCar.FindOrCreate(s.db)
	c.Assert(err, IsNil)
	c.Assert(aCar.Id, Not(Equals), sameCar.Id)

}

func (s *TestSuite) TestCreateTruck(c *C) {
	aTruck := new(dal.Truck)
	aTruck.SetMake("volvo")
	aTruck.SetModel("t-1000")
	aTruck.SetTonnage(13.5)
	err := aTruck.Create(s.db)
	c.Assert(err, IsNil)

	aTruck = new(dal.Truck)
	aTruck.SetMake("ford")
	aTruck.SetModel("f150")
	aTruck.SetTonnage(0.5)
	err = aTruck.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	aTruck = new(dal.Truck)
	aTruck.SetMake("chevy")
	aTruck.SetModel("k1500")
	aTruck.SetTonnage(0.5)
	now := time.Now().Truncate(time.Second).Add(10 * time.Minute)
	aTruck.SetCreatedAt(now)
	aTruck.SetUpdatedAt(now)
	err = aTruck.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	c.Assert(aTruck.CreatedAt.UTC(), DeepEquals, now.UTC())
	c.Assert(aTruck.UpdatedAt.UTC(), DeepEquals, now.UTC())

	sameTruck := new(dal.Truck)
	sameTruck.SetId(aTruck.Id)
	err = sameTruck.Get(s.db)
	c.Assert(err, IsNil)
	sameTruck.IsSet = aTruck.IsSet //Clear flags
	c.Assert(*sameTruck, Equals, *aTruck)
}
<commit_msg>expand tests<commit_after>package gen_test

import . "gopkg.in/check.v1"
import "testing"
import "database/sql"
import "github.com/hydrogen18/sillyquill/gen_test/dal"
import "github.com/hydrogen18/sillyquill/rt"
import _ "github.com/lib/pq"
import "os"
import "time"

type TestSuite struct {
	db *sql.DB
}

func Test(t *testing.T) { TestingT(t) }

var _ = Suite(&TestSuite{})

func (s *TestSuite) SetUpSuite(c *C) {
	var err error
	s.db, err = sql.Open("postgres", os.Getenv("DB"))
	c.Assert(err, IsNil)
	err = s.db.Ping()
	c.Assert(err, IsNil)
}
func (s *TestSuite) TearDownSuite(c *C) {
	if s.db != nil {
		s.db.Close()
	}
}

func (s *TestSuite) TestErrOnNonUniquelyIdentifiables(c *C) {
	//This type can never be identified uniquely
	i := new(dal.NotUniquelyIdentifiable)
	i.SetAge(42)
	i.SetId(44)

	err := i.FindOrCreate(s.db)
	c.Check(err, FitsTypeOf, sillyquill_rt.RowNotUniquelyIdentifiableError{})

	//This could be made to work but doesn't because the created row
	//would not be identifiable
	err = i.Create(s.db)
	c.Check(err, FitsTypeOf, sillyquill_rt.RowNotUniquelyIdentifiableError{})

	//This instance can not be identified uniquely
	j := new(dal.Incident)
	resolution := "MEOW"
	j.SetResolution(&resolution)
	err = j.FindOrCreate(s.db)
	c.Check(err, FitsTypeOf, sillyquill_rt.RowNotUniquelyIdentifiableError{})

	err = j.Create(s.db) //Should suceed because the ID column can be populated by the DB
	c.Check(err, IsNil)
	c.Assert(j.IsLoaded.Id, Equals, true)
}

func (s *TestSuite) TestNoOverwritingExistingFields(c *C) {
	i := new(dal.Incident)
	var resolution string
	resolution = "PEBKAC"
	i.SetResolution(&resolution)

	err := i.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(i.IsLoaded.Id, Equals, true)

	j := new(dal.Incident)
	j.SetId(i.Id)
	var notTheResolution string
	notTheResolution = "fatality"
	j.SetResolution(&notTheResolution)
	err = j.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	c.Assert(j.IsLoaded.Resolution, Equals, true)
	c.Assert(*j.Resolution, Equals, *i.Resolution)

}

func (s *TestSuite) TestNumeric(c *C) {
	aNumber := new(dal.Number)
	var v sillyquill_rt.Numeric
	v.SetString("2632624.626332")
	aNumber.SetValue(v)

	err := aNumber.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aNumber.IsLoaded.Id, Equals, true)

	sameNumber := new(dal.Number)
	sameNumber.SetId(aNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, DeepEquals, aNumber.Value)
}

func (s *TestSuite) TestNumericNull(c *C) {
	nullNumber := new(dal.NullNumber)
	nullNumber.SetTitle("mewo")
	err := nullNumber.Create(s.db)
	c.Assert(err, IsNil)

	aNumber := new(dal.NullNumber)
	var v sillyquill_rt.NullNumeric
	aNumber.SetTitle("kitties")
	v.SetString("135135.16136")
	aNumber.SetValue(&v)

	err = aNumber.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aNumber.IsLoaded.Id, Equals, true)

	sameNumber := new(dal.NullNumber)
	sameNumber.SetId(aNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, DeepEquals, aNumber.Value)

	sameNumber = new(dal.NullNumber)
	sameNumber.SetId(nullNumber.Id)
	err = sameNumber.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(sameNumber.Value, IsNil)
}

func (s *TestSuite) TestArchiveFiles(c *C) {
	aFile := new(dal.ArchiveFile)
	aFile.SetName("foo.txt")
	var FOO_DATA = []byte{0x1, 0x2, 0x3}
	aFile.SetData(FOO_DATA)
	err := aFile.Create(s.db)
	c.Assert(err, IsNil)
	fooId := aFile.Id

	aFile = new(dal.ArchiveFile)
	aFile.SetName("bar.txt")
	aFile.SetData([]byte{}) //Test that zero-length doesn't violate not-null constraint
	err = aFile.Create(s.db)
	c.Assert(err, IsNil)

	//Test load by unique
	aFile = new(dal.ArchiveFile)
	aFile.SetId(fooId)
	err = aFile.Get(s.db)
	c.Assert(err, IsNil)
	c.Assert(aFile.Name, Equals, "foo.txt")
	c.Assert(aFile.Data, DeepEquals, FOO_DATA)
}

func (s *TestSuite) TestPizzaDeliveryGuys(c *C) {
	aGuy := new(dal.PizzaDeliveryGuy)
	aGuy.SetName("bob")
	aGuy.SetGasMileage(16.4)
	err := aGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	/** TODO fixme
	err = aGuy.FindOrCreate(s.db)
	c.Assert(err, Equals,NoColumnsSetError)
	**/
	//Test Reload
	err = aGuy.Reload(s.db)
	c.Assert(err, IsNil)

	//Test find by primary key
	sameGuy := new(dal.PizzaDeliveryGuy)
	sameGuy.SetName(aGuy.Name)
	err = sameGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	//Create another pizza delivery guy
	secondGuy := new(dal.PizzaDeliveryGuy)
	secondGuy.SetName("rufus")
	secondGuy.SetGasMileage(36.0)
	err = secondGuy.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	//Test Save
	aGuy.SetGasMileage(15.0)
	err = aGuy.Save(s.db)
	c.Assert(err, IsNil)

	//Test save w/ no params
	//TODO fixme
	/**
	err = aGuy.Save(s.db)
	c.Assert(err, IsNil)
	**/

	err = aGuy.Reload(s.db)
	c.Assert(err, IsNil)

	err = secondGuy.Reload(s.db)
	c.Assert(err, IsNil)

	//Test for wild where clause in update
	c.Assert(aGuy.GasMileage, Equals, 15.0)
	c.Assert(aGuy.GasMileage, Not(Equals), secondGuy.GasMileage)

}

func (s *TestSuite) TestCreateCar(c *C) {
	aCar := new(dal.Car)
	aCar.SetMake("kia")
	aCar.SetModel("rio")
	aCar.SetPassengers(5)
	err := aCar.Create(s.db)
	c.Assert(err, IsNil)
	c.Assert(aCar.IsLoaded.UpdatedAt, Equals, true)
	c.Assert(aCar.UpdatedAt, Not(Equals), time.Time{})

	//Test searching by primary key
	sameCar := new(dal.Car)
	sameCar.SetMake(aCar.Make)
	sameCar.SetModel(aCar.Model)
	err = sameCar.Get(s.db)
	c.Assert(err, IsNil)

	//Get loads all columns by default
	c.Assert(sameCar.IsLoaded.Id, Equals, true)
	c.Assert(sameCar.Id, Equals, aCar.Id)

	//Test searching by unique column partial load
	sameCar = new(dal.Car)
	sameCar.SetId(aCar.Id)
	err = sameCar.Get(s.db, dal.Cars.Passengers)
	c.Assert(err, IsNil)
	c.Assert(sameCar.IsLoaded.Passengers, Equals, true)
	c.Assert(sameCar.IsLoaded.Make, Equals, false)
	c.Assert(sameCar.IsLoaded.Model, Equals, false)
	c.Assert(sameCar.Passengers, Equals, aCar.Passengers)

	//Create another car
	aCar = new(dal.Car)
	aCar.SetMake("mazda")
	aCar.SetModel("rx-7")
	aCar.SetPassengers(5)
	err = aCar.FindOrCreate(s.db)
	c.Assert(err, IsNil)
	c.Assert(aCar.Id, Not(Equals), sameCar.Id)

}

func (s *TestSuite) TestCreateTruck(c *C) {
	aTruck := new(dal.Truck)
	aTruck.SetMake("volvo")
	aTruck.SetModel("t-1000")
	aTruck.SetTonnage(13.5)
	err := aTruck.Create(s.db)
	c.Assert(err, IsNil)

	aTruck = new(dal.Truck)
	aTruck.SetMake("ford")
	aTruck.SetModel("f150")
	aTruck.SetTonnage(0.5)
	err = aTruck.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	aTruck = new(dal.Truck)
	aTruck.SetMake("chevy")
	aTruck.SetModel("k1500")
	aTruck.SetTonnage(0.5)
	now := time.Now().Truncate(time.Second).Add(10 * time.Minute)
	aTruck.SetCreatedAt(now)
	aTruck.SetUpdatedAt(now)
	err = aTruck.FindOrCreate(s.db)
	c.Assert(err, IsNil)

	c.Assert(aTruck.CreatedAt.UTC(), DeepEquals, now.UTC())
	c.Assert(aTruck.UpdatedAt.UTC(), DeepEquals, now.UTC())

	sameTruck := new(dal.Truck)
	sameTruck.SetId(aTruck.Id)
	err = sameTruck.Get(s.db)
	c.Assert(err, IsNil)
	sameTruck.IsSet = aTruck.IsSet //Clear flags
	c.Assert(*sameTruck, Equals, *aTruck)
}
<|endoftext|>


<commit_before>package gospell

import (
	"strings"
	"unicode"
)

// WordCase is an enum of various word casing styles
type WordCase int

// Various WordCase types.. likely to be not correct
const (
	AllLower WordCase = iota
	AllUpper
	Title
	Mixed
	Camel
)

// CaseStyle returns what case style a word is in
func CaseStyle(word string) WordCase {
	hasTitle := false
	upperCount := 0
	lowerCount := 0
	runeCount := 0

	// this iterates over RUNES not BYTES
	for _, r := range word {
		// ASCII apostrophe doesn't count
		//  want words like "don't" to have
		//  upper case forms when adding to dictionary
		if r == 0x0027 {
			continue
		}
		runeCount++
		if unicode.IsLower(r) {
			lowerCount++
			continue
		}
		if unicode.IsUpper(r) {
			if runeCount == 1 {
				hasTitle = true
			}
			upperCount++
			continue
		}

		//???
	}

	switch {
	case runeCount == lowerCount:
		return AllLower
	case runeCount == upperCount:
		return AllUpper
	case hasTitle && runeCount-1 == lowerCount:
		return Title
	default:
		return Mixed
	}
}

func caseVariations(word string) []string {
	switch CaseStyle(word) {
	case AllLower:
		return []string{word, strings.ToUpper(word[0:1]) + word[1:], strings.ToUpper(word)}
	case AllUpper:
		return []string{strings.ToUpper(word)}
	case Title:
		return []string{word, strings.ToUpper(word)}
	case Mixed:
		return []string{word, strings.ToUpper(word)}
	default:
		return []string{word}
	}
}
<commit_msg>Simplify case<commit_after>package gospell

import (
	"strings"
	"unicode"
)

// WordCase is an enum of various word casing styles
type WordCase int

// Various WordCase types.. likely to be not correct
const (
	AllLower WordCase = iota
	AllUpper
	Title
	Mixed
	Camel
)

// CaseStyle returns what case style a word is in
func CaseStyle(word string) WordCase {
	hasTitle := false
	upperCount := 0
	lowerCount := 0
	runeCount := 0

	// this iterates over RUNES not BYTES
	for _, r := range word {
		// ASCII apostrophe doesn't count
		//  want words like "don't" to have
		//  upper case forms when adding to dictionary
		if r == 0x0027 {
			continue
		}
		runeCount++
		if unicode.IsLower(r) {
			lowerCount++
			continue
		}
		if unicode.IsUpper(r) {
			if runeCount == 1 {
				hasTitle = true
			}
			upperCount++
			continue
		}

		//???
	}

	switch {
	case runeCount == lowerCount:
		return AllLower
	case runeCount == upperCount:
		return AllUpper
	case hasTitle && runeCount-1 == lowerCount:
		return Title
	default:
		return Mixed
	}
}

func caseVariations(word string) []string {
	switch CaseStyle(word) {
	case AllLower:
		return []string{word, strings.ToUpper(word[0:1]) + word[1:], strings.ToUpper(word)}
	case AllUpper:
		return []string{strings.ToUpper(word)}
	default:
		return []string{word, strings.ToUpper(word)}
	}
}
<|endoftext|>


<commit_before>// Package logging provides a fast, asynchronous request logger which outputs
// NCSA/Apache combined logs.
package logging

import (
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)

// A LoggingHandler is a HTTP handler which proxies requests to an underlying
// handler and logs the results.
type LoggingHandler struct {
	clock   clock
	w       io.Writer
	handler http.Handler
	buffer  chan string
	quit    chan bool
}

// Wrap returns the underlying handler, wrapped in a LoggingHandler which will
// write to the given Writer. N.B.: You must call Start() on the result before
// using it.
func Wrap(h http.Handler, w io.Writer) *LoggingHandler {
	return &LoggingHandler{
		clock:   time.Now,
		w:       w,
		handler: h,
		buffer:  make(chan string, 1000),
		quit:    make(chan bool),
	}
}

// Start creates a goroutine to handle the logging IO.
func (al *LoggingHandler) Start() {
	go func() {
		for s := range al.buffer {
			fmt.Fprint(al.w, s)
		}
		al.quit <- true
	}()
}

// Stop closes the internal channel used to buffer log statements and waits for
// the IO goroutine to complete.
func (al *LoggingHandler) Stop() {
	close(al.buffer)
	<-al.quit
}

func (al *LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	wrapper := &responseWrapper{w: w, status: 200}

	start := al.clock()
	al.handler.ServeHTTP(wrapper, r)
	end := al.clock()

	remoteAddr := r.RemoteAddr
	if index := strings.LastIndex(remoteAddr, ":"); index != -1 {
		remoteAddr = remoteAddr[:index]
	}

	if s := r.Header.Get(xForwardedFor); s != "" {
		remoteAddr = s
	}

	referer := r.Referer()
	if "" == referer {
		referer = "-"
	}

	userAgent := r.UserAgent()
	if "" == userAgent {
		userAgent = "-"
	}

	al.buffer <- fmt.Sprintf(
		"%s %s %s [%s] \"%s %s %s\" %d %d %q %q %d %q\n",
		remoteAddr,
		"-", // We're not supporting identd, sorry.
		"-", // We're also not supporting basic auth.
		start.In(time.UTC).Format(apacheFormat),
		r.Method,
		r.RequestURI,
		r.Proto,
		wrapper.status,
		0,
		referer,
		userAgent,
		end.Sub(start).Nanoseconds()/int64(time.Millisecond),
		r.Header.Get(xRequestID),
	)
}

const (
	apacheFormat  = "02/Jan/2006:15:04:05 -0700"
	xRequestID    = "X-Request-Id"
	xForwardedFor = "X-Forwarded-For"
)

type responseWrapper struct {
	w      http.ResponseWriter
	status int
}

func (w *responseWrapper) Header() http.Header {
	return w.w.Header()
}

func (w *responseWrapper) Write(b []byte) (int, error) {
	return w.w.Write(b)
}

func (w *responseWrapper) WriteHeader(status int) {
	w.status = status
	w.w.WriteHeader(status)
}

type clock func() time.Time
<commit_msg>Replace the quit bool chan by an empty struct chan.<commit_after>// Package logging provides a fast, asynchronous request logger which outputs
// NCSA/Apache combined logs.
package logging

import (
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)

// A LoggingHandler is a HTTP handler which proxies requests to an underlying
// handler and logs the results.
type LoggingHandler struct {
	clock   clock
	w       io.Writer
	handler http.Handler
	buffer  chan string
	quit    chan struct{}
}

// Wrap returns the underlying handler, wrapped in a LoggingHandler which will
// write to the given Writer. N.B.: You must call Start() on the result before
// using it.
func Wrap(h http.Handler, w io.Writer) *LoggingHandler {
	return &LoggingHandler{
		clock:   time.Now,
		w:       w,
		handler: h,
		buffer:  make(chan string, 1000),
		quit:    make(chan struct{}),
	}
}

// Start creates a goroutine to handle the logging IO.
func (al *LoggingHandler) Start() {
	go func() {
		for s := range al.buffer {
			fmt.Fprint(al.w, s)
		}
		close(al.quit)
	}()
}

// Stop closes the internal channel used to buffer log statements and waits for
// the IO goroutine to complete.
func (al *LoggingHandler) Stop() {
	close(al.buffer)
	<-al.quit

}

func (al *LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	wrapper := &responseWrapper{w: w, status: 200}

	start := al.clock()
	al.handler.ServeHTTP(wrapper, r)
	end := al.clock()

	remoteAddr := r.RemoteAddr
	if index := strings.LastIndex(remoteAddr, ":"); index != -1 {
		remoteAddr = remoteAddr[:index]
	}

	if s := r.Header.Get(xForwardedFor); s != "" {
		remoteAddr = s
	}

	referer := r.Referer()
	if "" == referer {
		referer = "-"
	}

	userAgent := r.UserAgent()
	if "" == userAgent {
		userAgent = "-"
	}

	al.buffer <- fmt.Sprintf(
		"%s %s %s [%s] \"%s %s %s\" %d %d %q %q %d %q\n",
		remoteAddr,
		"-", // We're not supporting identd, sorry.
		"-", // We're also not supporting basic auth.
		start.In(time.UTC).Format(apacheFormat),
		r.Method,
		r.RequestURI,
		r.Proto,
		wrapper.status,
		0,
		referer,
		userAgent,
		end.Sub(start).Nanoseconds()/int64(time.Millisecond),
		r.Header.Get(xRequestID),
	)
}

const (
	apacheFormat  = "02/Jan/2006:15:04:05 -0700"
	xRequestID    = "X-Request-Id"
	xForwardedFor = "X-Forwarded-For"
)

type responseWrapper struct {
	w      http.ResponseWriter
	status int
}

func (w *responseWrapper) Header() http.Header {
	return w.w.Header()
}

func (w *responseWrapper) Write(b []byte) (int, error) {
	return w.w.Write(b)
}

func (w *responseWrapper) WriteHeader(status int) {
	w.status = status
	w.w.WriteHeader(status)
}

type clock func() time.Time
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"goim/libs/define"
	inet "goim/libs/net"
	"goim/libs/proto"
	"net/rpc"
	"time"

	log "github.com/thinkboy/log4go"
	"sync/atomic"
)

var (
	cometServiceMap = make(map[int32]*Comet)
)

const (
	CometService              = "PushRPC"
	CometServicePing          = "PushRPC.Ping"
	CometServiceRooms         = "PushRPC.Rooms"
	CometServicePushMsg       = "PushRPC.PushMsg"
	CometServiceMPushMsg      = "PushRPC.MPushMsg"
	CometServiceBroadcast     = "PushRPC.Broadcast"
	CometServiceBroadcastRoom = "PushRPC.BroadcastRoom"
)

type CometOptions struct {
	RoutineAmount int64
	RoutineSize   int
	CallSize      int
}

type Comet struct {
	serverId             int32
	rpcClient            *rpc.Client
	pushRoutines         []chan *proto.MPushMsgArg
	broadcastRoutines    []chan *proto.BoardcastArg
	roomRoutines         []chan *proto.BoardcastRoomArg
	pushRoutinesNum      int64
	roomRoutinesNum      int64
	broadcastRoutinesNum int64
	options              CometOptions
}

// user push
func (cm *Comet) Push(arg *proto.MPushMsgArg) (err error) {
	num := atomic.AddInt64(&cm.pushRoutinesNum, 1) % cm.options.RoutineAmount
	cm.pushRoutines[num] <- arg
	return
}

// room push
func (cm *Comet) BroadcastRoom(arg *proto.BoardcastRoomArg) (err error) {
	num := atomic.AddInt64(&cm.roomRoutinesNum, 1) % cm.options.RoutineAmount
	cm.roomRoutines[num] <- arg
	return
}

// broadcast
func (cm *Comet) Broadcast(arg *proto.BoardcastArg) (err error) {
	num := atomic.AddInt64(&cm.broadcastRoutinesNum, 1) % cm.options.RoutineAmount
	cm.broadcastRoutines[num] <- arg
	return
}

// process
func (c *Comet) process(pushChan chan *proto.MPushMsgArg, roomChan chan *proto.BoardcastRoomArg, broadcastChan chan *proto.BoardcastArg) {
	var (
		pushArg      *proto.MPushMsgArg
		roomArg      *proto.BoardcastRoomArg
		broadcastArg *proto.BoardcastArg
		reply        = &proto.NoReply{}
		done         = make(chan *rpc.Call, c.options.CallSize)
		call         *rpc.Call
	)
	for {
		select {
		case pushArg = <-pushChan:
			// push
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceMPushMsg, pushArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceMPushMsg, pushArg, c.serverId, ErrComet)
			}
			pushArg = nil
		case roomArg = <-roomChan:
			// room
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceBroadcastRoom, roomArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceBroadcastRoom, roomArg, c.serverId, ErrComet)
			}
			roomArg = nil
		case broadcastArg = <-broadcastChan:
			// broadcast
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceBroadcast, broadcastArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceBroadcast, broadcastArg, c.serverId, ErrComet)
			}
			broadcastArg = nil
		case call = <-done:
			// result
			if call.Error != nil {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", call.ServiceMethod, call.Args, c.serverId, call.Error)
			}
			call = nil
		}
	}
}

// Reconnect for ping rpc server and reconnect with it when it's crash.
func (c *Comet) ping(network, address string) {
	var (
		call  *rpc.Call
		ch    = make(chan *rpc.Call, 1)
		args  = proto.NoArg{}
		reply = proto.NoReply{}
	)
	for {
		if c.rpcClient != nil {
			call = <-c.rpcClient.Go(CometServicePing, &args, &reply, ch).Done
			if call.Error != nil {
				log.Error("rpc ping %s error(%v)", address, call.Error)
			}
		}
		if c.rpcClient == nil || call.Error != nil {
			if newCli, err := rpc.Dial(network, address); err == nil {
				c.rpcClient = newCli
			}
		}
		time.Sleep(1 * time.Second)
	}
}

func InitComet(addrs map[int32]string, options CometOptions) (err error) {
	for serverID, addrsTmp := range addrs {
		var (
			c             *Comet
			rpcClient     *rpc.Client
			network, addr string
		)
		if network, addr, err = inet.ParseNetwork(addrsTmp); err != nil {
			log.Error("inet.ParseNetwork() error(%v)", err)
			return
		}
		if rpcClient, err = rpc.Dial(network, addr); err != nil {
			log.Error("rpc.Dial(\"%s\") error(%s)", addr, err)
		}
		// comet
		c = new(Comet)
		c.serverId = serverID
		c.pushRoutines = make([]chan *proto.MPushMsgArg, options.RoutineAmount)
		c.roomRoutines = make([]chan *proto.BoardcastRoomArg, options.RoutineAmount)
		c.broadcastRoutines = make([]chan *proto.BoardcastArg, options.RoutineAmount)
		c.options = options
		c.rpcClient = rpcClient
		cometServiceMap[serverID] = c
		// process
		for i := int64(0); i < options.RoutineAmount; i++ {
			pushChan := make(chan *proto.MPushMsgArg, options.RoutineSize)
			roomChan := make(chan *proto.BoardcastRoomArg, options.RoutineSize)
			broadcastChan := make(chan *proto.BoardcastArg, options.RoutineSize)
			c.pushRoutines[i] = pushChan
			c.roomRoutines[i] = roomChan
			c.broadcastRoutines[i] = broadcastChan
			go c.process(pushChan, roomChan, broadcastChan)
		}
		// ping & reconnect
		go c.ping(network, addr)
		log.Info("init comet rpc addr:%s connection", addr)
	}
	return
}

// mPushComet push a message to a batch of subkeys
func mPushComet(serverId int32, subKeys []string, body json.RawMessage) {
	var args = &proto.MPushMsgArg{
		Keys: subKeys, P: proto.Proto{Ver: 0, Operation: define.OP_SEND_SMS_REPLY, Body: body, Time: time.Now()},
	}
	if c, ok := cometServiceMap[serverId]; ok {
		if err := c.Push(args); err != nil {
			log.Error("c.Push(%v) serverId:%d error(%v)", args, serverId, err)
		}
	}
}

// broadcast broadcast a message to all
func broadcast(msg []byte) {
	var args = &proto.BoardcastArg{
		P: proto.Proto{Ver: 0, Operation: define.OP_SEND_SMS_REPLY, Body: msg, Time: time.Now()},
	}
	for serverId, c := range cometServiceMap {
		if err := c.Broadcast(args); err != nil {
			log.Error("c.Broadcast(%v) serverId:%d error(%v)", args, serverId, err)
		}
	}
}

// broadcastRoomBytes broadcast aggregation messages to room
func broadcastRoomBytes(roomId int32, body []byte) {
	var (
		args     = proto.BoardcastRoomArg{P: proto.Proto{Ver: 0, Operation: define.OP_RAW, Body: body, Time: time.Now()}, RoomId: roomId}
		c        *Comet
		serverId int32
		servers  map[int32]struct{}
		ok       bool
		err      error
	)
	if servers, ok = RoomServersMap[roomId]; ok {
		for serverId, _ = range servers {
			if c, ok = cometServiceMap[serverId]; ok {
				// push routines
				if err = c.BroadcastRoom(&args); err != nil {
					log.Error("c.BroadcastRoom(%v) roomId:%d error(%v)", args, roomId, err)
				}
			}
		}
	}
}

func roomsComet(c *rpc.Client) []int32 {
	var (
		args  = proto.NoArg{}
		reply = proto.RoomsReply{}
		err   error
	)
	if err = c.Call(CometServiceRooms, &args, &reply); err != nil {
		log.Error("c.Call(%s, 0, reply) error(%v)", CometServiceRooms, err)
		return nil
	}
	return reply.RoomIds
}
<commit_msg>optimize code<commit_after>package main

import (
	"encoding/json"
	"goim/libs/define"
	inet "goim/libs/net"
	"goim/libs/proto"
	"net/rpc"
	"time"

	log "github.com/thinkboy/log4go"
	"sync/atomic"
)

var (
	cometServiceMap = make(map[int32]*Comet)
)

const (
	CometService              = "PushRPC"
	CometServicePing          = "PushRPC.Ping"
	CometServiceRooms         = "PushRPC.Rooms"
	CometServicePushMsg       = "PushRPC.PushMsg"
	CometServiceMPushMsg      = "PushRPC.MPushMsg"
	CometServiceBroadcast     = "PushRPC.Broadcast"
	CometServiceBroadcastRoom = "PushRPC.BroadcastRoom"
)

type CometOptions struct {
	RoutineAmount int64
	RoutineSize   int
	CallSize      int
}

type Comet struct {
	serverId             int32
	rpcClient            *rpc.Client
	pushRoutines         []chan *proto.MPushMsgArg
	broadcastRoutines    []chan *proto.BoardcastArg
	roomRoutines         []chan *proto.BoardcastRoomArg
	pushRoutinesNum      int64
	roomRoutinesNum      int64
	broadcastRoutinesNum int64
	options              CometOptions
}

// user push
func (c *Comet) Push(arg *proto.MPushMsgArg) (err error) {
	num := atomic.AddInt64(&c.pushRoutinesNum, 1) % c.options.RoutineAmount
	c.pushRoutines[num] <- arg
	return
}

// room push
func (c *Comet) BroadcastRoom(arg *proto.BoardcastRoomArg) (err error) {
	num := atomic.AddInt64(&c.roomRoutinesNum, 1) % c.options.RoutineAmount
	c.roomRoutines[num] <- arg
	return
}

// broadcast
func (c *Comet) Broadcast(arg *proto.BoardcastArg) (err error) {
	num := atomic.AddInt64(&c.broadcastRoutinesNum, 1) % c.options.RoutineAmount
	c.broadcastRoutines[num] <- arg
	return
}

// process
func (c *Comet) process(pushChan chan *proto.MPushMsgArg, roomChan chan *proto.BoardcastRoomArg, broadcastChan chan *proto.BoardcastArg) {
	var (
		pushArg      *proto.MPushMsgArg
		roomArg      *proto.BoardcastRoomArg
		broadcastArg *proto.BoardcastArg
		reply        = &proto.NoReply{}
		done         = make(chan *rpc.Call, c.options.CallSize)
		call         *rpc.Call
	)
	for {
		select {
		case pushArg = <-pushChan:
			// push
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceMPushMsg, pushArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceMPushMsg, pushArg, c.serverId, ErrComet)
			}
			pushArg = nil
		case roomArg = <-roomChan:
			// room
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceBroadcastRoom, roomArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceBroadcastRoom, roomArg, c.serverId, ErrComet)
			}
			roomArg = nil
		case broadcastArg = <-broadcastChan:
			// broadcast
			if c.rpcClient != nil {
				c.rpcClient.Go(CometServiceBroadcast, broadcastArg, reply, done)
			} else {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", CometServiceBroadcast, broadcastArg, c.serverId, ErrComet)
			}
			broadcastArg = nil
		case call = <-done:
			// result
			if call.Error != nil {
				log.Error("rpcClient.Go(%s, %v, reply, done) serverId:%d error(%v)", call.ServiceMethod, call.Args, c.serverId, call.Error)
			}
			call = nil
		}
	}
}

// Reconnect for ping rpc server and reconnect with it when it's crash.
func (c *Comet) ping(network, address string) {
	var (
		call  *rpc.Call
		ch    = make(chan *rpc.Call, 1)
		args  = proto.NoArg{}
		reply = proto.NoReply{}
	)
	for {
		if c.rpcClient != nil {
			call = <-c.rpcClient.Go(CometServicePing, &args, &reply, ch).Done
			if call.Error != nil {
				log.Error("rpc ping %s error(%v)", address, call.Error)
			}
		}
		if c.rpcClient == nil || call.Error != nil {
			if newCli, err := rpc.Dial(network, address); err == nil {
				c.rpcClient = newCli
			}
		}
		time.Sleep(1 * time.Second)
	}
}

func InitComet(addrs map[int32]string, options CometOptions) (err error) {
	for serverID, addrsTmp := range addrs {
		var (
			c             *Comet
			rpcClient     *rpc.Client
			network, addr string
		)
		if network, addr, err = inet.ParseNetwork(addrsTmp); err != nil {
			log.Error("inet.ParseNetwork() error(%v)", err)
			return
		}
		if rpcClient, err = rpc.Dial(network, addr); err != nil {
			log.Error("rpc.Dial(\"%s\") error(%s)", addr, err)
		}
		// comet
		c = new(Comet)
		c.serverId = serverID
		c.pushRoutines = make([]chan *proto.MPushMsgArg, options.RoutineAmount)
		c.roomRoutines = make([]chan *proto.BoardcastRoomArg, options.RoutineAmount)
		c.broadcastRoutines = make([]chan *proto.BoardcastArg, options.RoutineAmount)
		c.options = options
		c.rpcClient = rpcClient
		cometServiceMap[serverID] = c
		// process
		for i := int64(0); i < options.RoutineAmount; i++ {
			pushChan := make(chan *proto.MPushMsgArg, options.RoutineSize)
			roomChan := make(chan *proto.BoardcastRoomArg, options.RoutineSize)
			broadcastChan := make(chan *proto.BoardcastArg, options.RoutineSize)
			c.pushRoutines[i] = pushChan
			c.roomRoutines[i] = roomChan
			c.broadcastRoutines[i] = broadcastChan
			go c.process(pushChan, roomChan, broadcastChan)
		}
		// ping & reconnect
		go c.ping(network, addr)
		log.Info("init comet rpc addr:%s connection", addr)
	}
	return
}

// mPushComet push a message to a batch of subkeys
func mPushComet(serverId int32, subKeys []string, body json.RawMessage) {
	var args = &proto.MPushMsgArg{
		Keys: subKeys, P: proto.Proto{Ver: 0, Operation: define.OP_SEND_SMS_REPLY, Body: body, Time: time.Now()},
	}
	if c, ok := cometServiceMap[serverId]; ok {
		if err := c.Push(args); err != nil {
			log.Error("c.Push(%v) serverId:%d error(%v)", args, serverId, err)
		}
	}
}

// broadcast broadcast a message to all
func broadcast(msg []byte) {
	var args = &proto.BoardcastArg{
		P: proto.Proto{Ver: 0, Operation: define.OP_SEND_SMS_REPLY, Body: msg, Time: time.Now()},
	}
	for serverId, c := range cometServiceMap {
		if err := c.Broadcast(args); err != nil {
			log.Error("c.Broadcast(%v) serverId:%d error(%v)", args, serverId, err)
		}
	}
}

// broadcastRoomBytes broadcast aggregation messages to room
func broadcastRoomBytes(roomId int32, body []byte) {
	var (
		args     = proto.BoardcastRoomArg{P: proto.Proto{Ver: 0, Operation: define.OP_RAW, Body: body, Time: time.Now()}, RoomId: roomId}
		c        *Comet
		serverId int32
		servers  map[int32]struct{}
		ok       bool
		err      error
	)
	if servers, ok = RoomServersMap[roomId]; ok {
		for serverId, _ = range servers {
			if c, ok = cometServiceMap[serverId]; ok {
				// push routines
				if err = c.BroadcastRoom(&args); err != nil {
					log.Error("c.BroadcastRoom(%v) roomId:%d error(%v)", args, roomId, err)
				}
			}
		}
	}
}

func roomsComet(c *rpc.Client) []int32 {
	var (
		args  = proto.NoArg{}
		reply = proto.RoomsReply{}
		err   error
	)
	if err = c.Call(CometServiceRooms, &args, &reply); err != nil {
		log.Error("c.Call(%s, 0, reply) error(%v)", CometServiceRooms, err)
		return nil
	}
	return reply.RoomIds
}
<|endoftext|>


<commit_before>package main

/*
#cgo LDFLAGS: -lnetsnmp -L/usr/local/lib
#cgo CFLAGS: -I/usr/local/include
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/mib_api.h>
#include <unistd.h>
*/
import "C"

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/prometheus/common/log"
)

// One entry in the tree of the MIB.
type Node struct {
	Oid               string
	Label             string
	Augments          string
	Children          []*Node
	Description       string
	Type              string
	Hint              string
	TextualConvention string
	Units             string
	Access            string

	Indexes []string
}

// Adapted from parse.h.
var (
	netSnmptypeMap = map[int]string{
		0:  "OTHER",
		1:  "OBJID",
		2:  "OCTETSTR",
		3:  "INTEGER",
		4:  "NETADDR",
		5:  "IPADDR",
		6:  "COUNTER",
		7:  "GAUGE",
		8:  "TIMETICKS",
		9:  "OPAQUE",
		10: "NULL",
		11: "COUNTER64",
		12: "BITSTRING",
		13: "NSAPADDRESS",
		14: "UINTEGER",
		15: "UNSIGNED32",
		16: "INTEGER32",
		20: "TRAPTYPE",
		21: "NOTIFTYPE",
		22: "OBJGROUP",
		23: "NOTIFGROUP",
		24: "MODID",
		25: "AGENTCAP",
		26: "MODCOMP",
		27: "OBJIDENTITY",
	}
	netSnmpaccessMap = map[int]string{
		18: "ACCESS_READONLY",
		19: "ACCESS_READWRITE",
		20: "ACCESS_WRITEONLY",
		21: "ACCESS_NOACCESS",
		67: "ACCESS_NOTIFY",
		48: "ACCESS_CREATE",
	}
)

// Initilise NetSNMP. Returns MIB parse errors.
//
// Warning: This function plays with the stderr file descriptor.
func initSNMP() string {
	// Load all the MIBs.
	// RFC1213-MIB is lacking type hints and has many common tables,
	// so prefer MIBs with hints.
	os.Setenv("MIBS", "SNMPv2-MIB:IF-MIB:IP-MIB:ALL")
	// Help the user find their MIB directories.
	log.Infof("Loading MIBs from %s", C.GoString(C.netsnmp_get_mib_directory()))
	// We want the descriptions.
	C.snmp_set_save_descriptions(1)

	// Make stderr go to a pipe, as netsnmp tends to spew a
	// lot of errors on startup that there's no apparent
	// way to disable or redirect.
	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("Error creating pipe: %s", err)
	}
	defer r.Close()
	defer w.Close()
	savedStderrFd := C.dup(2)
	C.close(2)
	C.dup2(C.int(w.Fd()), 2)
	ch := make(chan string)
	go func() {
		data, err := ioutil.ReadAll(r)
		if err != nil {
			log.Fatalf("Error reading from pipe: %s", err)
		}
		ch <- string(data)
	}()

	// Do the initilization.
	C.netsnmp_init_mib()

	// Restore stderr to normal.
	w.Close()
	C.close(2)
	C.dup2(savedStderrFd, 2)
	C.close(savedStderrFd)
	return <-ch
}

// Walk NetSNMP MIB tree, building a Go tree from it.
func buildMIBTree(t *C.struct_tree, n *Node, oid string) {
	if oid != "" {
		n.Oid = fmt.Sprintf("%s.%d", oid, t.subid)
	} else {
		n.Oid = fmt.Sprintf("%d", t.subid)
	}
	n.Label = C.GoString(t.label)
	if typ, ok := netSnmptypeMap[int(t._type)]; ok {
		n.Type = typ
	} else {
		n.Type = "unknown"
	}

	if access, ok := netSnmpaccessMap[int(t.access)]; ok {
		n.Access = access
	} else {
		n.Access = "unknown"
	}

	n.Augments = C.GoString(t.augments)
	n.Description = C.GoString(t.description)
	n.Hint = C.GoString(t.hint)
	n.TextualConvention = C.GoString(C.get_tc_descriptor(t.tc_index))
	n.Units = C.GoString(t.units)

	if t.child_list == nil {
		return
	}

	head := t.child_list
	n.Children = []*Node{}
	for head != nil {
		child := &Node{}
		// Prepend, as nodes are backwards.
		n.Children = append([]*Node{child}, n.Children...)
		buildMIBTree(head, child, n.Oid)
		head = head.next_peer
	}

	// Set names of indexes on each child.
	// In practice this means only the entry will have it.
	index := t.indexes
	indexes := []string{}
	for index != nil {
		indexes = append(indexes, C.GoString(index.ilabel))
		index = index.next
	}
	n.Indexes = indexes
}

// Convert the NetSNMP MIB tree to a Go data structure.
func getMIBTree() *Node {

	tree := C.get_tree_head()
	head := &Node{}
	buildMIBTree(tree, head, "")
	return head
}
<commit_msg>Remove special load order to workaround RFC1213<commit_after>package main

/*
#cgo LDFLAGS: -lnetsnmp -L/usr/local/lib
#cgo CFLAGS: -I/usr/local/include
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/mib_api.h>
#include <unistd.h>
*/
import "C"

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/prometheus/common/log"
)

// One entry in the tree of the MIB.
type Node struct {
	Oid               string
	Label             string
	Augments          string
	Children          []*Node
	Description       string
	Type              string
	Hint              string
	TextualConvention string
	Units             string
	Access            string

	Indexes []string
}

// Adapted from parse.h.
var (
	netSnmptypeMap = map[int]string{
		0:  "OTHER",
		1:  "OBJID",
		2:  "OCTETSTR",
		3:  "INTEGER",
		4:  "NETADDR",
		5:  "IPADDR",
		6:  "COUNTER",
		7:  "GAUGE",
		8:  "TIMETICKS",
		9:  "OPAQUE",
		10: "NULL",
		11: "COUNTER64",
		12: "BITSTRING",
		13: "NSAPADDRESS",
		14: "UINTEGER",
		15: "UNSIGNED32",
		16: "INTEGER32",
		20: "TRAPTYPE",
		21: "NOTIFTYPE",
		22: "OBJGROUP",
		23: "NOTIFGROUP",
		24: "MODID",
		25: "AGENTCAP",
		26: "MODCOMP",
		27: "OBJIDENTITY",
	}
	netSnmpaccessMap = map[int]string{
		18: "ACCESS_READONLY",
		19: "ACCESS_READWRITE",
		20: "ACCESS_WRITEONLY",
		21: "ACCESS_NOACCESS",
		67: "ACCESS_NOTIFY",
		48: "ACCESS_CREATE",
	}
)

// Initilise NetSNMP. Returns MIB parse errors.
//
// Warning: This function plays with the stderr file descriptor.
func initSNMP() string {
	// Load all the MIBs.
	os.Setenv("MIBS", "ALL")
	// Help the user find their MIB directories.
	log.Infof("Loading MIBs from %s", C.GoString(C.netsnmp_get_mib_directory()))
	// We want the descriptions.
	C.snmp_set_save_descriptions(1)

	// Make stderr go to a pipe, as netsnmp tends to spew a
	// lot of errors on startup that there's no apparent
	// way to disable or redirect.
	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("Error creating pipe: %s", err)
	}
	defer r.Close()
	defer w.Close()
	savedStderrFd := C.dup(2)
	C.close(2)
	C.dup2(C.int(w.Fd()), 2)
	ch := make(chan string)
	go func() {
		data, err := ioutil.ReadAll(r)
		if err != nil {
			log.Fatalf("Error reading from pipe: %s", err)
		}
		ch <- string(data)
	}()

	// Do the initilization.
	C.netsnmp_init_mib()

	// Restore stderr to normal.
	w.Close()
	C.close(2)
	C.dup2(savedStderrFd, 2)
	C.close(savedStderrFd)
	return <-ch
}

// Walk NetSNMP MIB tree, building a Go tree from it.
func buildMIBTree(t *C.struct_tree, n *Node, oid string) {
	if oid != "" {
		n.Oid = fmt.Sprintf("%s.%d", oid, t.subid)
	} else {
		n.Oid = fmt.Sprintf("%d", t.subid)
	}
	n.Label = C.GoString(t.label)
	if typ, ok := netSnmptypeMap[int(t._type)]; ok {
		n.Type = typ
	} else {
		n.Type = "unknown"
	}

	if access, ok := netSnmpaccessMap[int(t.access)]; ok {
		n.Access = access
	} else {
		n.Access = "unknown"
	}

	n.Augments = C.GoString(t.augments)
	n.Description = C.GoString(t.description)
	n.Hint = C.GoString(t.hint)
	n.TextualConvention = C.GoString(C.get_tc_descriptor(t.tc_index))
	n.Units = C.GoString(t.units)

	if t.child_list == nil {
		return
	}

	head := t.child_list
	n.Children = []*Node{}
	for head != nil {
		child := &Node{}
		// Prepend, as nodes are backwards.
		n.Children = append([]*Node{child}, n.Children...)
		buildMIBTree(head, child, n.Oid)
		head = head.next_peer
	}

	// Set names of indexes on each child.
	// In practice this means only the entry will have it.
	index := t.indexes
	indexes := []string{}
	for index != nil {
		indexes = append(indexes, C.GoString(index.ilabel))
		index = index.next
	}
	n.Indexes = indexes
}

// Convert the NetSNMP MIB tree to a Go data structure.
func getMIBTree() *Node {

	tree := C.get_tree_head()
	head := &Node{}
	buildMIBTree(tree, head, "")
	return head
}
<|endoftext|>