<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/big"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/common"
	"github.com/gorilla/mux"
)

var currWork *ResponseArray = nil

var pendingBlockNumber uint64 = 0
var pendingBlockDifficulty *big.Int

var invalidRequest = `{
  "id":64,
  "jsonrpc": "2.0",
  "result": false,
  "error": "invalid request"
}`

var okRequest = `{
  "id":64,
  "jsonrpc": "2.0",
  "result": true
}`

var pow256 = common.BigPow(2, 256)

var hasher = ethash.New()

var secret = "CHANGETHIS"
var poolPort = "5082"
var ethereumPort = "8545" //8545 = geth, 8080 = eth (requires dev branch when using eth client)

var logInfo *log.Logger
var logError *log.Logger

type ResponseArray struct {
	Id      int           `json:"id"`
	Jsonrpc string        `json:"jsonrpc"`
	Result  []interface{} `json:"result"`
}

type ResponseJSON struct {
	Id      int                    `json:"id"`
	Jsonrpc string                 `json:"jsonrpc"`
	Result  map[string]interface{} `json:"result"`
}

type ResponseBool struct {
	Id      int    `json:"id"`
	Jsonrpc string `json:"jsonrpc"`
	Result  bool   `json:"result"`
}

type Request struct {
	Id      int           `json:"id"`
	Jsonrpc string        `json:"jsonrpc"`
	Method  string        `json:"method"`
	Params  []interface{} `json:"params"`
}

type block struct {
	difficulty  *big.Int
	hashNoNonce common.Hash
	nonce       uint64
	mixDigest   common.Hash
	number      uint64
}

func (b block) Difficulty() *big.Int     { return b.difficulty }
func (b block) HashNoNonce() common.Hash { return b.hashNoNonce }
func (b block) Nonce() uint64            { return b.nonce }
func (b block) MixDigest() common.Hash   { return b.mixDigest }
func (b block) NumberU64() uint64        { return b.number }

func main() {
	// Set up logging
	logInfo = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime)
	logError = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime)
	logInfo.Println("Welcome to ethpool 2.0")
	logInfo.Println("Pool port is", poolPort)
	logInfo.Println("Point your miners to: http://<ip>:" + poolPort + "/miner/{miner}/{difficulty}")

	go updateWork()
	go updatePendingBlock()
	go submitShares()
	// names := []interface{}{"pending", false}

	// pb := callJSON("eth_getBlockByNumber", names)
	// fmt.Println(pb.Result["number"])

	// fmt.Scanln()
	r := mux.NewRouter()
	r.HandleFunc("/miner/{miner}/{difficulty}", handleMiner)
	http.Handle("/", r)
	log.Fatal(http.ListenAndServe(":5082", nil))
}

func handleMiner(rw http.ResponseWriter, req *http.Request) {

	vars := mux.Vars(req)

	minerDifficulty, err := strconv.ParseFloat(vars["difficulty"], 64)
	if err != nil {
		logError.Println("Invalid difficulty provided: " + vars["difficulty"])
		minerDifficulty = 5 // Set a fixed difficulty (5MH/s) in this case
		// fmt.Fprint(rw, getErrorResponse("Invalid difficulty provided: "+vars["difficulty"]))
		// return
	}
	minerAdjustedDifficulty := int64(minerDifficulty * 1000000 * 100)

	minerArray := strings.Split(vars["miner"], ".")

	if len(minerArray) == 0 || len(minerArray) > 2 {
		logError.Println("Invalid miner & worker provided: " + vars["miner"])
		fmt.Fprint(rw, getErrorResponse("Invalid miner & worker provided: "+vars["miner"]))
		return
	}

	miner := strings.Replace(minerArray[0], "0x", "", -1)
	worker := "default"

	if len(minerArray) == 2 {
		worker = minerArray[1]
	}

	if len(miner) != 40 {
		logError.Println("Invalid ethereum address provided: 0x" + miner)
		fmt.Fprint(rw, getErrorResponse("Invalid ethereum address provided: 0x"+miner))
		return
	}

	decoder := json.NewDecoder(req.Body)
	var t Request
	err = decoder.Decode(&t)
	if err != nil {
		logError.Println("Invalid JSON request: ", err)
		fmt.Fprint(rw, getErrorResponse("Invalid JSON request"))
		return
	}

	if t.Method == "eth_getWork" {
		difficulty := big.NewInt(minerAdjustedDifficulty)
		// Send the response
		fmt.Fprint(rw, getWorkPackage(difficulty))
	} else if t.Method == "eth_submitHashrate" {
		fmt.Fprint(rw, okRequest)
	} else if t.Method == "eth_submitWork" {
		paramsOrig := t.Params[:]

		hashNoNonce := t.Params[1].(string)
		nonce, err := strconv.ParseUint(strings.Replace(t.Params[0].(string), "0x", "", -1), 16, 64)
		if err != nil {
			logError.Println("Invalid nonce provided: ", err)
			fmt.Fprint(rw, getErrorResponse("Invalid nonce provided"))
			return
		}

		mixDigest := t.Params[2].(string)

		myBlock := block{
			number:      pendingBlockNumber,
			hashNoNonce: common.HexToHash(hashNoNonce),
			difficulty:  big.NewInt(minerAdjustedDifficulty),
			nonce:       nonce,
			mixDigest:   common.HexToHash(mixDigest),
		}

		myBlockRealDiff := block{
			number:      pendingBlockNumber,
			hashNoNonce: common.HexToHash(hashNoNonce),
			difficulty:  pendingBlockDifficulty,
			nonce:       nonce,
			mixDigest:   common.HexToHash(mixDigest),
		}

		if hasher.Verify(myBlock) {
			//fmt.Println("Share is valid")
			if hasher.Verify(myBlockRealDiff) {
				submitWork(paramsOrig)
				logInfo.Println("###########################################################################")
				logInfo.Println("################################Block found################################")
				logInfo.Println("###########################################################################")
				http.PostForm("http://192.168.10.244:5000/foundblock", url.Values{})
			}

			logInfo.Println("Miner", miner, ".", worker, "found valid share (Diff:", minerAdjustedDifficulty, "Mix:", mixDigest, "Hash:", hashNoNonce, "Nonce:", nonce, ")")
			http.PostForm("http://192.168.10.244:5000/submit", url.Values{"secret": {secret}, "mixdigest": {mixDigest}, "miner": {miner}, "diff": {strconv.FormatInt(minerAdjustedDifficulty, 10)}, "worker": {worker}})
		} else {
			logError.Println("Miner", miner, "provided invalid share")
			fmt.Fprint(rw, getErrorResponse("Provided PoW solution is invalid!"))
		}
		fmt.Fprint(rw, okRequest)
	} else {
		logError.Println("Method " + t.Method + " not implemented!")
		fmt.Fprint(rw, getErrorResponse("Method "+t.Method+" not implemented!"))
	}
}

func getWorkPackage(difficulty *big.Int) string {

	if currWork == nil {
		return getErrorResponse("Current work unavailable")
	}

	// Our response object
	response := &ResponseArray{
		Id:      currWork.Id,
		Jsonrpc: currWork.Jsonrpc,
		Result:  currWork.Result[:],
	}

	// Calculte requested difficulty
	diff := new(big.Int).Div(pow256, difficulty)
	diffBytes := string(common.ToHex(diff.Bytes()))

	// Adjust the difficulty for the miner
	response.Result[2] = diffBytes

	// Convert respone object to JSON
	b, _ := json.Marshal(response)

	return string(b)

}

func updateWork() {
	for true {
		currWorkNew, err := callArray("eth_getWork", []interface{}{})

		if err == nil {
			currWork = currWorkNew
		} else {
			currWork = nil
		}

		// fmt.Println("Current work", currWork.Result[0])
		time.Sleep(time.Millisecond * 100)
	}
}

func submitWork(params []interface{}) {
	result, err := callBool("eth_submitWork", params)
	if err == nil {
		logInfo.Println(result.Result)
	}
}

func submitShares() {
	for true {
		/*iter := levelDB.NewIterator(nil, nil)
		for iter.Next() {
			key := iter.Key()
			value := iter.Value()
			_ = value
			logInfo.Println("Do smth with the share (e.g. send to pool database):", string(key))
		}
		iter.Release()
		err := iter.Error()
		if err != nil {
			logError.Println("Error itarating shares:", err)
		}*/
		time.Sleep(time.Second * 10)
	}
}

func updatePendingBlock() {
	params := []interface{}{"pending", false}

	for true {
		block, err := callJSON("eth_getBlockByNumber", params)
		if err == nil {
			blockNbr, err := strconv.ParseUint(strings.Replace(block.Result["number"].(string), "0x", "", -1), 16, 64)
			if err == nil {
				pendingBlockNumber = blockNbr
			}

			blockDiff, err := strconv.ParseInt(strings.Replace(block.Result["difficulty"].(string), "0x", "", -1), 16, 64)
			if err == nil {
				pendingBlockDifficulty = big.NewInt(blockDiff)
				// logInfo.Println("Pending block difficulty:", pendingBlockDifficulty)
			}
		}
		time.Sleep(time.Millisecond * 100)
	}
}

func callArray(method string, params []interface{}) (*ResponseArray, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseArray{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func callBool(method string, params []interface{}) (*ResponseBool, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseBool{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func callJSON(method string, params []interface{}) (*ResponseJSON, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseJSON{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func getErrorResponse(errorMsg string) string {
	return `{
    "id":64,
    "jsonrpc": "2.0",
    "result": false,
    "error": "` + errorMsg + `"
  }`
}
<commit_msg>Update pool.go<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/big"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/common"
	"github.com/gorilla/mux"
)

var currWork *ResponseArray = nil

var pendingBlockNumber uint64 = 0
var pendingBlockDifficulty *big.Int

var invalidRequest = `{
  "id":64,
  "jsonrpc": "2.0",
  "result": false,
  "error": "invalid request"
}`

var okRequest = `{
  "id":64,
  "jsonrpc": "2.0",
  "result": true
}`

var pow256 = common.BigPow(2, 256)

var hasher = ethash.New()

var secret = "CHANGETHIS"
var poolPort = "5082"
var ethereumPort = "8545" //8545 = geth, 8080 = eth (requires dev branch when using eth client)

var logInfo *log.Logger
var logError *log.Logger

type ResponseArray struct {
	Id      int           `json:"id"`
	Jsonrpc string        `json:"jsonrpc"`
	Result  []interface{} `json:"result"`
}

type ResponseJSON struct {
	Id      int                    `json:"id"`
	Jsonrpc string                 `json:"jsonrpc"`
	Result  map[string]interface{} `json:"result"`
}

type ResponseBool struct {
	Id      int    `json:"id"`
	Jsonrpc string `json:"jsonrpc"`
	Result  bool   `json:"result"`
}

type Request struct {
	Id      int           `json:"id"`
	Jsonrpc string        `json:"jsonrpc"`
	Method  string        `json:"method"`
	Params  []interface{} `json:"params"`
}

type block struct {
	difficulty  *big.Int
	hashNoNonce common.Hash
	nonce       uint64
	mixDigest   common.Hash
	number      uint64
}

func (b block) Difficulty() *big.Int     { return b.difficulty }
func (b block) HashNoNonce() common.Hash { return b.hashNoNonce }
func (b block) Nonce() uint64            { return b.nonce }
func (b block) MixDigest() common.Hash   { return b.mixDigest }
func (b block) NumberU64() uint64        { return b.number }

func main() {
	// Set up logging
	logInfo = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime)
	logError = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime)
	logInfo.Println("Welcome to ethpool 1.0")
	logInfo.Println("Pool port is", poolPort)
	logInfo.Println("Point your miners to: http://<ip>:" + poolPort + "/miner/{miner}/{difficulty}")

	go updateWork()
	go updatePendingBlock()
	go submitShares()
	// names := []interface{}{"pending", false}

	// pb := callJSON("eth_getBlockByNumber", names)
	// fmt.Println(pb.Result["number"])

	// fmt.Scanln()
	r := mux.NewRouter()
	r.HandleFunc("/miner/{miner}/{difficulty}", handleMiner)
	http.Handle("/", r)
	log.Fatal(http.ListenAndServe(":5082", nil))
}

func handleMiner(rw http.ResponseWriter, req *http.Request) {

	vars := mux.Vars(req)

	minerDifficulty, err := strconv.ParseFloat(vars["difficulty"], 64)
	if err != nil {
		logError.Println("Invalid difficulty provided: " + vars["difficulty"])
		minerDifficulty = 5 // Set a fixed difficulty (5MH/s) in this case
		// fmt.Fprint(rw, getErrorResponse("Invalid difficulty provided: "+vars["difficulty"]))
		// return
	}
	minerAdjustedDifficulty := int64(minerDifficulty * 1000000 * 100)

	minerArray := strings.Split(vars["miner"], ".")

	if len(minerArray) == 0 || len(minerArray) > 2 {
		logError.Println("Invalid miner & worker provided: " + vars["miner"])
		fmt.Fprint(rw, getErrorResponse("Invalid miner & worker provided: "+vars["miner"]))
		return
	}

	miner := strings.Replace(minerArray[0], "0x", "", -1)
	worker := "default"

	if len(minerArray) == 2 {
		worker = minerArray[1]
	}

	if len(miner) != 40 {
		logError.Println("Invalid ethereum address provided: 0x" + miner)
		fmt.Fprint(rw, getErrorResponse("Invalid ethereum address provided: 0x"+miner))
		return
	}

	decoder := json.NewDecoder(req.Body)
	var t Request
	err = decoder.Decode(&t)
	if err != nil {
		logError.Println("Invalid JSON request: ", err)
		fmt.Fprint(rw, getErrorResponse("Invalid JSON request"))
		return
	}

	if t.Method == "eth_getWork" {
		difficulty := big.NewInt(minerAdjustedDifficulty)
		// Send the response
		fmt.Fprint(rw, getWorkPackage(difficulty))
	} else if t.Method == "eth_submitHashrate" {
		fmt.Fprint(rw, okRequest)
	} else if t.Method == "eth_submitWork" {
		paramsOrig := t.Params[:]

		hashNoNonce := t.Params[1].(string)
		nonce, err := strconv.ParseUint(strings.Replace(t.Params[0].(string), "0x", "", -1), 16, 64)
		if err != nil {
			logError.Println("Invalid nonce provided: ", err)
			fmt.Fprint(rw, getErrorResponse("Invalid nonce provided"))
			return
		}

		mixDigest := t.Params[2].(string)

		myBlock := block{
			number:      pendingBlockNumber,
			hashNoNonce: common.HexToHash(hashNoNonce),
			difficulty:  big.NewInt(minerAdjustedDifficulty),
			nonce:       nonce,
			mixDigest:   common.HexToHash(mixDigest),
		}

		myBlockRealDiff := block{
			number:      pendingBlockNumber,
			hashNoNonce: common.HexToHash(hashNoNonce),
			difficulty:  pendingBlockDifficulty,
			nonce:       nonce,
			mixDigest:   common.HexToHash(mixDigest),
		}

		if hasher.Verify(myBlock) {
			//fmt.Println("Share is valid")
			if hasher.Verify(myBlockRealDiff) {
				submitWork(paramsOrig)
				logInfo.Println("###########################################################################")
				logInfo.Println("################################Block found################################")
				logInfo.Println("###########################################################################")
				http.PostForm("http://192.168.10.244:5000/foundblock", url.Values{})
			}

			logInfo.Println("Miner", miner, ".", worker, "found valid share (Diff:", minerAdjustedDifficulty, "Mix:", mixDigest, "Hash:", hashNoNonce, "Nonce:", nonce, ")")
			http.PostForm("http://192.168.10.244:5000/submit", url.Values{"secret": {secret}, "mixdigest": {mixDigest}, "miner": {miner}, "diff": {strconv.FormatInt(minerAdjustedDifficulty, 10)}, "worker": {worker}})
		} else {
			logError.Println("Miner", miner, "provided invalid share")
			fmt.Fprint(rw, getErrorResponse("Provided PoW solution is invalid!"))
		}
		fmt.Fprint(rw, okRequest)
	} else {
		logError.Println("Method " + t.Method + " not implemented!")
		fmt.Fprint(rw, getErrorResponse("Method "+t.Method+" not implemented!"))
	}
}

func getWorkPackage(difficulty *big.Int) string {

	if currWork == nil {
		return getErrorResponse("Current work unavailable")
	}

	// Our response object
	response := &ResponseArray{
		Id:      currWork.Id,
		Jsonrpc: currWork.Jsonrpc,
		Result:  currWork.Result[:],
	}

	// Calculte requested difficulty
	diff := new(big.Int).Div(pow256, difficulty)
	diffBytes := string(common.ToHex(diff.Bytes()))

	// Adjust the difficulty for the miner
	response.Result[2] = diffBytes

	// Convert respone object to JSON
	b, _ := json.Marshal(response)

	return string(b)

}

func updateWork() {
	for true {
		currWorkNew, err := callArray("eth_getWork", []interface{}{})

		if err == nil {
			currWork = currWorkNew
		} else {
			currWork = nil
		}

		// fmt.Println("Current work", currWork.Result[0])
		time.Sleep(time.Millisecond * 100)
	}
}

func submitWork(params []interface{}) {
	result, err := callBool("eth_submitWork", params)
	if err == nil {
		logInfo.Println(result.Result)
	}
}

func submitShares() {
	for true {
		/*iter := levelDB.NewIterator(nil, nil)
		for iter.Next() {
			key := iter.Key()
			value := iter.Value()
			_ = value
			logInfo.Println("Do smth with the share (e.g. send to pool database):", string(key))
		}
		iter.Release()
		err := iter.Error()
		if err != nil {
			logError.Println("Error itarating shares:", err)
		}*/
		time.Sleep(time.Second * 10)
	}
}

func updatePendingBlock() {
	params := []interface{}{"pending", false}

	for true {
		block, err := callJSON("eth_getBlockByNumber", params)
		if err == nil {
			blockNbr, err := strconv.ParseUint(strings.Replace(block.Result["number"].(string), "0x", "", -1), 16, 64)
			if err == nil {
				pendingBlockNumber = blockNbr
			}

			blockDiff, err := strconv.ParseInt(strings.Replace(block.Result["difficulty"].(string), "0x", "", -1), 16, 64)
			if err == nil {
				pendingBlockDifficulty = big.NewInt(blockDiff)
				// logInfo.Println("Pending block difficulty:", pendingBlockDifficulty)
			}
		}
		time.Sleep(time.Millisecond * 100)
	}
}

func callArray(method string, params []interface{}) (*ResponseArray, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseArray{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func callBool(method string, params []interface{}) (*ResponseBool, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseBool{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func callJSON(method string, params []interface{}) (*ResponseJSON, error) {
	url := "http://192.168.10.244:" + ethereumPort
	jsonReq := &Request{
		Id:      1,
		Jsonrpc: "2.0",
		Method:  method,
		Params:  params,
	}
	reqJSON, _ := json.Marshal(jsonReq)
	// fmt.Println(string(reqJSON))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqJSON))

	if err != nil {
		logError.Println("Could not create POST request", err)
		return nil, errors.New("Could not create POST request")
	}

	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logError.Println("Could not send POST request to Ethereum client", err)
		return nil, errors.New("Could not send POST request to Ethereum client")
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	// fmt.Println(string(body))
	res := &ResponseJSON{}

	if err := json.Unmarshal(body, res); err != nil {
		logError.Println("Ethereum client returned unexpected data", err)
		return nil, errors.New("Ethereum client returned unexpected data")
	}

	// fmt.Println("done")
	return res, nil
}

func getErrorResponse(errorMsg string) string {
	return `{
    "id":64,
    "jsonrpc": "2.0",
    "result": false,
    "error": "` + errorMsg + `"
  }`
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Opsidian Ltd.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package text

import (
	"fmt"
	"io"
	"io/ioutil"
	"regexp"
	"unicode/utf8"

	"github.com/opsidian/parsley/reader"
)

// Position represents a token position. It also contains the line and column indexes.
type Position struct {
	filename string
	pos      int
	line     int
	col      int
}

// NewPosition creates a new position instance
func NewPosition(pos int, line int, col int) Position {
	return Position{"", pos, line, col}
}

// NewFilePosition creates a new position instance with a filename
func NewFilePosition(filename string, pos int, line int, col int) Position {
	return Position{filename, pos, line, col}
}

// Filename returns with the file name if any
func (p Position) Filename() string {
	return p.filename
}

// Pos returns with the byte position
func (p Position) Pos() int {
	return p.pos
}

// Line returns with the line position
func (p Position) Line() int {
	return p.line
}

// Col returns with the column position
func (p Position) Col() int {
	return p.col
}

func (p Position) String() string {
	if p.filename == "" {
		return fmt.Sprintf("%d:%d", p.line, p.col)
	}
	return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
}

// Reader defines a text input reader
// For more efficient reading it provides methods for regexp matching.
type Reader struct {
	b                 []byte
	cur               Position
	charCount         int
	ignoreWhitespaces bool
	regexpCache       map[string]*regexp.Regexp
}

// NewReader creates a new reader instance
func NewReader(b []byte, ignoreWhitespaces bool) *Reader {
	return &Reader{
		b:                 b,
		cur:               NewPosition(0, 1, 1),
		charCount:         utf8.RuneCount(b),
		ignoreWhitespaces: ignoreWhitespaces,
		regexpCache:       make(map[string]*regexp.Regexp),
	}
}

// NewFileReader creates a new reader instance which reads from a file
func NewFileReader(filename string, ignoreWhitespaces bool) (*Reader, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Reader{
		b:                 b,
		cur:               NewFilePosition(filename, 0, 1, 1),
		charCount:         utf8.RuneCount(b),
		ignoreWhitespaces: ignoreWhitespaces,
		regexpCache:       make(map[string]*regexp.Regexp),
	}, nil
}

// Clone creates a new reader with the same position
func (r *Reader) Clone() reader.Reader {
	return &Reader{
		b:                 r.b,
		cur:               r.cur,
		charCount:         r.charCount,
		ignoreWhitespaces: r.ignoreWhitespaces,
		regexpCache:       r.regexpCache,
	}
}

// ReadRune reads the next character
func (r *Reader) ReadRune() (ch rune, size int, err error) {
	if r.cur.pos >= len(r.b) {
		return 0, 0, io.EOF
	}
	if c := r.b[r.cur.pos]; c < utf8.RuneSelf {
		ch = rune(c)
		size = 1
	} else {
		ch, size = utf8.DecodeRune(r.b[r.cur.pos:])
		if ch == utf8.RuneError {
			return 0, 0, fmt.Errorf("invalid UTF-8 byte sequence encountered at %s", r.cur)
		}
	}
	r.cur.pos += size
	r.charCount--
	if ch != '\n' {
		r.cur.col++
	} else {
		r.cur.line++
		r.cur.col = 1
	}
	return
}

// PeakRune reads the next character but does not move the cursor
func (r *Reader) PeakRune() (ch rune, size int, err error) {
	if r.cur.pos >= len(r.b) {
		return 0, 0, io.EOF
	}
	if c := r.b[r.cur.pos]; c < utf8.RuneSelf {
		ch = rune(c)
		size = 1
	} else {
		ch, size = utf8.DecodeRune(r.b[r.cur.pos:])
		if ch == utf8.RuneError {
			return 0, 0, fmt.Errorf("invalid UTF-8 byte sequence encountered at %s", r.cur)
		}
	}
	return
}

// ReadMatch reads a set of characters matching the given regular expression
func (r *Reader) ReadMatch(expr string, includeWhitespaces bool) ([]string, reader.Position, bool) {
	cur := r.cur
	if r.ignoreWhitespaces && !includeWhitespaces {
		r.readWhitespaces()
	}

	loc := r.getPattern(expr).FindSubmatchIndex(r.b[r.cur.pos:])
	if loc == nil {
		r.cur = cur
		return nil, nil, false
	}
	pos := r.cur
	matches := make([]string, len(loc)/2)
	for i := 0; i < len(loc)/2; i++ {
		matches[i] = string(r.b[r.cur.pos+loc[i*2] : r.cur.pos+loc[i*2+1]])
	}

	r.cur.pos += loc[1]
	for _, ch := range matches[0] {
		r.charCount--
		if ch != '\n' {
			r.cur.col++
		} else {
			r.cur.line++
			r.cur.col = 1
		}
	}

	return matches, pos, true
}

// PeakMatch reads a set of characters matching the given regular expression but doesn't move the cursor
// Also it never ignores whitespaces
func (r *Reader) PeakMatch(expr string) ([]string, bool) {
	pos := r.cur.pos

	loc := r.getPattern(expr).FindSubmatchIndex(r.b[pos:])
	if loc == nil {
		return nil, false
	}

	matches := make([]string, len(loc)/2)
	for i := 0; i < len(loc)/2; i++ {
		matches[i] = string(r.b[pos+loc[i*2] : pos+loc[i*2+1]])
	}

	return matches, true
}

// Readf uses the given function to match the next token
func (r *Reader) Readf(f func(b []byte) (string, int, bool), includeWhitespaces bool) (string, reader.Position, bool) {
	if r.ignoreWhitespaces && !includeWhitespaces {
		r.readWhitespaces()
	}

	pos := r.cur
	value, l, ok := f(r.b[r.cur.pos:])
	if !ok {
		return "", nil, false
	}
	if l != 0 {
		str := string(r.b[r.cur.pos : r.cur.pos+l])
		for _, ch := range str {
			r.charCount--
			if ch != '\n' {
				r.cur.col++
			} else {
				r.cur.line++
				r.cur.col = 1
			}
		}
		r.cur.pos += l
	}
	return value, pos, true
}

// Remaining returns with the remaining character count
func (r *Reader) Remaining() int {
	return r.charCount
}

// Cursor returns with the cursor's position
func (r *Reader) Cursor() reader.Position {
	return r.cur
}

// IsEOF returns true if we reached the end of the buffer
func (r *Reader) IsEOF() bool {
	if r.ignoreWhitespaces {
		r.readWhitespaces()
	}
	return r.cur.pos >= len(r.b)
}

func (r *Reader) String() string {
	return fmt.Sprintf("R{%s}", r.cur)
}

func (r *Reader) readWhitespaces() {
	loc := r.getPattern("[ \n\r\t]+").FindIndex(r.b[r.cur.pos:])
	if loc == nil {
		return
	}

	for _, ch := range r.b[r.cur.pos : r.cur.pos+loc[1]] {
		r.charCount--
		if ch != '\n' {
			r.cur.col++
		} else {
			r.cur.line++
			r.cur.col = 1
		}
	}
	r.cur.pos += loc[1]
}

func (r *Reader) getPattern(expr string) (rc *regexp.Regexp) {
	rc, ok := r.regexpCache[expr]
	if !ok {
		rc = regexp.MustCompile("^(?:" + expr + ")")
		r.regexpCache[expr] = rc
	}
	return
}
<commit_msg>Move precompiled whitespace regexp to a separate variable in text reader<commit_after>// Copyright (c) 2017 Opsidian Ltd.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package text

import (
	"fmt"
	"io"
	"io/ioutil"
	"regexp"
	"unicode/utf8"

	"github.com/opsidian/parsley/reader"
)

var whitespaceRegExp = regexp.MustCompile("^[ \n\r\t]+")

// Position represents a token position. It also contains the line and column indexes.
type Position struct {
	filename string
	pos      int
	line     int
	col      int
}

// NewPosition creates a new position instance
func NewPosition(pos int, line int, col int) Position {
	return Position{"", pos, line, col}
}

// NewFilePosition creates a new position instance with a filename
func NewFilePosition(filename string, pos int, line int, col int) Position {
	return Position{filename, pos, line, col}
}

// Filename returns with the file name if any
func (p Position) Filename() string {
	return p.filename
}

// Pos returns with the byte position
func (p Position) Pos() int {
	return p.pos
}

// Line returns with the line position
func (p Position) Line() int {
	return p.line
}

// Col returns with the column position
func (p Position) Col() int {
	return p.col
}

func (p Position) String() string {
	if p.filename == "" {
		return fmt.Sprintf("%d:%d", p.line, p.col)
	}
	return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
}

// Reader defines a text input reader
// For more efficient reading it provides methods for regexp matching.
type Reader struct {
	b                 []byte
	cur               Position
	charCount         int
	ignoreWhitespaces bool
	regexpCache       map[string]*regexp.Regexp
}

// NewReader creates a new reader instance
func NewReader(b []byte, ignoreWhitespaces bool) *Reader {
	return &Reader{
		b:                 b,
		cur:               NewPosition(0, 1, 1),
		charCount:         utf8.RuneCount(b),
		ignoreWhitespaces: ignoreWhitespaces,
		regexpCache:       make(map[string]*regexp.Regexp),
	}
}

// NewFileReader creates a new reader instance which reads from a file
func NewFileReader(filename string, ignoreWhitespaces bool) (*Reader, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Reader{
		b:                 b,
		cur:               NewFilePosition(filename, 0, 1, 1),
		charCount:         utf8.RuneCount(b),
		ignoreWhitespaces: ignoreWhitespaces,
		regexpCache:       make(map[string]*regexp.Regexp),
	}, nil
}

// Clone creates a new reader with the same position
func (r *Reader) Clone() reader.Reader {
	return &Reader{
		b:                 r.b,
		cur:               r.cur,
		charCount:         r.charCount,
		ignoreWhitespaces: r.ignoreWhitespaces,
		regexpCache:       r.regexpCache,
	}
}

// ReadRune reads the next character
func (r *Reader) ReadRune() (ch rune, size int, err error) {
	if r.cur.pos >= len(r.b) {
		return 0, 0, io.EOF
	}
	if c := r.b[r.cur.pos]; c < utf8.RuneSelf {
		ch = rune(c)
		size = 1
	} else {
		ch, size = utf8.DecodeRune(r.b[r.cur.pos:])
		if ch == utf8.RuneError {
			return 0, 0, fmt.Errorf("invalid UTF-8 byte sequence encountered at %s", r.cur)
		}
	}
	r.cur.pos += size
	r.charCount--
	if ch != '\n' {
		r.cur.col++
	} else {
		r.cur.line++
		r.cur.col = 1
	}
	return
}

// PeakRune reads the next character but does not move the cursor
func (r *Reader) PeakRune() (ch rune, size int, err error) {
	if r.cur.pos >= len(r.b) {
		return 0, 0, io.EOF
	}
	if c := r.b[r.cur.pos]; c < utf8.RuneSelf {
		ch = rune(c)
		size = 1
	} else {
		ch, size = utf8.DecodeRune(r.b[r.cur.pos:])
		if ch == utf8.RuneError {
			return 0, 0, fmt.Errorf("invalid UTF-8 byte sequence encountered at %s", r.cur)
		}
	}
	return
}

// ReadMatch reads a set of characters matching the given regular expression
func (r *Reader) ReadMatch(expr string, includeWhitespaces bool) ([]string, reader.Position, bool) {
	cur := r.cur
	if r.ignoreWhitespaces && !includeWhitespaces {
		r.readWhitespaces()
	}

	loc := r.getPattern(expr).FindSubmatchIndex(r.b[r.cur.pos:])
	if loc == nil {
		r.cur = cur
		return nil, nil, false
	}
	pos := r.cur
	matches := make([]string, len(loc)/2)
	for i := 0; i < len(loc)/2; i++ {
		matches[i] = string(r.b[r.cur.pos+loc[i*2] : r.cur.pos+loc[i*2+1]])
	}

	r.cur.pos += loc[1]
	for _, ch := range matches[0] {
		r.charCount--
		if ch != '\n' {
			r.cur.col++
		} else {
			r.cur.line++
			r.cur.col = 1
		}
	}

	return matches, pos, true
}

// PeakMatch reads a set of characters matching the given regular expression but doesn't move the cursor
// Also it never ignores whitespaces
func (r *Reader) PeakMatch(expr string) ([]string, bool) {
	pos := r.cur.pos

	loc := r.getPattern(expr).FindSubmatchIndex(r.b[pos:])
	if loc == nil {
		return nil, false
	}

	matches := make([]string, len(loc)/2)
	for i := 0; i < len(loc)/2; i++ {
		matches[i] = string(r.b[pos+loc[i*2] : pos+loc[i*2+1]])
	}

	return matches, true
}

// Readf uses the given function to match the next token
func (r *Reader) Readf(f func(b []byte) (string, int, bool), includeWhitespaces bool) (string, reader.Position, bool) {
	if r.ignoreWhitespaces && !includeWhitespaces {
		r.readWhitespaces()
	}

	pos := r.cur
	value, l, ok := f(r.b[r.cur.pos:])
	if !ok {
		return "", nil, false
	}
	if l != 0 {
		str := string(r.b[r.cur.pos : r.cur.pos+l])
		for _, ch := range str {
			r.charCount--
			if ch != '\n' {
				r.cur.col++
			} else {
				r.cur.line++
				r.cur.col = 1
			}
		}
		r.cur.pos += l
	}
	return value, pos, true
}

// Remaining returns with the remaining character count
func (r *Reader) Remaining() int {
	return r.charCount
}

// Cursor returns with the cursor's position
func (r *Reader) Cursor() reader.Position {
	return r.cur
}

// IsEOF returns true if we reached the end of the buffer
func (r *Reader) IsEOF() bool {
	if r.ignoreWhitespaces {
		r.readWhitespaces()
	}
	return r.cur.pos >= len(r.b)
}

func (r *Reader) String() string {
	return fmt.Sprintf("R{%s}", r.cur)
}

func (r *Reader) readWhitespaces() {
	loc := whitespaceRegExp.FindIndex(r.b[r.cur.pos:])
	if loc == nil {
		return
	}

	for _, ch := range r.b[r.cur.pos : r.cur.pos+loc[1]] {
		r.charCount--
		if ch != '\n' {
			r.cur.col++
		} else {
			r.cur.line++
			r.cur.col = 1
		}
	}
	r.cur.pos += loc[1]
}

func (r *Reader) getPattern(expr string) *regexp.Regexp {
	rc, ok := r.regexpCache[expr]
	if !ok {
		rc = regexp.MustCompile("^(?:" + expr + ")")
		r.regexpCache[expr] = rc
	}
	return rc
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/urfave/cli"
)

func main() {

	app := cli.NewApp()
	app.Name = "zippy"
	app.Author = "Tugberk Ugurlu"
	app.Usage = "General purpose package distribution tool for your stuff (yes, all your stuff™)"

	app.Commands = []cli.Command{
		cli.Command{
			Name:  "install",
			Usage: "Downloads the specified package and outputs it onto the specified directory",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "version, v",
					Usage: "Version of the package to be installed",
				},

				cli.StringFlag{
					Name:  "outputFolder, o",
					Usage: "Path to the output folder for the package to be installed",
					Value: "./", // os.Getwd()
				},

				cli.StringFlag{
					Name:  "source, s",
					Usage: "Base URL for the desired zippy endpoint to be looked at for this install operation",
				},
			},
		},
	}

	app.Action = func(c *cli.Context) error {
		fmt.Print("hello and byee!\n")
		return cli.NewExitError("no pun intended", -1)
	}

	app.Run(os.Args)
}
<commit_msg>added push command<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/urfave/cli"
)

func main() {

	app := cli.NewApp()
	app.Name = "zippy"
	app.Author = "Tugberk Ugurlu"
	app.Usage = "General purpose package distribution tool for your stuff (yes, all your stuff™)"

	app.Commands = []cli.Command{
		cli.Command{
			Name:  "install",
			Usage: "Downloads the specified package and outputs it onto the specified directory",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "version, v",
					Usage: "Version of the package to be installed",
				},

				cli.StringFlag{
					Name:  "outputFolder, o",
					Usage: "Path to the output folder for the package to be installed",
					Value: "./", // os.Getwd()
				},

				cli.StringFlag{
					Name:  "source, s",
					Usage: "Base URL for the desired zippy endpoint to be looked at for this install operation",
				},
			},
		},

		cli.Command{
			Name:      "push",
			Usage:     "Pushes the specified package to the specified source",
			ArgsUsage: "[package-file-path]",
			Flags: []cli.Flag{

				// If the version is not specified, it will be be extrated from the package file.
				// E.g. for my-foo.1.0.2-rc2.zip, 1.0.2-rc2 will be the version
				cli.StringFlag{
					Name:  "version, v",
					Usage: "Version of the package to be pushed to the source along with the package",
				},

				cli.StringFlag{
					Name:  "source, s",
					Usage: "Base URL for the desired zippy endpoint to be looked at for this push operation",
				},
			},
		},
	}

	app.Action = func(c *cli.Context) error {
		fmt.Print("hello and byee!\n")
		return cli.NewExitError("no pun intended", -1)
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
  "github.com/garyburd/redigo/redis"
  "os"
  "os/exec"
  "fmt"
  "log"
  "flag"
)

var (
  hostname string
  num_labels int
)

func init() {
  flag.StringVar(&hostname,"host","localhost","Redis server hostname")
  flag.IntVar(&num_labels,"labels",1,"Number of labels to print")

  flag.Parse()
}

func save_used_label(p *redis.Pool, label string) {
  redis.String(p.Get().Do("SADD", "ngs_ids_used_000", label))
}

func printLabel(p *redis.Pool, num_ids int) {

  lp := exec.Command("/bin/cat")
  outfile, err := os.Create("./out.txt")
  if err != nil {
      panic(err)
  }
  defer outfile.Close()
  lp.Stdout = outfile

  lp_in, err := lp.StdinPipe()
  if err != nil {
    panic(err)
  }
  err = lp.Start()
  if err != nil {
      panic(err)
  }

  for i:=0; i < num_ids; i++ {
    reply, err := redis.String(p.Get().Do("srandmember","ngs_ids_000"))
    if err != nil {
      log.Fatal(err)
    }
    fmt.Printf("ngs-%s\n",reply)
    lp_in.Write([]byte(fmt.Sprintf("ngs-%s\n",reply)))
    go save_used_label(p,reply)
  }

  lp_in.Close()

  lp.Wait()
}

func main() {
  p := redis.NewPool(func() (redis.Conn, error) { return redis.Dial("tcp", fmt.Sprintf("%s:6379",hostname)) }, 2)
  defer p.Close()

  printLabel(p,num_labels)
}
<commit_msg>Production POPing from queue & actuallly going to lp to print<commit_after>package main

import (
  "github.com/garyburd/redigo/redis"
  "os/exec"
  "fmt"
  "log"
  "flag"
)

var (
  hostname string
  num_labels int
)

func init() {
  flag.StringVar(&hostname,"host","localhost","Redis server hostname")
  flag.IntVar(&num_labels,"labels",1,"Number of labels to print")

  flag.Parse()
}

func save_used_label(p *redis.Pool, label string) {
  redis.String(p.Get().Do("SADD", "ngs_ids_used_000", label))
}

func printLabel(p *redis.Pool, num_ids int) {

  lp := exec.Command("/usr/bin/lp")

  lp_in, err := lp.StdinPipe()
  if err != nil {
    panic(err)
  }
  err = lp.Start()
  if err != nil {
      panic(err)
  }

  for i:=0; i < num_ids; i++ {
    reply, err := redis.String(p.Get().Do("SPOP","ngs_ids_000"))
    if err != nil {
      log.Fatal(err)
    }
    fmt.Printf("ngs-%s\n",reply)
    lp_in.Write([]byte(fmt.Sprintf("ngs-%s\n",reply)))
    go save_used_label(p,reply)
  }

  lp_in.Close()

  lp.Wait()
}

func main() {
  p := redis.NewPool(func() (redis.Conn, error) { return redis.Dial("tcp", fmt.Sprintf("%s:6379",hostname)) }, 2)
  defer p.Close()

  printLabel(p,num_labels)
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package simulator

import (
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/mo"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
)

type VirtualMachineSnapshot struct {
	mo.VirtualMachineSnapshot
}

func (v *VirtualMachineSnapshot) RemoveSnapshotTask(req *types.RemoveSnapshot_Task) soap.HasFault {
	task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
		var changes []types.PropertyChange

		Map.Remove(req.This)

		vm := Map.Get(v.Vm).(*VirtualMachine)
		Map.WithLock(vm, func() {
			if vm.Snapshot.CurrentSnapshot != nil && *vm.Snapshot.CurrentSnapshot == req.This {
				var parentSnapshot types.ManagedObjectReference
				if parentRef := findParentSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This); parentRef != nil {
					parentSnapshot = *parentRef
				}
				changes = append(changes, types.PropertyChange{Name: "snapshot.currentSnapshot", Val: parentSnapshot})
			}

			rootSnapshots := removeSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This, req.RemoveChildren)
			changes = append(changes, types.PropertyChange{Name: "snapshot.rootSnapshotList", Val: rootSnapshots})

			if len(rootSnapshots) == 0 {
				changes = []types.PropertyChange{
					{Name: "snapshot", Val: nil},
				}
			}

			Map.Update(vm, changes)
		})

		return nil, nil
	})

	return &methods.RemoveSnapshot_TaskBody{
		Res: &types.RemoveSnapshot_TaskResponse{
			Returnval: task.Run(),
		},
	}
}

func (v *VirtualMachineSnapshot) RevertToSnapshotTask(req *types.RevertToSnapshot_Task) soap.HasFault {
	task := CreateTask(v, "revertToSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
		vm := Map.Get(v.Vm).(*VirtualMachine)

		Map.WithLock(vm, func() {
			Map.Update(vm, []types.PropertyChange{
				{Name: "snapshot.currentSnapshot", Val: v.Self},
			})
		})

		return nil, nil
	})

	return &methods.RevertToSnapshot_TaskBody{
		Res: &types.RevertToSnapshot_TaskResponse{
			Returnval: task.Run(),
		},
	}
}
<commit_msg>vcsim: correct property update in RemoveSnapshotTask<commit_after>/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package simulator

import (
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/mo"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
)

type VirtualMachineSnapshot struct {
	mo.VirtualMachineSnapshot
}

func (v *VirtualMachineSnapshot) RemoveSnapshotTask(req *types.RemoveSnapshot_Task) soap.HasFault {
	task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
		var changes []types.PropertyChange

		Map.Remove(req.This)

		vm := Map.Get(v.Vm).(*VirtualMachine)
		Map.WithLock(vm, func() {
			if vm.Snapshot.CurrentSnapshot != nil && *vm.Snapshot.CurrentSnapshot == req.This {
				parent := findParentSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This)
				changes = append(changes, types.PropertyChange{Name: "snapshot.currentSnapshot", Val: parent})
			}

			rootSnapshots := removeSnapshotInTree(vm.Snapshot.RootSnapshotList, req.This, req.RemoveChildren)
			changes = append(changes, types.PropertyChange{Name: "snapshot.rootSnapshotList", Val: rootSnapshots})

			if len(rootSnapshots) == 0 {
				changes = []types.PropertyChange{
					{Name: "snapshot", Val: nil},
				}
			}

			Map.Update(vm, changes)
		})

		return nil, nil
	})

	return &methods.RemoveSnapshot_TaskBody{
		Res: &types.RemoveSnapshot_TaskResponse{
			Returnval: task.Run(),
		},
	}
}

func (v *VirtualMachineSnapshot) RevertToSnapshotTask(req *types.RevertToSnapshot_Task) soap.HasFault {
	task := CreateTask(v, "revertToSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) {
		vm := Map.Get(v.Vm).(*VirtualMachine)

		Map.WithLock(vm, func() {
			Map.Update(vm, []types.PropertyChange{
				{Name: "snapshot.currentSnapshot", Val: v.Self},
			})
		})

		return nil, nil
	})

	return &methods.RevertToSnapshot_TaskBody{
		Res: &types.RevertToSnapshot_TaskResponse{
			Returnval: task.Run(),
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/gtfierro/cs262-project/common"
	"gopkg.in/vmihailenco/msgpack.v2"
	"net"
	"sync"
)

var emptyList = []common.UUID{}

// Handles the subscriptions, updates, forwarding
type Broker struct {
	metadata *MetadataStore

	// map queries to clients
	subscriber_lock sync.RWMutex
	subscribers     map[string][]Client

	// map of producer ids to queries
	forwarding_lock sync.RWMutex
	forwarding      map[common.UUID]*queryList

	// index of producers
	producers_lock sync.RWMutex
	producers      map[common.UUID]*Producer

	// map query string to query struct
	query_lock sync.RWMutex
	queries    map[string]*Query
}

//TODO: config for broker?
func NewBroker(metadata *MetadataStore) *Broker {
	return &Broker{
		metadata:    metadata,
		subscribers: make(map[string][]Client),
		forwarding:  make(map[common.UUID]*queryList),
		producers:   make(map[common.UUID]*Producer),
		queries:     make(map[string]*Query),
	}
}

// safely adds entry to map[query][]Client map
func (b *Broker) mapQueryToClient(query string, c *Client) {
	b.subscriber_lock.Lock()
	if list, found := b.subscribers[query]; found {
		// check if we are already in the list
		for _, c2 := range list {
			if c2 == *c {
				b.subscriber_lock.Unlock()
				return
			}
		}
		// if we aren't in the list, but list exists, append to the end
		b.subscribers[query] = append(list, *c)
	} else {
		// otherwise, create a new list with us in it
		b.subscribers[query] = []Client{*c}
	}
	b.subscriber_lock.Unlock()
}

func (b *Broker) updateForwardingTable(query *Query) {
	b.forwarding_lock.Lock()
Loop:
	for producerID, _ := range query.MatchingProducers {
		if list, found := b.forwarding[producerID]; found {
			// check if we are already in the list
			for _, q2 := range *list {
				if q2 == query.Query {
					continue Loop
				}
			}
			log.WithFields(log.Fields{
				"producerID": producerID, "query": query.Query, "list": list,
			}).Debug("Adding query to existing query list")
			b.forwarding[producerID].addQuery(query.Query)
		} else {
			log.WithFields(log.Fields{
				"producerID": producerID, "query": query.Query,
			}).Debug("Adding query to NEW query list")
			b.forwarding[producerID] = &queryList{query.Query}
		}
	}
	log.Debugf("forwarding table %v", b.forwarding)
	b.forwarding_lock.Unlock()
}

// we have the list of new and removed UUIDs for a query,
// so we update the forwarding table to match that
func (b *Broker) updateForwardingDiffs(query *Query, added, removed []common.UUID) {
	var (
		list  *queryList
		found bool
	)
	if len(removed) > 0 {
		b.forwarding_lock.Lock()
		for _, rm_uuid := range removed {
			if list, found = b.forwarding[rm_uuid]; !found {
				// no subscribers for this uuid
				continue
			}
			for _, tmp_query := range *list {
				if tmp_query == query.Query {
					list.removeQuery(query.Query)
					continue
				}
			}
			b.forwarding[rm_uuid] = list // TODO ETK why is this step necessary?

		}
		b.forwarding_lock.Unlock()
	}
	b.updateForwardingTable(query)
}

func (b *Broker) ForwardMessage(m *common.Message) {
	var (
		matchingQueries *queryList
		found           bool
	)
	log.Debugf("forwarding msg? %v", m)
	b.forwarding_lock.RLock()
	// return if we can't find anyone to forward to
	matchingQueries, found = b.forwarding[m.UUID]
	b.forwarding_lock.RUnlock()

	if !found || (matchingQueries != nil && len(*matchingQueries) == 0) {
		log.Debugf("no forwarding targets")
		return
	}

	var clientList []Client
	for _, query := range *matchingQueries {
		b.subscriber_lock.RLock()
		clientList, found = b.subscribers[query]
		b.subscriber_lock.RUnlock()
		if !found || len(clientList) == 0 {
			log.Debugf("found no clients")
			break
		}
		for _, client := range clientList {
			go client.Send(m)
		}
	}
}

func (b *Broker) SendSubscriptionDiffs(query string, added, removed []common.UUID) {
	// if we don't do this, then empty lists show up as None
	// when we pack them
	if len(added) == 0 {
		added = emptyList
	}
	if len(removed) == 0 {
		removed = emptyList
	}
	msg := map[string][]common.UUID{"New": added, "Del": removed}
	// send to subscribers
	b.subscriber_lock.RLock()
	subscribers := b.subscribers[query]
	b.subscriber_lock.RUnlock()
	for _, sub := range subscribers {
		go sub.Send(msg)
	}
}

// Evaluates the query and establishes the forwarding decisions.
// Returns the client
func (b *Broker) NewSubscription(querystring string, conn net.Conn) *Client {
	var (
		query *Query
		found bool
		err   error
	)
	b.query_lock.RLock()
	query, found = b.queries[querystring]
	b.query_lock.RUnlock()

	if !found {
		// parse it!
		queryAST := Parse(querystring)
		query, err = b.metadata.Query(queryAST)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err, "query": querystring,
			}).Error("Error evaluating mongo query")
		}

		// add to our map of queries
		b.query_lock.Lock()
		b.queries[querystring] = query
		b.query_lock.Unlock()

		log.WithFields(log.Fields{
			"query": querystring, "results": query.MatchingProducers,
		}).Debug("Evaluated query")
	}

	c := NewClient(querystring, &conn)
	go c.dosend()

	// set up forwarding for all initial producers
	b.updateForwardingTable(query)
	b.mapQueryToClient(querystring, c)
	c.Send(query.MatchingProducers)

	return c
}

func (b *Broker) HandleProducer(msg *common.Message, dec *msgpack.Decoder, conn net.Conn) {
	// use uuid to find old producer or create new one
	// add producer.C to a list of channels to select from
	// when we receive a message from a producer, save the
	// metadata and evaluate it, then forward it.
	// decode the incoming message
	var (
		err   error
		found bool
		p     *Producer
	)

	// save the metadata
	err = b.metadata.Save(msg)
	if err != nil {
		log.WithFields(log.Fields{
			"message": msg, "error": err,
		}).Error("Could not save metadata")
		conn.Close()
		return
	}

	// find the producer
	b.producers_lock.RLock()
	p, found = b.producers[msg.UUID]
	b.producers_lock.RUnlock()
	if !found {
		p = NewProducer(msg.UUID, dec)
	}
	b.RemapProducer(p, msg)

	// queue first message to be sent
	b.ForwardMessage(msg)

	go func(p *Producer) {
		for p.C != nil { // TODO ETK not sure what this for-loop achieves
			select {
			case <-p.stop:
				return
			case msg := <-p.C:
				if len(msg.Metadata) > 0 {
					err = b.metadata.Save(msg)
					b.RemapProducer(p, msg)
				}
				b.ForwardMessage(msg)
			}
		}
	}(p)
}

// 1. Firstly, have a method that given a producer (which is an implicit pointer to its
//    metadata) reevaluates all queries.

// when we receive a new producer, find related queries and update the forwarding
// tables that match. If newMetadata is nil, it will just reevaluate using current
// producer metadata across *all* queries, else it can use metadata in the provided
// Message to filter which queries to reevaluate
func (b *Broker) RemapProducer(p *Producer, newMetadata *common.Message) {
	//TODO: make a list of queries to update so that its unique THEN actually reevaluate
	//      to get added/removed lists. Once we have added/removed lists we use
	//      that to update the forwarding table.
	//      Question: Do i save the loop over to make OLD until after the forwarding table
	//      is updated? NO this should be encapsulated?
	var queriesToReevaluate = make(map[string]*Query)
	// TODO ETK this `true` shouldn't be here, right? Debugging purposes?
	if newMetadata == nil || true { // reevaluate ALL queries
		b.subscriber_lock.RLock()
		for querystring, _ := range b.subscribers {
			if _, found := queriesToReevaluate[querystring]; !found {
				b.query_lock.RLock()
				queriesToReevaluate[querystring] = b.queries[querystring]
				b.query_lock.RUnlock()
			}
		}
		b.subscriber_lock.RUnlock()

		for _, query := range queriesToReevaluate {
			added, removed := b.metadata.Reevaluate(query)
			log.WithFields(log.Fields{
				"query": query.Query, "added": added, "removed": removed,
			}).Info("Reevaluated query")
			query.RWMutex.RLock()
			log.Debugf("remapped? %v %v %v", p, query)
			query.RWMutex.RUnlock()
			b.updateForwardingDiffs(query, added, removed)
			b.SendSubscriptionDiffs(query.Query, added, removed)
		}
	}
}
<commit_msg>remove unnecessary assignment<commit_after>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/gtfierro/cs262-project/common"
	"gopkg.in/vmihailenco/msgpack.v2"
	"net"
	"sync"
)

var emptyList = []common.UUID{}

// Handles the subscriptions, updates, forwarding
type Broker struct {
	metadata *MetadataStore

	// map queries to clients
	subscriber_lock sync.RWMutex
	subscribers     map[string][]Client

	// map of producer ids to queries
	forwarding_lock sync.RWMutex
	forwarding      map[common.UUID]*queryList

	// index of producers
	producers_lock sync.RWMutex
	producers      map[common.UUID]*Producer

	// map query string to query struct
	query_lock sync.RWMutex
	queries    map[string]*Query
}

//TODO: config for broker?
func NewBroker(metadata *MetadataStore) *Broker {
	return &Broker{
		metadata:    metadata,
		subscribers: make(map[string][]Client),
		forwarding:  make(map[common.UUID]*queryList),
		producers:   make(map[common.UUID]*Producer),
		queries:     make(map[string]*Query),
	}
}

// safely adds entry to map[query][]Client map
func (b *Broker) mapQueryToClient(query string, c *Client) {
	b.subscriber_lock.Lock()
	if list, found := b.subscribers[query]; found {
		// check if we are already in the list
		for _, c2 := range list {
			if c2 == *c {
				b.subscriber_lock.Unlock()
				return
			}
		}
		// if we aren't in the list, but list exists, append to the end
		b.subscribers[query] = append(list, *c)
	} else {
		// otherwise, create a new list with us in it
		b.subscribers[query] = []Client{*c}
	}
	b.subscriber_lock.Unlock()
}

func (b *Broker) updateForwardingTable(query *Query) {
	b.forwarding_lock.Lock()
Loop:
	for producerID, _ := range query.MatchingProducers {
		if list, found := b.forwarding[producerID]; found {
			// check if we are already in the list
			for _, q2 := range *list {
				if q2 == query.Query {
					continue Loop
				}
			}
			log.WithFields(log.Fields{
				"producerID": producerID, "query": query.Query, "list": list,
			}).Debug("Adding query to existing query list")
			b.forwarding[producerID].addQuery(query.Query)
		} else {
			log.WithFields(log.Fields{
				"producerID": producerID, "query": query.Query,
			}).Debug("Adding query to NEW query list")
			b.forwarding[producerID] = &queryList{query.Query}
		}
	}
	log.Debugf("forwarding table %v", b.forwarding)
	b.forwarding_lock.Unlock()
}

// we have the list of new and removed UUIDs for a query,
// so we update the forwarding table to match that
func (b *Broker) updateForwardingDiffs(query *Query, added, removed []common.UUID) {
	var (
		list  *queryList
		found bool
	)
	if len(removed) > 0 {
		b.forwarding_lock.Lock()
		for _, rm_uuid := range removed {
			if list, found = b.forwarding[rm_uuid]; !found {
				// no subscribers for this uuid
				continue
			}
			for _, tmp_query := range *list {
				if tmp_query == query.Query {
					list.removeQuery(query.Query)
					continue
				}
			}
		}
		b.forwarding_lock.Unlock()
	}
	b.updateForwardingTable(query)
}

func (b *Broker) ForwardMessage(m *common.Message) {
	var (
		matchingQueries *queryList
		found           bool
	)
	log.Debugf("forwarding msg? %v", m)
	b.forwarding_lock.RLock()
	// return if we can't find anyone to forward to
	matchingQueries, found = b.forwarding[m.UUID]
	b.forwarding_lock.RUnlock()

	if !found || (matchingQueries != nil && len(*matchingQueries) == 0) {
		log.Debugf("no forwarding targets")
		return
	}

	var clientList []Client
	for _, query := range *matchingQueries {
		b.subscriber_lock.RLock()
		clientList, found = b.subscribers[query]
		b.subscriber_lock.RUnlock()
		if !found || len(clientList) == 0 {
			log.Debugf("found no clients")
			break
		}
		for _, client := range clientList {
			go client.Send(m)
		}
	}
}

func (b *Broker) SendSubscriptionDiffs(query string, added, removed []common.UUID) {
	// if we don't do this, then empty lists show up as None
	// when we pack them
	if len(added) == 0 {
		added = emptyList
	}
	if len(removed) == 0 {
		removed = emptyList
	}
	msg := map[string][]common.UUID{"New": added, "Del": removed}
	// send to subscribers
	b.subscriber_lock.RLock()
	subscribers := b.subscribers[query]
	b.subscriber_lock.RUnlock()
	for _, sub := range subscribers {
		go sub.Send(msg)
	}
}

// Evaluates the query and establishes the forwarding decisions.
// Returns the client
func (b *Broker) NewSubscription(querystring string, conn net.Conn) *Client {
	var (
		query *Query
		found bool
		err   error
	)
	b.query_lock.RLock()
	query, found = b.queries[querystring]
	b.query_lock.RUnlock()

	if !found {
		// parse it!
		queryAST := Parse(querystring)
		query, err = b.metadata.Query(queryAST)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err, "query": querystring,
			}).Error("Error evaluating mongo query")
		}

		// add to our map of queries
		b.query_lock.Lock()
		b.queries[querystring] = query
		b.query_lock.Unlock()

		log.WithFields(log.Fields{
			"query": querystring, "results": query.MatchingProducers,
		}).Debug("Evaluated query")
	}

	c := NewClient(querystring, &conn)
	go c.dosend()

	// set up forwarding for all initial producers
	b.updateForwardingTable(query)
	b.mapQueryToClient(querystring, c)
	c.Send(query.MatchingProducers)

	return c
}

func (b *Broker) HandleProducer(msg *common.Message, dec *msgpack.Decoder, conn net.Conn) {
	// use uuid to find old producer or create new one
	// add producer.C to a list of channels to select from
	// when we receive a message from a producer, save the
	// metadata and evaluate it, then forward it.
	// decode the incoming message
	var (
		err   error
		found bool
		p     *Producer
	)

	// save the metadata
	err = b.metadata.Save(msg)
	if err != nil {
		log.WithFields(log.Fields{
			"message": msg, "error": err,
		}).Error("Could not save metadata")
		conn.Close()
		return
	}

	// find the producer
	b.producers_lock.RLock()
	p, found = b.producers[msg.UUID]
	b.producers_lock.RUnlock()
	if !found {
		p = NewProducer(msg.UUID, dec)
	}
	b.RemapProducer(p, msg)

	// queue first message to be sent
	b.ForwardMessage(msg)

	go func(p *Producer) {
		for p.C != nil { // TODO ETK not sure what this for-loop achieves
			select {
			case <-p.stop:
				return
			case msg := <-p.C:
				if len(msg.Metadata) > 0 {
					err = b.metadata.Save(msg)
					b.RemapProducer(p, msg)
				}
				b.ForwardMessage(msg)
			}
		}
	}(p)
}

// 1. Firstly, have a method that given a producer (which is an implicit pointer to its
//    metadata) reevaluates all queries.

// when we receive a new producer, find related queries and update the forwarding
// tables that match. If newMetadata is nil, it will just reevaluate using current
// producer metadata across *all* queries, else it can use metadata in the provided
// Message to filter which queries to reevaluate
func (b *Broker) RemapProducer(p *Producer, newMetadata *common.Message) {
	//TODO: make a list of queries to update so that its unique THEN actually reevaluate
	//      to get added/removed lists. Once we have added/removed lists we use
	//      that to update the forwarding table.
	//      Question: Do i save the loop over to make OLD until after the forwarding table
	//      is updated? NO this should be encapsulated?
	var queriesToReevaluate = make(map[string]*Query)
	// TODO ETK this `true` shouldn't be here, right? Debugging purposes?
	if newMetadata == nil || true { // reevaluate ALL queries
		b.subscriber_lock.RLock()
		for querystring, _ := range b.subscribers {
			if _, found := queriesToReevaluate[querystring]; !found {
				b.query_lock.RLock()
				queriesToReevaluate[querystring] = b.queries[querystring]
				b.query_lock.RUnlock()
			}
		}
		b.subscriber_lock.RUnlock()

		for _, query := range queriesToReevaluate {
			added, removed := b.metadata.Reevaluate(query)
			log.WithFields(log.Fields{
				"query": query.Query, "added": added, "removed": removed,
			}).Info("Reevaluated query")
			query.RWMutex.RLock()
			log.Debugf("remapped? %v %v %v", p, query)
			query.RWMutex.RUnlock()
			b.updateForwardingDiffs(query, added, removed)
			b.SendSubscriptionDiffs(query.Query, added, removed)
		}
	}
}
<|endoftext|>


<commit_before>package token

// Type is a token type.
type Type string

const (
	// ILLEGAL is a token type for illegal tokens.
	ILLEGAL Type = "ILLEGAL"
	// EOF is a token type that represents end of file.
	EOF = "EOF"

	// IDENT is a token type for identifiers.
	IDENT = "IDENT" // add, foobar, x, y, ...
	// INT is a token type for integers.
	INT = "INT"
	// FLOAT is a token type for floating point numbers.
	FLOAT = "FLOAT"
	// STRING is a token type for strings.
	STRING = "STRING"

	// BANG is a token type for NOT operator.
	BANG = "!"
	// ASSIGN is a token type for assignment operators.
	ASSIGN = "="
	// PLUS is a token type for addition.
	PLUS = "+"
	// MINUS is a token type for substraction.
	MINUS = "-"
	// ASTARISK is a token type for multiplication.
	ASTARISK = "*"
	// SLASH is a token type for division.
	SLASH = "/"
	// LT is a token ype for 'less than' operator.
	LT = "<"
	// GT is a token ype for 'greater than' operator.
	GT = ">"
	// EQ is a token type for equality operator.
	EQ = "=="
	// NEQ is a token type for not equality operator.
	NEQ = "!="

	// COMMA is a token type for commas.
	COMMA = ","
	// SEMICOLON is a token type for semicolons.
	SEMICOLON = ";"
	// COLON is a token type for colons.
	COLON = ":"

	// LPAREN is a token type for left parentheses.
	LPAREN = "("
	// RPAREN is a token type for right parentheses.
	RPAREN = ")"
	// LBRACE is a token type for left braces.
	LBRACE = "{"
	// RBRACE is a token type for right braces.
	RBRACE = "}"
	// LBRACKET is a token type for left brackets.
	LBRACKET = "["
	// RBRACKET is a token type for right brackets.
	RBRACKET = "]"

	// FUNCTION is a token type for functions.
	FUNCTION = "FUNCTION"
	// LET is a token type for lets.
	LET = "LET"
	// TRUE is a token type for true.
	TRUE = "TRUE"
	// FALSE is a token type for false.
	FALSE = "FALSE"
	// IF is a token type for if.
	IF = "IF"
	// ELSE is a token type for else.
	ELSE = "ELSE"
	// RETURN is a token type for return.
	RETURN = "RETURN"
)

// Token represents a token which has a token type and literal.
type Token struct {
	Type    Type
	Literal string
}

// Language keywords
var keywords = map[string]Type{
	"fn":     FUNCTION,
	"let":    LET,
	"true":   TRUE,
	"false":  FALSE,
	"if":     IF,
	"else":   ELSE,
	"return": RETURN,
}

// LookupIdent checks the language keywords to see whether the given identifier is a keyword.
// If it is, it returns the keyword's Type constant. If it isn't, it just gets back IDENT.
func LookupIdent(ident string) Type {
	if tok, ok := keywords[ident]; ok {
		return tok
	}
	return IDENT
}
<commit_msg>token: fix typo<commit_after>package token

// Type is a token type.
type Type string

const (
	// ILLEGAL is a token type for illegal tokens.
	ILLEGAL Type = "ILLEGAL"
	// EOF is a token type that represents end of file.
	EOF = "EOF"

	// IDENT is a token type for identifiers.
	IDENT = "IDENT" // add, foobar, x, y, ...
	// INT is a token type for integers.
	INT = "INT"
	// FLOAT is a token type for floating point numbers.
	FLOAT = "FLOAT"
	// STRING is a token type for strings.
	STRING = "STRING"

	// BANG is a token type for NOT operator.
	BANG = "!"
	// ASSIGN is a token type for assignment operators.
	ASSIGN = "="
	// PLUS is a token type for addition.
	PLUS = "+"
	// MINUS is a token type for subtraction.
	MINUS = "-"
	// ASTARISK is a token type for multiplication.
	ASTARISK = "*"
	// SLASH is a token type for division.
	SLASH = "/"
	// LT is a token ype for 'less than' operator.
	LT = "<"
	// GT is a token ype for 'greater than' operator.
	GT = ">"
	// EQ is a token type for equality operator.
	EQ = "=="
	// NEQ is a token type for not equality operator.
	NEQ = "!="

	// COMMA is a token type for commas.
	COMMA = ","
	// SEMICOLON is a token type for semicolons.
	SEMICOLON = ";"
	// COLON is a token type for colons.
	COLON = ":"

	// LPAREN is a token type for left parentheses.
	LPAREN = "("
	// RPAREN is a token type for right parentheses.
	RPAREN = ")"
	// LBRACE is a token type for left braces.
	LBRACE = "{"
	// RBRACE is a token type for right braces.
	RBRACE = "}"
	// LBRACKET is a token type for left brackets.
	LBRACKET = "["
	// RBRACKET is a token type for right brackets.
	RBRACKET = "]"

	// FUNCTION is a token type for functions.
	FUNCTION = "FUNCTION"
	// LET is a token type for lets.
	LET = "LET"
	// TRUE is a token type for true.
	TRUE = "TRUE"
	// FALSE is a token type for false.
	FALSE = "FALSE"
	// IF is a token type for if.
	IF = "IF"
	// ELSE is a token type for else.
	ELSE = "ELSE"
	// RETURN is a token type for return.
	RETURN = "RETURN"
)

// Token represents a token which has a token type and literal.
type Token struct {
	Type    Type
	Literal string
}

// Language keywords
var keywords = map[string]Type{
	"fn":     FUNCTION,
	"let":    LET,
	"true":   TRUE,
	"false":  FALSE,
	"if":     IF,
	"else":   ELSE,
	"return": RETURN,
}

// LookupIdent checks the language keywords to see whether the given identifier is a keyword.
// If it is, it returns the keyword's Type constant. If it isn't, it just gets back IDENT.
func LookupIdent(ident string) Type {
	if tok, ok := keywords[ident]; ok {
		return tok
	}
	return IDENT
}
<|endoftext|>


<commit_before>// Package transfer collects together adapters for uploading and downloading LFS content
// NOTE: Subject to change, do not rely on this package from outside git-lfs source
package tq

import (
	"fmt"
	"time"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/lfsapi"
)

type Direction int

const (
	Upload   = Direction(iota)
	Download = Direction(iota)
)

func (d Direction) String() string {
	switch d {
	case Download:
		return "download"
	case Upload:
		return "upload"
	default:
		return "<unknown>"
	}
}

type Transfer struct {
	Name          string       `json:"name,omitempty"`
	Oid           string       `json:"oid,omitempty"`
	Size          int64        `json:"size"`
	Authenticated bool         `json:"authenticated,omitempty"`
	Actions       mapActionSet `json:"actions,omitempty"`
	Links         mapActionSet `json:"_links,omitempty"`
	Error         *ObjectError `json:"error,omitempty"`
	Path          string       `json:"path,omitempty"`
}

func (t *Transfer) Rel(name string) (*Action, bool) {
	if t.Actions == nil {
		return nil, false
	}

	rel, ok := t.Actions[name]
	return rel, ok
}

type ObjectError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (e *ObjectError) Error() string {
	return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}

// newTransfer returns a copy of the given Transfer, with the name and path
// values set.
func newTransfer(tr *Transfer, name string, path string) *Transfer {
	t := &Transfer{
		Name:          name,
		Path:          path,
		Oid:           tr.Oid,
		Size:          tr.Size,
		Authenticated: tr.Authenticated,
		Actions:       make(mapActionSet),
	}

	if tr.Error != nil {
		t.Error = &ObjectError{
			Code:    tr.Error.Code,
			Message: tr.Error.Message,
		}
	}

	for rel, action := range tr.Actions {
		t.Actions[rel] = &Action{
			Href:      action.Href,
			Header:    action.Header,
			ExpiresAt: action.ExpiresAt,
		}
	}

	if tr.Links != nil {
		t.Links = make(mapActionSet)

		for rel, link := range tr.Links {
			t.Links[rel] = &Action{
				Href:      link.Href,
				Header:    link.Header,
				ExpiresAt: link.ExpiresAt,
			}
		}
	}

	return t
}

type Action struct {
	Href      string            `json:"href"`
	Header    map[string]string `json:"header,omitempty"`
	ExpiresAt time.Time         `json:"expires_at,omitempty"`
}

type ActionSet interface {
	Get(rel string) (*Action, error)
}

type mapActionSet map[string]*Action

const (
	// objectExpirationToTransfer is the duration we expect to have passed
	// from the time that the object's expires_at property is checked to
	// when the transfer is executed.
	objectExpirationToTransfer = 5 * time.Second
)

func (as mapActionSet) Get(rel string) (*Action, error) {
	a, ok := as[rel]
	if !ok {
		return nil, nil
	}

	if !a.ExpiresAt.IsZero() && a.ExpiresAt.Before(time.Now().Add(objectExpirationToTransfer)) {
		return nil, errors.NewRetriableError(&ActionExpiredErr{Rel: rel, At: a.ExpiresAt})
	}

	return a, nil
}

type ActionExpiredErr struct {
	Rel string
	At  time.Time
}

func (e ActionExpiredErr) Error() string {
	return fmt.Sprintf("tq: action %q expires at %s",
		e.Rel, e.At.In(time.Local).Format(time.RFC822))
}

func IsActionExpiredError(err error) bool {
	if _, ok := err.(*ActionExpiredErr); ok {
		return true
	}
	return false
}

// NewAdapterFunc creates new instances of Adapter. Code that wishes
// to provide new Adapter instances should pass an implementation of this
// function to RegisterNewTransferAdapterFunc() on a *Manifest.
// name and dir are to provide context if one func implements many instances
type NewAdapterFunc func(name string, dir Direction) Adapter

type ProgressCallback func(name string, totalSize, readSoFar int64, readSinceLast int) error

type AdapterConfig interface {
	APIClient() *lfsapi.Client
	ConcurrentTransfers() int
	Remote() string
}

type adapterConfig struct {
	apiClient           *lfsapi.Client
	concurrentTransfers int
	remote              string
}

func (c *adapterConfig) ConcurrentTransfers() int {
	return c.concurrentTransfers
}

func (c *adapterConfig) APIClient() *lfsapi.Client {
	return c.apiClient
}

func (c *adapterConfig) Remote() string {
	return c.remote
}

// Adapter is implemented by types which can upload and/or download LFS
// file content to a remote store. Each Adapter accepts one or more requests
// which it may schedule and parallelise in whatever way it chooses, clients of
// this interface will receive notifications of progress and completion asynchronously.
// TransferAdapters support transfers in one direction; if an implementation
// provides support for upload and download, it should be instantiated twice,
// advertising support for each direction separately.
// Note that Adapter only implements the actual upload/download of content
// itself; organising the wider process including calling the API to get URLs,
// handling progress reporting and retries is the job of the core TransferQueue.
// This is so that the orchestration remains core & standard but Adapter
// can be changed to physically transfer to different hosts with less code.
type Adapter interface {
	// Name returns the name of this adapter, which is the same for all instances
	// of this type of adapter
	Name() string
	// Direction returns whether this instance is an upload or download instance
	// Adapter instances can only be one or the other, although the same
	// type may be instantiated for each direction
	Direction() Direction
	// Begin a new batch of uploads or downloads. Call this first, followed by
	// one or more Add calls. maxConcurrency controls the number of transfers
	// that may be done at once. The passed in callback will receive updates on
	// progress. Either argument may be nil if not required by the client.
	Begin(cfg AdapterConfig, cb ProgressCallback) error
	// Add queues a download/upload, which will complete asynchronously and
	// notify the callbacks given to Begin()
	Add(transfers ...*Transfer) (results <-chan TransferResult)
	// Indicate that all transfers have been scheduled and resources can be released
	// once the queued items have completed.
	// This call blocks until all items have been processed
	End()
	// ClearTempStorage clears any temporary files, such as unfinished downloads that
	// would otherwise be resumed
	ClearTempStorage() error
}

// Result of a transfer returned through CompletionChannel()
type TransferResult struct {
	Transfer *Transfer
	// This will be non-nil if there was an error transferring this item
	Error error
}
<commit_msg>tq: implement 'multiActionSet'<commit_after>// Package transfer collects together adapters for uploading and downloading LFS content
// NOTE: Subject to change, do not rely on this package from outside git-lfs source
package tq

import (
	"fmt"
	"time"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/lfsapi"
)

type Direction int

const (
	Upload   = Direction(iota)
	Download = Direction(iota)
)

func (d Direction) String() string {
	switch d {
	case Download:
		return "download"
	case Upload:
		return "upload"
	default:
		return "<unknown>"
	}
}

type Transfer struct {
	Name          string       `json:"name,omitempty"`
	Oid           string       `json:"oid,omitempty"`
	Size          int64        `json:"size"`
	Authenticated bool         `json:"authenticated,omitempty"`
	Actions       mapActionSet `json:"actions,omitempty"`
	Links         mapActionSet `json:"_links,omitempty"`
	Error         *ObjectError `json:"error,omitempty"`
	Path          string       `json:"path,omitempty"`
}

func (t *Transfer) Rel(name string) (*Action, bool) {
	if t.Actions == nil {
		return nil, false
	}

	rel, ok := t.Actions[name]
	return rel, ok
}

type ObjectError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (e *ObjectError) Error() string {
	return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}

// newTransfer returns a copy of the given Transfer, with the name and path
// values set.
func newTransfer(tr *Transfer, name string, path string) *Transfer {
	t := &Transfer{
		Name:          name,
		Path:          path,
		Oid:           tr.Oid,
		Size:          tr.Size,
		Authenticated: tr.Authenticated,
		Actions:       make(mapActionSet),
	}

	if tr.Error != nil {
		t.Error = &ObjectError{
			Code:    tr.Error.Code,
			Message: tr.Error.Message,
		}
	}

	for rel, action := range tr.Actions {
		t.Actions[rel] = &Action{
			Href:      action.Href,
			Header:    action.Header,
			ExpiresAt: action.ExpiresAt,
		}
	}

	if tr.Links != nil {
		t.Links = make(mapActionSet)

		for rel, link := range tr.Links {
			t.Links[rel] = &Action{
				Href:      link.Href,
				Header:    link.Header,
				ExpiresAt: link.ExpiresAt,
			}
		}
	}

	return t
}

type Action struct {
	Href      string            `json:"href"`
	Header    map[string]string `json:"header,omitempty"`
	ExpiresAt time.Time         `json:"expires_at,omitempty"`
}

type ActionSet interface {
	Get(rel string) (*Action, error)
}

type mapActionSet map[string]*Action

const (
	// objectExpirationToTransfer is the duration we expect to have passed
	// from the time that the object's expires_at property is checked to
	// when the transfer is executed.
	objectExpirationToTransfer = 5 * time.Second
)

func (as mapActionSet) Get(rel string) (*Action, error) {
	a, ok := as[rel]
	if !ok {
		return nil, nil
	}

	if !a.ExpiresAt.IsZero() && a.ExpiresAt.Before(time.Now().Add(objectExpirationToTransfer)) {
		return nil, errors.NewRetriableError(&ActionExpiredErr{Rel: rel, At: a.ExpiresAt})
	}

	return a, nil
}

// multiActionSet composes multiple `ActionSet`s.
type multiActionSet struct {
	as []ActionSet
}

// Get implements ActionSet.Get, and returns the first "ok" result (i.e., having
// a non-nil error, or action) from the `ActionSet`s of which it is composed, in
// their respective order.
func (m *multiActionSet) Get(rel string) (*Action, error) {
	for _, what := range m.as {
		a, err := what.Get(rel)
		if a != nil || err != nil {
			return a, err
		}
	}

	return nil, nil
}

type ActionExpiredErr struct {
	Rel string
	At  time.Time
}

func (e ActionExpiredErr) Error() string {
	return fmt.Sprintf("tq: action %q expires at %s",
		e.Rel, e.At.In(time.Local).Format(time.RFC822))
}

func IsActionExpiredError(err error) bool {
	if _, ok := err.(*ActionExpiredErr); ok {
		return true
	}
	return false
}

// NewAdapterFunc creates new instances of Adapter. Code that wishes
// to provide new Adapter instances should pass an implementation of this
// function to RegisterNewTransferAdapterFunc() on a *Manifest.
// name and dir are to provide context if one func implements many instances
type NewAdapterFunc func(name string, dir Direction) Adapter

type ProgressCallback func(name string, totalSize, readSoFar int64, readSinceLast int) error

type AdapterConfig interface {
	APIClient() *lfsapi.Client
	ConcurrentTransfers() int
	Remote() string
}

type adapterConfig struct {
	apiClient           *lfsapi.Client
	concurrentTransfers int
	remote              string
}

func (c *adapterConfig) ConcurrentTransfers() int {
	return c.concurrentTransfers
}

func (c *adapterConfig) APIClient() *lfsapi.Client {
	return c.apiClient
}

func (c *adapterConfig) Remote() string {
	return c.remote
}

// Adapter is implemented by types which can upload and/or download LFS
// file content to a remote store. Each Adapter accepts one or more requests
// which it may schedule and parallelise in whatever way it chooses, clients of
// this interface will receive notifications of progress and completion asynchronously.
// TransferAdapters support transfers in one direction; if an implementation
// provides support for upload and download, it should be instantiated twice,
// advertising support for each direction separately.
// Note that Adapter only implements the actual upload/download of content
// itself; organising the wider process including calling the API to get URLs,
// handling progress reporting and retries is the job of the core TransferQueue.
// This is so that the orchestration remains core & standard but Adapter
// can be changed to physically transfer to different hosts with less code.
type Adapter interface {
	// Name returns the name of this adapter, which is the same for all instances
	// of this type of adapter
	Name() string
	// Direction returns whether this instance is an upload or download instance
	// Adapter instances can only be one or the other, although the same
	// type may be instantiated for each direction
	Direction() Direction
	// Begin a new batch of uploads or downloads. Call this first, followed by
	// one or more Add calls. maxConcurrency controls the number of transfers
	// that may be done at once. The passed in callback will receive updates on
	// progress. Either argument may be nil if not required by the client.
	Begin(cfg AdapterConfig, cb ProgressCallback) error
	// Add queues a download/upload, which will complete asynchronously and
	// notify the callbacks given to Begin()
	Add(transfers ...*Transfer) (results <-chan TransferResult)
	// Indicate that all transfers have been scheduled and resources can be released
	// once the queued items have completed.
	// This call blocks until all items have been processed
	End()
	// ClearTempStorage clears any temporary files, such as unfinished downloads that
	// would otherwise be resumed
	ClearTempStorage() error
}

// Result of a transfer returned through CompletionChannel()
type TransferResult struct {
	Transfer *Transfer
	// This will be non-nil if there was an error transferring this item
	Error error
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"time"
)

// Transparently intercept HTTPS connections.

// runTransparentServer transparently intercepts connections, listening at addr.
func runTransparentServer(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	listenerChan <- ln

	var tempDelay time.Duration

	for {
		conn, err := ln.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				log.Printf("Accept error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return err
		}

		serverAddr, err := realServerAddress(&conn)
		if err != nil {
			log.Println("Error getting original address for intercepted connection:", err)
			continue
		}
		go SSLBump(conn, serverAddr, conn.RemoteAddr().String())
	}

	panic("unreachable")
}
<commit_msg>Strip port from client address for transparent HTTPS filtering.<commit_after>package main

import (
	"log"
	"net"
	"time"
)

// Transparently intercept HTTPS connections.

// runTransparentServer transparently intercepts connections, listening at addr.
func runTransparentServer(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	listenerChan <- ln

	var tempDelay time.Duration

	for {
		conn, err := ln.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				log.Printf("Accept error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return err
		}

		serverAddr, err := realServerAddress(&conn)
		if err != nil {
			log.Println("Error getting original address for intercepted connection:", err)
			continue
		}
		user, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
		go SSLBump(conn, serverAddr, user)
	}

	panic("unreachable")
}
<|endoftext|>


<commit_before>package nmeaais

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestType16MessageProcessing(t *testing.T) {
	Convey("When processing a type 16 message", t, func() {
		raws := []string{
			"!AIVDM,1,1,,B,@h3OvjBGaw3h3h0000000000,0*7E",
		}

		packets := buildPackets(raws)
		message, err := Process(packets)
		type15, err := message.GetAsAssignmentModeCommand()

		expected := &AssignmentModeCommand{
			MessageType:      16,
			RepeatIndicator:  3,
			MMSI:             3669705,
			DestinationMMSI1: 636091452,
			Offset1:          60,
			Increment1:       0,
			DestinationMMSI2: 0,
			Offset2:          0,
			Increment2:       0,
		}

		Convey("The get should return a type 16 message", func() {
			Convey("Where the message is not nil", func() {
				So(type15, ShouldNotBeNil)
			})
		})

		Convey("The get should not return an error", func() {
			So(err, ShouldBeNil)
		})

		Convey("The fields should be populated correctly", func() {
			So(type15, ShouldResemble, expected)
		})
	})
}
<commit_msg>Minor variable name fix<commit_after>package nmeaais

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestType16MessageProcessing(t *testing.T) {
	Convey("When processing a type 16 message", t, func() {
		raws := []string{
			"!AIVDM,1,1,,B,@h3OvjBGaw3h3h0000000000,0*7E",
		}

		packets := buildPackets(raws)
		message, err := Process(packets)
		type16, err := message.GetAsAssignmentModeCommand()

		expected := &AssignmentModeCommand{
			MessageType:      16,
			RepeatIndicator:  3,
			MMSI:             3669705,
			DestinationMMSI1: 636091452,
			Offset1:          60,
			Increment1:       0,
			DestinationMMSI2: 0,
			Offset2:          0,
			Increment2:       0,
		}

		Convey("The get should return a type 16 message", func() {
			Convey("Where the message is not nil", func() {
				So(type16, ShouldNotBeNil)
			})
		})

		Convey("The get should not return an error", func() {
			So(err, ShouldBeNil)
		})

		Convey("The fields should be populated correctly", func() {
			So(type16, ShouldResemble, expected)
		})
	})
}
<|endoftext|>


<commit_before>package types

type BrokerAdd struct {
	BindAddress      string
	Constraints      string
	Cpus             float64
	Expr             string
	FailoverDelay    string
	FailoverMaxDelay string
	FailoverMaxTries string
	Heap             float64
	JvmOptions       string
	Log4jOptions     string
	Mem              float64
	Options          string
	Port             string
	StickinessPeriod string
	Volume           string
}
<commit_msg>types: BrokerAdd field type change (all strings)<commit_after>package types

type BrokerAdd struct {
	BindAddress      string
	Constraints      string
	Cpus             string
	Expr             string
	FailoverDelay    string
	FailoverMaxDelay string
	FailoverMaxTries string
	Heap             string
	JvmOptions       string
	Log4jOptions     string
	Mem              string
	Options          string
	Port             string
	StickinessPeriod string
	Volume           string
}
<|endoftext|>