<commit_before>// Go binding for libGammu (library to work with different cell phones)
package gammu

/*
#include <gammu.h>

void sendCallback(GSM_StateMachine *sm, int status, int msgRef, void *data) {
	if (status==0) {
		*((GSM_Error *) data) = ERR_NONE;
	} else {
		*((GSM_Error *) data) = ERR_UNKNOWN;
	}
}
void setStatusCallback(GSM_StateMachine *sm, GSM_Error *status) {
	GSM_SetSendSMSStatusCallback(sm, sendCallback, status);
}
GSM_Debug_Info *debug_info;
void setDebug() {
	debug_info = GSM_GetGlobalDebug();
	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
	GSM_SetDebugLevel("textall", debug_info);
}

#cgo pkg-config: gammu
*/
import "C"
import (
	"fmt"
	"io"
	"runtime"
	"time"
	"unsafe"
)

// Error
type Error struct {
	descr string
	g     C.GSM_Error
}

func (e Error) Error() string {
	return fmt.Sprintf(
		"[%s] %s", e.descr, C.GoString(C.GSM_ErrorString(C.GSM_Error(e.g))),
	)
}

type EncodeError struct {
	g C.GSM_Error
}

func (e EncodeError) Error() string {
	return fmt.Sprintf(
		"[EncodeMultiPartSMS] %s", C.GoString(C.GSM_ErrorString(C.GSM_Error(e.g))),
	)
}

// StateMachine
type StateMachine struct {
	g      *C.GSM_StateMachine
	smsc   C.GSM_SMSC
	status C.GSM_Error

	Timeout time.Duration // Default 15s
}

// Creates new state maschine using cf configuration file or default
// configuration file if cf == "".
func NewStateMachine(cf string) (*StateMachine, error) {
	//C.setDebug()
	var config *C.INI_Section
	if cf != "" {
		cs := C.CString(cf)
		defer C.free(unsafe.Pointer(cs))
		if e := C.GSM_FindGammuRC(&config, cs); e != C.ERR_NONE {
			return nil, Error{"FindGammuRC", e}
		}
	} else {
		if e := C.GSM_FindGammuRC(&config, nil); e != C.ERR_NONE {
			return nil, Error{"FindGammuRC", e}
		}
	}
	defer C.INI_Free(config)

	sm := new(StateMachine)
	sm.g = C.GSM_AllocStateMachine()
	if sm.g == nil {
		panic("out of memory")
	}

	if e := C.GSM_ReadConfig(config, C.GSM_GetConfig(sm.g, 0), 0); e != C.ERR_NONE {
		sm.free()
		return nil, Error{"ReadConfig", e}
	}
	C.GSM_SetConfigNum(sm.g, 1)
	sm.Timeout = 15 * time.Second

	runtime.SetFinalizer(sm, (*StateMachine).free)
	return sm, nil
}

func (sm *StateMachine) free() {
	if sm.IsConnected() {
		sm.Disconnect()
	}
	C.GSM_FreeStateMachine(sm.g)
	sm.g = nil
}

func (sm *StateMachine) Connect() error {
	if e := C.GSM_InitConnection(sm.g, 1); e != C.ERR_NONE {
		return Error{"InitConnection", e}
	}
	C.setStatusCallback(sm.g, &sm.status)
	sm.smsc.Location = 1
	if e := C.GSM_GetSMSC(sm.g, &sm.smsc); e != C.ERR_NONE {
		return Error{"GetSMSC", e}
	}
	return nil
}

func (sm *StateMachine) IsConnected() bool {
	return C.GSM_IsConnected(sm.g) != 0
}

func (sm *StateMachine) Disconnect() error {
	if e := C.GSM_TerminateConnection(sm.g); e != C.ERR_NONE {
		return Error{"TerminateConnection", e}
	}
	return nil
}

func (sm *StateMachine) Reset() error {
	if e := C.GSM_Reset(sm.g, 0); e != C.ERR_NONE {
		return Error{"Reset", e}
	}
	return nil
}

func (sm *StateMachine) HardReset() error {
	if e := C.GSM_Reset(sm.g, 1); e != C.ERR_NONE {
		return Error{"Reset", e}
	}
	return nil
}

func decodeUTF8(out *C.uchar, in string) {
	cn := C.CString(in)
	C.DecodeUTF8(out, cn, C.int(len(in)))
	C.free(unsafe.Pointer(cn))
}

func (sm *StateMachine) sendSMS(sms *C.GSM_SMSMessage, number string, report bool) error {
	C.CopyUnicodeString(&sms.SMSC.Number[0], &sm.smsc.Number[0])
	decodeUTF8(&sms.Number[0], number)
	if report {
		sms.PDU = C.SMS_Status_Report
	} else {
		sms.PDU = C.SMS_Submit
	}
	// Send mepssage
	sm.status = C.ERR_TIMEOUT
	if e := C.GSM_SendSMS(sm.g, sms); e != C.ERR_NONE {
		return Error{"SendSMS", e}
	}
	// Wait for reply
	t := time.Now()
	for time.Now().Sub(t) < sm.Timeout {
		C.GSM_ReadDevice(sm.g, C.TRUE)
		if sm.status == C.ERR_NONE {
			// Message sent OK
			break
		} else if sm.status != C.ERR_TIMEOUT {
			// Error
			break
		}
	}
	if sm.status != C.ERR_NONE {
		return Error{"ReadDevice", sm.status}
	}
	return nil
}

func (sm *StateMachine) SendSMS(number, text string, report bool) error {
	var sms C.GSM_SMSMessage
	decodeUTF8(&sms.Text[0], text)
	sms.UDH.Type = C.UDH_NoUDH
	sms.Coding = C.SMS_Coding_Default_No_Compression
	sms.Class = 1
	return sm.sendSMS(&sms, number, report)
}

func (sm *StateMachine) SendLongSMS(number, text string, report bool) error {
	// Fill in SMS info
	var smsInfo C.GSM_MultiPartSMSInfo
	C.GSM_ClearMultiPartSMSInfo(&smsInfo)
	smsInfo.Class = 1
	smsInfo.EntriesNum = 1
	smsInfo.UnicodeCoding = C.FALSE
	// Check for non-ASCII rune
	for _, r := range text {
		if r > 0x7F {
			smsInfo.UnicodeCoding = C.TRUE
			break
		}
	}
	smsInfo.Entries[0].ID = C.SMS_ConcatenatedTextLong
	msgUnicode := make([]C.uchar, (len(text)+1)*2)
	decodeUTF8(&msgUnicode[0], text)
	smsInfo.Entries[0].Buffer = &msgUnicode[0]
	// Prepare multipart message
	var msms C.GSM_MultiSMSMessage
	if e := C.GSM_EncodeMultiPartSMS(nil, &smsInfo, &msms); e != C.ERR_NONE {
		return EncodeError{e}
	}
	// Send message
	for i := 0; i < int(msms.Number); i++ {
		if e := sm.sendSMS(&msms.SMS[i], number, report); e != nil {
			return e
		}
	}
	return nil
}

func encodeUTF8(in *C.uchar) string {
	l := C.UnicodeLength(in)
	if l == 0 {
		return ""
	}
	out := make([]C.char, C.UnicodeLength(in)*2)
	C.EncodeUTF8(&out[0], in)
	return C.GoString(&out[0])
}

func goTime(t *C.GSM_DateTime) time.Time {
	return time.Date(
		int(t.Year), time.Month(t.Month), int(t.Day),
		int(t.Hour), int(t.Minute), int(t.Second), 0,
		time.UTC,
	).Add(-time.Second * time.Duration(t.Timezone)).Local()
}

type SMS struct {
	Time     time.Time
	SMSCTime time.Time
	Number   string
	Report   bool // True if this message is a delivery report
	Body     string
}

// Read and deletes first avaliable message.
// Returns io.EOF if there is no more messages to read
func (sm *StateMachine) GetSMS() (sms SMS, err error) {
	var msms C.GSM_MultiSMSMessage
	if e := C.GSM_GetNextSMS(sm.g, &msms, C.TRUE); e != C.ERR_NONE {
		if e == C.ERR_EMPTY {
			err = io.EOF
		} else {
			err = Error{"GetNextSMS", e}
		}
		return
	}
	s := msms.SMS[msms.Number-1]
	sms.Number = encodeUTF8(&s.Number[0])
	sms.Time = goTime(&s.DateTime)
	sms.SMSCTime = goTime(&s.SMSCTime)

	for i := 0; i < int(msms.Number); i++ {
		s = msms.SMS[i]
		if s.Coding == C.SMS_Coding_8bit {
			continue
		}
		sms.Body += encodeUTF8(&s.Text[0])
		if s.PDU == C.SMS_Status_Report {
			sms.Report = true
		}
		s.Folder = 0 // Flat
		if e := C.GSM_DeleteSMS(sm.g, &s); e != C.ERR_NONE {
			err = Error{"DeleteSMS", e}
			return
		}
	}
	return
}
<commit_msg>Avoid pass Go pointer to Go pointer to C.<commit_after>// Go binding for libGammu (library to work with different cell phones)
package gammu

/*
#include <stdlib.h>
#include <gammu.h>

void sendCallback(GSM_StateMachine *sm, int status, int msgRef, void *data) {
	if (status==0) {
		*((GSM_Error *) data) = ERR_NONE;
	} else {
		*((GSM_Error *) data) = ERR_UNKNOWN;
	}
}
void setStatusCallback(GSM_StateMachine *sm, GSM_Error *status) {
	GSM_SetSendSMSStatusCallback(sm, sendCallback, status);
}
GSM_Debug_Info *debug_info;
void setDebug() {
	debug_info = GSM_GetGlobalDebug();
	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
	GSM_SetDebugLevel("textall", debug_info);
}

#cgo pkg-config: gammu
*/
import "C"
import (
	"fmt"
	"io"
	"runtime"
	"time"
	"unsafe"
)

// Error
type Error struct {
	descr string
	g     C.GSM_Error
}

func (e Error) Error() string {
	return fmt.Sprintf(
		"[%s] %s", e.descr, C.GoString(C.GSM_ErrorString(C.GSM_Error(e.g))),
	)
}

type EncodeError struct {
	g C.GSM_Error
}

func (e EncodeError) Error() string {
	return fmt.Sprintf(
		"[EncodeMultiPartSMS] %s", C.GoString(C.GSM_ErrorString(C.GSM_Error(e.g))),
	)
}

// StateMachine
type StateMachine struct {
	g      *C.GSM_StateMachine
	smsc   C.GSM_SMSC
	status C.GSM_Error

	Timeout time.Duration // Default 15s
}

// Creates new state maschine using cf configuration file or default
// configuration file if cf == "".
func NewStateMachine(cf string) (*StateMachine, error) {
	//C.setDebug()
	var config *C.INI_Section
	if cf != "" {
		cs := C.CString(cf)
		defer C.free(unsafe.Pointer(cs))
		if e := C.GSM_FindGammuRC(&config, cs); e != C.ERR_NONE {
			return nil, Error{"FindGammuRC", e}
		}
	} else {
		if e := C.GSM_FindGammuRC(&config, nil); e != C.ERR_NONE {
			return nil, Error{"FindGammuRC", e}
		}
	}
	defer C.INI_Free(config)

	sm := new(StateMachine)
	sm.g = C.GSM_AllocStateMachine()
	if sm.g == nil {
		panic("out of memory")
	}

	if e := C.GSM_ReadConfig(config, C.GSM_GetConfig(sm.g, 0), 0); e != C.ERR_NONE {
		sm.free()
		return nil, Error{"ReadConfig", e}
	}
	C.GSM_SetConfigNum(sm.g, 1)
	sm.Timeout = 15 * time.Second

	runtime.SetFinalizer(sm, (*StateMachine).free)
	return sm, nil
}

func (sm *StateMachine) free() {
	if sm.IsConnected() {
		sm.Disconnect()
	}
	C.GSM_FreeStateMachine(sm.g)
	sm.g = nil
}

func (sm *StateMachine) Connect() error {
	if e := C.GSM_InitConnection(sm.g, 1); e != C.ERR_NONE {
		return Error{"InitConnection", e}
	}
	C.setStatusCallback(sm.g, &sm.status)
	sm.smsc.Location = 1
	if e := C.GSM_GetSMSC(sm.g, &sm.smsc); e != C.ERR_NONE {
		return Error{"GetSMSC", e}
	}
	return nil
}

func (sm *StateMachine) IsConnected() bool {
	return C.GSM_IsConnected(sm.g) != 0
}

func (sm *StateMachine) Disconnect() error {
	if e := C.GSM_TerminateConnection(sm.g); e != C.ERR_NONE {
		return Error{"TerminateConnection", e}
	}
	return nil
}

func (sm *StateMachine) Reset() error {
	if e := C.GSM_Reset(sm.g, 0); e != C.ERR_NONE {
		return Error{"Reset", e}
	}
	return nil
}

func (sm *StateMachine) HardReset() error {
	if e := C.GSM_Reset(sm.g, 1); e != C.ERR_NONE {
		return Error{"Reset", e}
	}
	return nil
}

func decodeUTF8(out *C.uchar, in string) {
	cn := C.CString(in)
	C.DecodeUTF8(out, cn, C.int(len(in)))
	C.free(unsafe.Pointer(cn))
}

func (sm *StateMachine) sendSMS(sms *C.GSM_SMSMessage, number string, report bool) error {
	C.CopyUnicodeString(&sms.SMSC.Number[0], &sm.smsc.Number[0])
	decodeUTF8(&sms.Number[0], number)
	if report {
		sms.PDU = C.SMS_Status_Report
	} else {
		sms.PDU = C.SMS_Submit
	}
	// Send mepssage
	sm.status = C.ERR_TIMEOUT
	if e := C.GSM_SendSMS(sm.g, sms); e != C.ERR_NONE {
		return Error{"SendSMS", e}
	}
	// Wait for reply
	t := time.Now()
	for time.Now().Sub(t) < sm.Timeout {
		C.GSM_ReadDevice(sm.g, C.TRUE)
		if sm.status == C.ERR_NONE {
			// Message sent OK
			break
		} else if sm.status != C.ERR_TIMEOUT {
			// Error
			break
		}
	}
	if sm.status != C.ERR_NONE {
		return Error{"ReadDevice", sm.status}
	}
	return nil
}

func (sm *StateMachine) SendSMS(number, text string, report bool) error {
	var sms C.GSM_SMSMessage
	decodeUTF8(&sms.Text[0], text)
	sms.UDH.Type = C.UDH_NoUDH
	sms.Coding = C.SMS_Coding_Default_No_Compression
	sms.Class = 1
	return sm.sendSMS(&sms, number, report)
}

func (sm *StateMachine) SendLongSMS(number, text string, report bool) error {
	// Fill in SMS info
	var smsInfo C.GSM_MultiPartSMSInfo
	C.GSM_ClearMultiPartSMSInfo(&smsInfo)
	smsInfo.Class = 1
	smsInfo.EntriesNum = 1
	smsInfo.UnicodeCoding = C.FALSE
	// Check for non-ASCII rune
	for _, r := range text {
		if r > 0x7F {
			smsInfo.UnicodeCoding = C.TRUE
			break
		}
	}
	smsInfo.Entries[0].ID = C.SMS_ConcatenatedTextLong
	msgUnicode := (*C.uchar)(C.calloc(C.size_t(len(text)+1), 2))
	defer C.free(unsafe.Pointer(msgUnicode))
	decodeUTF8(msgUnicode, text)
	smsInfo.Entries[0].Buffer = msgUnicode
	// Prepare multipart message
	var msms C.GSM_MultiSMSMessage
	if e := C.GSM_EncodeMultiPartSMS(nil, &smsInfo, &msms); e != C.ERR_NONE {
		return EncodeError{e}
	}
	// Send message
	for i := 0; i < int(msms.Number); i++ {
		if e := sm.sendSMS(&msms.SMS[i], number, report); e != nil {
			return e
		}
	}
	return nil
}

func encodeUTF8(in *C.uchar) string {
	l := C.UnicodeLength(in)
	if l == 0 {
		return ""
	}
	out := make([]C.char, C.UnicodeLength(in)*2)
	C.EncodeUTF8(&out[0], in)
	return C.GoString(&out[0])
}

func goTime(t *C.GSM_DateTime) time.Time {
	return time.Date(
		int(t.Year), time.Month(t.Month), int(t.Day),
		int(t.Hour), int(t.Minute), int(t.Second), 0,
		time.UTC,
	).Add(-time.Second * time.Duration(t.Timezone)).Local()
}

type SMS struct {
	Time     time.Time
	SMSCTime time.Time
	Number   string
	Report   bool // True if this message is a delivery report
	Body     string
}

// Read and deletes first avaliable message.
// Returns io.EOF if there is no more messages to read
func (sm *StateMachine) GetSMS() (sms SMS, err error) {
	var msms C.GSM_MultiSMSMessage
	if e := C.GSM_GetNextSMS(sm.g, &msms, C.TRUE); e != C.ERR_NONE {
		if e == C.ERR_EMPTY {
			err = io.EOF
		} else {
			err = Error{"GetNextSMS", e}
		}
		return
	}
	s := msms.SMS[msms.Number-1]
	sms.Number = encodeUTF8(&s.Number[0])
	sms.Time = goTime(&s.DateTime)
	sms.SMSCTime = goTime(&s.SMSCTime)

	for i := 0; i < int(msms.Number); i++ {
		s = msms.SMS[i]
		if s.Coding == C.SMS_Coding_8bit {
			continue
		}
		sms.Body += encodeUTF8(&s.Text[0])
		if s.PDU == C.SMS_Status_Report {
			sms.Report = true
		}
		s.Folder = 0 // Flat
		if e := C.GSM_DeleteSMS(sm.g, &s); e != C.ERR_NONE {
			err = Error{"DeleteSMS", e}
			return
		}
	}
	return
}
<|endoftext|>


<commit_before>package api

import "testing"
import "net/http/httptest"
import "fmt"
import "net/http"
import "io/ioutil"
import . "music"
import "encoding/json"

var (
  server *httptest.Server
)

func init() {
  server = httptest.NewServer(Handlers())
}

func TestJson(t *testing.T) {
  url := fmt.Sprintf("%s/search/x", server.URL)
  resp, err := http.Get(url)

  if err != nil {
    panic(err.Error())
  }

  body, err := ioutil.ReadAll(resp.Body)

  if err != nil {
    panic(err.Error())
  }

  var data Results
  jerr := json.Unmarshal(body, &data)

  if jerr != nil {
    t.Error(jerr)
  }

  t.Error("This should fail!")
}
<commit_msg>Revert "make test fail"<commit_after>package api

import "testing"
import "net/http/httptest"
import "fmt"
import "net/http"
import "io/ioutil"
import . "music"
import "encoding/json"

var (
  server *httptest.Server
)

func init() {
  server = httptest.NewServer(Handlers())
}

func TestJson(t *testing.T) {
  url := fmt.Sprintf("%s/search/x", server.URL)
  resp, err := http.Get(url)

  if err != nil {
    panic(err.Error())
  }

  body, err := ioutil.ReadAll(resp.Body)

  if err != nil {
    panic(err.Error())
  }

  var data Results
  jerr := json.Unmarshal(body, &data)

  if jerr != nil {
    t.Error(jerr)
  }

}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

var account = make(map[string]int)

var logger = shim.NewLogger("ftLogger")

// SampleChaincode struct required to implement the shim.Chaincode interface
type SampleChaincode struct {
}

// Init method is called when the chaincode is first deployed onto the blockchain network
func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var customerName string // Name of the customer
	var currentBalance int  // Current account balance of the customer
	var err error

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

	// Initialize the chaincode
	customerName = args[0]
	currentBalance, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for customer account balance: " + err.Error())
	}

	logger.Infof("Customer: %s, Available Balance: %d", customerName, currentBalance)

	// Save the Customer info
	account[customerName] = currentBalance

	return nil, nil
}

// Query method is invoked whenever any read/get/query operation needs to be performed on the blockchain state.
func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Query is running: " + function)

	// Handle different functions
	if function == "GetAccountBalance" { //read a variable
		return t.getAccountBalance(stub, args)
	}
	logger.Error("Query did not find func: " + function)

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

// Invoke method is invoked whenever the state of the blockchain is to be modified.
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Invoke is running: " + function)

	// Handle different functions
	switch function {
	case "Init":
		return t.Init(stub, "init", args)
	case "Deposit":
		return t.depositFund(stub, args)
	case "Withdraw":
		return t.withdrawFund(stub, args)
	case "Settlement":
		return t.eodSettlement(stub, args)
	default:
		logger.Error("Invoke did not find func: " + function)
	}

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

func (t *SampleChaincode) getAccountBalance(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running getAccountBalance")
	var name string

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

	name = args[0]

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) depositFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running depositFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

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

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for deposit amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]
	newBalance = value + currentBalance

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) withdrawFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running withdrawFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

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

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for withdraw amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]

	if value > currentBalance {
		jsonResp = "{\"Error\":\"Insufficient Fund in account. Aborting...\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	newBalance = currentBalance - value

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) eodSettlement(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running eodSettlement")

	var err error
	var response []byte
	var jsonResp string

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

	f := "Settlement"

	chaincodeURL := args[0] //https://github.com/sauravhaloi/chaincode/issuer

	queryArgs := util.ToChaincodeArgs(f)

	fmt.Println("Query Args: ", queryArgs)

	response, err = stub.InvokeChaincode(chaincodeURL, queryArgs)
	if err != nil {
		errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", err.Error())
		jsonResp = "{\"Error\":\"" + errStr + "\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	logger.Infof("Response: %s", f, string(response))

	/*

		dueAsBytes, err := stub.GetState("IBI->ABI")
		if err != nil {
			logger.Error(err)
			return nil, errors.New("Failed to get state" + err.Error())
		}

		if dueAsBytes == nil {
			logger.Info("IBI does not owe any dues to ABI")
			return nil, nil
		}

		logger.Infof("IBI owes %s to ABI", string(dueAsBytes))

		logger.Info("IBI pays back to ABI all dues, commit it in the ledger")
		err = stub.PutState("IBI->ABI", dueAsBytes)
		if err != nil {
			logger.Error(err)
			return nil, err
		}

	*/

	logger.Info("EOD Settlement Done!")

	return nil, err
}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SampleChaincode))
	if err != nil {
		fmt.Println("Could not start SampleChaincode")
	} else {
		fmt.Println("SampleChaincode successfully started")
	}
}
<commit_msg>fix a bug<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

var account = make(map[string]int)

var logger = shim.NewLogger("ftLogger")

// SampleChaincode struct required to implement the shim.Chaincode interface
type SampleChaincode struct {
}

// Init method is called when the chaincode is first deployed onto the blockchain network
func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var customerName string // Name of the customer
	var currentBalance int  // Current account balance of the customer
	var err error

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

	// Initialize the chaincode
	customerName = args[0]
	currentBalance, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for customer account balance: " + err.Error())
	}

	logger.Infof("Customer: %s, Available Balance: %d", customerName, currentBalance)

	// Save the Customer info
	account[customerName] = currentBalance

	return nil, nil
}

// Query method is invoked whenever any read/get/query operation needs to be performed on the blockchain state.
func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Query is running: " + function)

	// Handle different functions
	if function == "GetAccountBalance" { //read a variable
		return t.getAccountBalance(stub, args)
	}
	logger.Error("Query did not find func: " + function)

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

// Invoke method is invoked whenever the state of the blockchain is to be modified.
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Invoke is running: " + function)

	// Handle different functions
	switch function {
	case "Init":
		return t.Init(stub, "init", args)
	case "Deposit":
		return t.depositFund(stub, args)
	case "Withdraw":
		return t.withdrawFund(stub, args)
	case "Settlement":
		return t.eodSettlement(stub, args)
	default:
		logger.Error("Invoke did not find func: " + function)
	}

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

func (t *SampleChaincode) getAccountBalance(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running getAccountBalance")
	var name string

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

	name = args[0]

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) depositFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running depositFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

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

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for deposit amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]
	newBalance = value + currentBalance

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) withdrawFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running withdrawFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

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

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for withdraw amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]

	if value > currentBalance {
		jsonResp = "{\"Error\":\"Insufficient Fund in account. Aborting...\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	newBalance = currentBalance - value

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) eodSettlement(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running eodSettlement")

	var err error
	var response []byte
	var jsonResp string

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

	chaincodeURL := args[0] //https://github.com/sauravhaloi/chaincode/issuer
	operation := args[1]
	customer := args[2]

	queryArgs := util.ToChaincodeArgs(operation, customer)

	fmt.Println("Query Args: ", queryArgs)

	response, err = stub.InvokeChaincode(chaincodeURL, queryArgs)
	if err != nil {
		errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", err.Error())
		jsonResp = "{\"Error\":\"" + errStr + "\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	logger.Infof("Response: %s", operation, string(response))

	/*

		dueAsBytes, err := stub.GetState("IBI->ABI")
		if err != nil {
			logger.Error(err)
			return nil, errors.New("Failed to get state" + err.Error())
		}

		if dueAsBytes == nil {
			logger.Info("IBI does not owe any dues to ABI")
			return nil, nil
		}

		logger.Infof("IBI owes %s to ABI", string(dueAsBytes))

		logger.Info("IBI pays back to ABI all dues, commit it in the ledger")
		err = stub.PutState("IBI->ABI", dueAsBytes)
		if err != nil {
			logger.Error(err)
			return nil, err
		}

	*/

	logger.Info("EOD Settlement Done!")

	return nil, err
}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SampleChaincode))
	if err != nil {
		fmt.Println("Could not start SampleChaincode")
	} else {
		fmt.Println("SampleChaincode successfully started")
	}
}
<|endoftext|>


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

package isvcs

import (
	"github.com/Sirupsen/logrus"
	"github.com/control-center/serviced/dfs/docker"
	"github.com/control-center/serviced/domain"
	"github.com/control-center/serviced/logging"
	"github.com/control-center/serviced/utils"

	"time"
)

var (
	Mgr *Manager
	log = logging.PackageLogger()
)

const (
	IMAGE_REPO    = "zenoss/serviced-isvcs"
	IMAGE_TAG     = "v50"
	ZK_IMAGE_REPO = "zenoss/isvcs-zookeeper"
	ZK_IMAGE_TAG  = "v7"
)

type IServiceHealthResult struct {
	ServiceName    string
	ContainerName  string
	ContainerID    string
	HealthStatuses []domain.HealthCheckStatus
}

func Init(esStartupTimeoutInSeconds int, dockerLogDriver string, dockerLogConfig map[string]string, dockerAPI docker.Docker) {
	elasticsearch_serviced.StartupTimeout = time.Duration(esStartupTimeoutInSeconds) * time.Second
	elasticsearch_logstash.StartupTimeout = time.Duration(esStartupTimeoutInSeconds) * time.Second

	Mgr = NewManager(utils.LocalDir("images"), utils.TempDir("var/isvcs"), dockerLogDriver, dockerLogConfig)

	elasticsearch_serviced.docker = dockerAPI
	if err := Mgr.Register(elasticsearch_serviced); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "elasticsearch-serviced",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	elasticsearch_logstash.docker = dockerAPI
	if err := Mgr.Register(elasticsearch_logstash); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "elasticsearch-logstash",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	zookeeper.docker = dockerAPI
	if err := Mgr.Register(zookeeper); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "zookeeper",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	logstash.docker = dockerAPI
	if err := Mgr.Register(logstash); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "logstash",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	opentsdb.docker = dockerAPI
	if err := Mgr.Register(opentsdb); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "opentsdb",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	dockerRegistry.docker = dockerAPI
	if err := Mgr.Register(dockerRegistry); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "docker-registry",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	kibana.docker = dockerAPI
	if err := Mgr.Register(kibana); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "kibana",
		}).WithError(err).Fatal("Unable to register internal service")
	}
}

func InitServices(isvcNames []string, dockerLogDriver string, dockerLogConfig map[string]string, dockerAPI docker.Docker) {
	Mgr = NewManager(utils.LocalDir("images"), utils.TempDir("var/isvcs"), dockerLogDriver, dockerLogConfig)
	for _, isvcName := range isvcNames {
		switch isvcName {
		case "zookeeper":
			zookeeper.docker = dockerAPI
			if err := Mgr.Register(zookeeper); err != nil {
				log.WithFields(logrus.Fields{
					"isvc": "zookeeper",
				}).WithError(err).Fatal("Unable to register internal service")
			}
		}
	}
}
<commit_msg>bumped isvcs zookeeper version<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package isvcs

import (
	"github.com/Sirupsen/logrus"
	"github.com/control-center/serviced/dfs/docker"
	"github.com/control-center/serviced/domain"
	"github.com/control-center/serviced/logging"
	"github.com/control-center/serviced/utils"

	"time"
)

var (
	Mgr *Manager
	log = logging.PackageLogger()
)

const (
	IMAGE_REPO    = "zenoss/serviced-isvcs"
	IMAGE_TAG     = "v50"
	ZK_IMAGE_REPO = "zenoss/isvcs-zookeeper"
	ZK_IMAGE_TAG  = "v8"
)

type IServiceHealthResult struct {
	ServiceName    string
	ContainerName  string
	ContainerID    string
	HealthStatuses []domain.HealthCheckStatus
}

func Init(esStartupTimeoutInSeconds int, dockerLogDriver string, dockerLogConfig map[string]string, dockerAPI docker.Docker) {
	elasticsearch_serviced.StartupTimeout = time.Duration(esStartupTimeoutInSeconds) * time.Second
	elasticsearch_logstash.StartupTimeout = time.Duration(esStartupTimeoutInSeconds) * time.Second

	Mgr = NewManager(utils.LocalDir("images"), utils.TempDir("var/isvcs"), dockerLogDriver, dockerLogConfig)

	elasticsearch_serviced.docker = dockerAPI
	if err := Mgr.Register(elasticsearch_serviced); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "elasticsearch-serviced",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	elasticsearch_logstash.docker = dockerAPI
	if err := Mgr.Register(elasticsearch_logstash); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "elasticsearch-logstash",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	zookeeper.docker = dockerAPI
	if err := Mgr.Register(zookeeper); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "zookeeper",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	logstash.docker = dockerAPI
	if err := Mgr.Register(logstash); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "logstash",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	opentsdb.docker = dockerAPI
	if err := Mgr.Register(opentsdb); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "opentsdb",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	dockerRegistry.docker = dockerAPI
	if err := Mgr.Register(dockerRegistry); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "docker-registry",
		}).WithError(err).Fatal("Unable to register internal service")
	}
	kibana.docker = dockerAPI
	if err := Mgr.Register(kibana); err != nil {
		log.WithFields(logrus.Fields{
			"isvc": "kibana",
		}).WithError(err).Fatal("Unable to register internal service")
	}
}

func InitServices(isvcNames []string, dockerLogDriver string, dockerLogConfig map[string]string, dockerAPI docker.Docker) {
	Mgr = NewManager(utils.LocalDir("images"), utils.TempDir("var/isvcs"), dockerLogDriver, dockerLogConfig)
	for _, isvcName := range isvcNames {
		switch isvcName {
		case "zookeeper":
			zookeeper.docker = dockerAPI
			if err := Mgr.Register(zookeeper); err != nil {
				log.WithFields(logrus.Fields{
					"isvc": "zookeeper",
				}).WithError(err).Fatal("Unable to register internal service")
			}
		}
	}
}
<|endoftext|>


<commit_before>package configuration

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"log"
)

var logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)

/*
	Service configuration struct
*/
type Configuration struct {
	// Marathon configuration
	Marathon Marathon

	// Bamboo specific configuration
	Bamboo Bamboo

	// HAProxy output configuration
	HAProxy HAProxy

	// StatsD configuration
	StatsD StatsD
}

/*
	Returns Configuration struct from a given file path

	Parameters:
		filePath: full file path to the JSON configuration
*/
func (config *Configuration) FromFile(filePath string) error {
	content, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err)
	}
	return json.Unmarshal(content, &config)
}

func FromFile(filePath string) (Configuration, error) {
	conf := &Configuration{}
	err := conf.FromFile(filePath)
	setValueFromEnv(&conf.Marathon.Zookeeper.Host, "MARATHON_ZK_HOST")
	setValueFromEnv(&conf.Marathon.Zookeeper.Path, "MARATHON_ZK_PATH")
	setValueFromEnv(&conf.Marathon.Endpoint, "MARATHON_ENDPOINT")

	setValueFromEnv(&conf.Bamboo.Host, "BAMBOO_HOST")
	setValueFromEnv(&conf.Bamboo.Zookeeper.Host, "BAMBOO_ZK_HOST")
	setValueFromEnv(&conf.Bamboo.Zookeeper.Path, "DOMAIN_ZK_PATH")

	setValueFromEnv(&conf.HAProxy.TemplatePath, "HAPROXY_TEMPLATE_PATH")
	setValueFromEnv(&conf.HAProxy.OutputPath, "HAPROXY_OUTPUT_PATH")
	setValueFromEnv(&conf.HAProxy.ReloadCommand, "HAPROXY_RELOAD_CMD")
	return *conf, err
}

func setValueFromEnv(field *string, envVar string) {
	env := os.Getenv(envVar)
	if len(env) > 0 {
		log.Printf("Using environment override %s=%s", envVar, env)
		*field = env
	}
}
<commit_msg>Fix environment variable naming<commit_after>package configuration

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"os"
)

var logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)

/*
	Service configuration struct
*/
type Configuration struct {
	// Marathon configuration
	Marathon Marathon

	// Bamboo specific configuration
	Bamboo Bamboo

	// HAProxy output configuration
	HAProxy HAProxy

	// StatsD configuration
	StatsD StatsD
}

/*
	Returns Configuration struct from a given file path

	Parameters:
		filePath: full file path to the JSON configuration
*/
func (config *Configuration) FromFile(filePath string) error {
	content, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err)
	}
	return json.Unmarshal(content, &config)
}

func FromFile(filePath string) (Configuration, error) {
	conf := &Configuration{}
	err := conf.FromFile(filePath)
	setValueFromEnv(&conf.Marathon.Zookeeper.Host, "MARATHON_ZK_HOST")
	setValueFromEnv(&conf.Marathon.Zookeeper.Path, "MARATHON_ZK_PATH")
	setValueFromEnv(&conf.Marathon.Endpoint, "MARATHON_ENDPOINT")

	setValueFromEnv(&conf.Bamboo.Host, "BAMBOO_HOST")
	setValueFromEnv(&conf.Bamboo.Zookeeper.Host, "BAMBOO_ZK_HOST")
	setValueFromEnv(&conf.Bamboo.Zookeeper.Path, "BAMBOO_ZK_PATH")

	setValueFromEnv(&conf.HAProxy.TemplatePath, "HAPROXY_TEMPLATE_PATH")
	setValueFromEnv(&conf.HAProxy.OutputPath, "HAPROXY_OUTPUT_PATH")
	setValueFromEnv(&conf.HAProxy.ReloadCommand, "HAPROXY_RELOAD_CMD")
	return *conf, err
}

func setValueFromEnv(field *string, envVar string) {
	env := os.Getenv(envVar)
	if len(env) > 0 {
		log.Printf("Using environment override %s=%s", envVar, env)
		*field = env
	}
}
<|endoftext|>


<commit_before>package utils

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

// Returns an AQL body string to search file in Artifactory according the the specified arguments requirements.
func createAqlBodyForItem(params *ArtifactoryCommonParams) (string, error) {
	var itemType string
	if params.IncludeDirs {
		itemType = "any"
	}
	searchPattern := prepareSearchPattern(params.Pattern, true)
	repoIndex := strings.Index(searchPattern, "/")

	repo := searchPattern[:repoIndex]
	searchPattern = searchPattern[repoIndex+1:]

	pathFilePairs := createPathFilePairs(searchPattern, params.Recursive)
	includeRoot := strings.LastIndex(searchPattern, "/") < 0
	pathPairsSize := len(pathFilePairs)
	propsQuery, err := buildPropsQuery(params.Props)
	if err != nil {
		return "", err
	}
	itemTypeQuery := buildItemTypeQuery(itemType)
	nePath := buildNePath(pathPairsSize == 0 || includeRoot)
	excludeQuery := createExcludeQuery(params.ExcludePatterns, pathPairsSize == 0 || params.Recursive)

	json := `{"repo": "` + repo + `",` + propsQuery + itemTypeQuery + nePath + excludeQuery + `"$or": [`
	if pathPairsSize == 0 {
		json += buildInnerQuery(".", searchPattern)
	} else {
		for i := 0; i < pathPairsSize; i++ {
			json += buildInnerQuery(pathFilePairs[i].path, pathFilePairs[i].file)
			if i+1 < pathPairsSize {
				json += ","
			}
		}
	}
	json += "]}"
	return json, nil
}

func createAqlQueryForBuild(buildName, buildNumber string) string {
	return "items.find(" +
			"{\"$and\": [" +
				"{\"artifact.module.build.name\": {\"$eq\": \"" + buildName + "\"}}," +
				"{\"artifact.module.build.number\": {\"$eq\": \"" + buildNumber + "\"}}" +
			"]}).include(\"name\",\"repo\",\"path\",\"actual_sha1\")"
}

func prepareSearchPattern(pattern string, repositoryExists bool) string {
	if repositoryExists && !strings.Contains(pattern, "/") {
		pattern += "/"
	}
	if strings.HasSuffix(pattern, "/") {
		pattern += "*"
	}

	// Remove parenthesis
	pattern = strings.Replace(pattern, "(", "", -1)
	pattern = strings.Replace(pattern, ")", "", -1)
	return pattern
}

func buildPropsQuery(props string) (string, error) {
	if props == "" {
		return "", nil
	}
	propList := strings.Split(props, ";")
	query := ""
	for _, prop := range propList {
		key, value, err := SplitProp(prop)
		if err != nil {
			return "", err
		}
		query += "\"@" + key + "\": {\"$match\" : \"" + value + "\"},"
	}
	return query, nil
}

func buildItemTypeQuery(itemType string) string {
	if itemType != "" {
		return `"type": {"$eq": "` + itemType + `"},`
	}
	return ""
}

func buildNePath(includeRoot bool) string {
	if !includeRoot {
		return `"path": {"$ne": "."},`
	}
	return ""
}

func buildInnerQuery(path, name string) string {
	innerQueryPattern := `{"$and":` +
							`[{` +
								`"path": {"$match": "%s"},` +
								`"name": {"$match": "%s"}` +
							`}]}`
	return fmt.Sprintf(innerQueryPattern, path, name)
}

func createExcludeQuery(excludePatterns []string, useLocalPath bool) string {
	if excludePatterns == nil {
		return ""
	}
	excludeQuery := ""
	var excludePairs []PathFilePair
	for _, excludePattern := range excludePatterns {
		excludePairs = append(excludePairs, createPathFilePairs(prepareSearchPattern(excludePattern, false), useLocalPath)...)
	}

	for _, excludePair := range excludePairs {
		excludePath := excludePair.path
		if excludePath == "." {
			excludePath = "*"
		}
		excludeQuery += fmt.Sprintf(`"$or": [{"path": {"$nmatch": "%s"}, "name": {"$nmatch": "%s"}}],`, excludePath, excludePair.file)
	}
	return excludeQuery
}

// We need to translate the provided download pattern to an AQL query.
// In Artifactory, for each artifact the name and path of the artifact are saved separately including folders.
// We therefore need to build an AQL query that covers all possible folders the provided
// pattern can include.
// For example, the pattern a/*b*c*/ can include the two following folders:
// a/b/c, a/bc/, a/x/y/z/b/c/
// To achieve that, this function parses the pattern by splitting it by its * characters.
// The end result is a list of PathFilePair structs.
// Each struct represent a possible path and folder name pair to be included in AQL query with an "or" relationship.
func createPathFolderPairs(searchPattern string) []PathFilePair {
	// Remove parenthesis
	searchPattern = searchPattern[:len(searchPattern) - 1]
	searchPattern = strings.Replace(searchPattern, "(", "", -1)
	searchPattern = strings.Replace(searchPattern, ")", "", -1)

	index := strings.Index(searchPattern, "/")
	searchPattern = searchPattern[index + 1:]

	index = strings.LastIndex(searchPattern, "/")
	lastSlashPath := searchPattern
	path := "."
	if index != -1 {
		lastSlashPath = searchPattern[index + 1:]
		path = searchPattern[:index]
	}

	pairs := []PathFilePair{{path:path, file:lastSlashPath}}
	for i := 0; i < len(lastSlashPath); i++ {
		if string(lastSlashPath[i]) == "*" {
			pairs = append(pairs, PathFilePair{path:filepath.Join(path, lastSlashPath[:i + 1]), file:lastSlashPath[i:]})
		}
	}
	return pairs
}

// We need to translate the provided download pattern to an AQL query.
// In Artifactory, for each artifact the name and path of the artifact are saved separately.
// We therefore need to build an AQL query that covers all possible paths and names the provided
// pattern can include.
// For example, the pattern a/* can include the two following file:
// a/file1.tgz and also a/b/file2.tgz
// To achieve that, this function parses the pattern by splitting it by its * characters.
// The end result is a list of PathFilePair structs.
// Each struct represent a possible path and file name pair to be included in AQL query with an "or" relationship.
func createPathFilePairs(pattern string, recursive bool) []PathFilePair {
	var defaultPath string
	if recursive {
		defaultPath = "*"
	} else {
		defaultPath = "."
	}

	pairs := []PathFilePair{}
	if pattern == "*" {
		pairs = append(pairs, PathFilePair{defaultPath, "*"})
		return pairs
	}

	slashIndex := strings.LastIndex(pattern, "/")
	var path string
	var name string
	if slashIndex < 0 {
		pairs = append(pairs, PathFilePair{".", pattern})
		path = ""
		name = pattern
	} else {
		path = pattern[:slashIndex]
		name = pattern[slashIndex+1:]
		pairs = append(pairs, PathFilePair{path, name})
	}
	if !recursive {
		return pairs
	}
	if name == "*" {
		path += "/*"
		pairs = append(pairs, PathFilePair{path, "*"})
		return pairs
	}
	pattern = name

	sections := strings.Split(pattern, "*")
	size := len(sections)
	for i := 0; i < size; i++ {
		options := []string{}
		if i + 1 < size {
			options = append(options, sections[i] + "*/")
		}
		for _, option := range options {
			str := ""
			for j := 0; j < size; j++ {
				if j > 0 {
					str += "*"
				}
				if j == i {
					str += option
				} else {
					str += sections[j]
				}
			}
			split := strings.Split(str, "/")
			filePath := split[0]
			fileName := split[1]
			if fileName == "" {
				fileName = "*"
			}
			if path != "" {
				if !strings.HasSuffix(path, "/") {
					path += "/"
				}
			}
			pairs = append(pairs, PathFilePair{path + filePath, fileName})
		}
	}
	return pairs
}

type PathFilePair struct {
	path string
	file string
}<commit_msg>Support pattern exclusion<commit_after>package utils

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

// Returns an AQL body string to search file in Artifactory according the the specified arguments requirements.
func createAqlBodyForItem(params *ArtifactoryCommonParams) (string, error) {
	var itemType string
	if params.IncludeDirs {
		itemType = "any"
	}
	searchPattern := prepareSearchPattern(params.Pattern, true)
	repoIndex := strings.Index(searchPattern, "/")

	repo := searchPattern[:repoIndex]
	searchPattern = searchPattern[repoIndex+1:]

	pathFilePairs := createPathFilePairs(searchPattern, params.Recursive)
	includeRoot := strings.LastIndex(searchPattern, "/") < 0
	pathPairsSize := len(pathFilePairs)
	propsQuery, err := buildPropsQuery(params.Props)
	if err != nil {
		return "", err
	}
	itemTypeQuery := buildItemTypeQuery(itemType)
	nePath := buildNePath(pathPairsSize == 0 || includeRoot)
	excludeQuery := createExcludeQuery(params.ExcludePatterns, pathPairsSize == 0 || params.Recursive, params.Recursive)

	json := `{"repo": "` + repo + `",` + propsQuery + itemTypeQuery + nePath + excludeQuery + `"$or": [`
	if pathPairsSize == 0 {
		json += buildInnerQuery(".", searchPattern)
	} else {
		for i := 0; i < pathPairsSize; i++ {
			json += buildInnerQuery(pathFilePairs[i].path, pathFilePairs[i].file)
			if i+1 < pathPairsSize {
				json += ","
			}
		}
	}
	json += "]}"
	return json, nil
}

func createAqlQueryForBuild(buildName, buildNumber string) string {
	return "items.find(" +
			"{\"$and\": [" +
				"{\"artifact.module.build.name\": {\"$eq\": \"" + buildName + "\"}}," +
				"{\"artifact.module.build.number\": {\"$eq\": \"" + buildNumber + "\"}}" +
			"]}).include(\"name\",\"repo\",\"path\",\"actual_sha1\")"
}

func prepareSearchPattern(pattern string, repositoryExists bool) string {
	if repositoryExists && !strings.Contains(pattern, "/") {
		pattern += "/"
	}
	if strings.HasSuffix(pattern, "/") {
		pattern += "*"
	}

	// Remove parenthesis
	pattern = strings.Replace(pattern, "(", "", -1)
	pattern = strings.Replace(pattern, ")", "", -1)
	return pattern
}

func buildPropsQuery(props string) (string, error) {
	if props == "" {
		return "", nil
	}
	propList := strings.Split(props, ";")
	query := ""
	for _, prop := range propList {
		key, value, err := SplitProp(prop)
		if err != nil {
			return "", err
		}
		query += "\"@" + key + "\": {\"$match\" : \"" + value + "\"},"
	}
	return query, nil
}

func buildItemTypeQuery(itemType string) string {
	if itemType != "" {
		return `"type": {"$eq": "` + itemType + `"},`
	}
	return ""
}

func buildNePath(includeRoot bool) string {
	if !includeRoot {
		return `"path": {"$ne": "."},`
	}
	return ""
}

func buildInnerQuery(path, name string) string {
	innerQueryPattern := `{"$and":` +
							`[{` +
								`"path": {"$match": "%s"},` +
								`"name": {"$match": "%s"}` +
							`}]}`
	return fmt.Sprintf(innerQueryPattern, path, name)
}

func createExcludeQuery(excludePatterns []string, useLocalPath, recursive bool) string {
	if excludePatterns == nil {
		return ""
	}
	excludeQuery := ""
	var excludePairs []PathFilePair
	for _, excludePattern := range excludePatterns {
		excludePairs = append(excludePairs, createPathFilePairs(prepareSearchPattern(excludePattern, false), recursive)...)
	}

	for _, excludePair := range excludePairs {
		excludePath := excludePair.path
		if !useLocalPath && excludePath == "." {
			excludePath = "*"
		}
		excludeQuery += fmt.Sprintf(`"$or": [{"path": {"$nmatch": "%s"}, "name": {"$nmatch": "%s"}}],`, excludePath, excludePair.file)
	}
	return excludeQuery
}

// We need to translate the provided download pattern to an AQL query.
// In Artifactory, for each artifact the name and path of the artifact are saved separately including folders.
// We therefore need to build an AQL query that covers all possible folders the provided
// pattern can include.
// For example, the pattern a/*b*c*/ can include the two following folders:
// a/b/c, a/bc/, a/x/y/z/b/c/
// To achieve that, this function parses the pattern by splitting it by its * characters.
// The end result is a list of PathFilePair structs.
// Each struct represent a possible path and folder name pair to be included in AQL query with an "or" relationship.
func createPathFolderPairs(searchPattern string) []PathFilePair {
	// Remove parenthesis
	searchPattern = searchPattern[:len(searchPattern) - 1]
	searchPattern = strings.Replace(searchPattern, "(", "", -1)
	searchPattern = strings.Replace(searchPattern, ")", "", -1)

	index := strings.Index(searchPattern, "/")
	searchPattern = searchPattern[index + 1:]

	index = strings.LastIndex(searchPattern, "/")
	lastSlashPath := searchPattern
	path := "."
	if index != -1 {
		lastSlashPath = searchPattern[index + 1:]
		path = searchPattern[:index]
	}

	pairs := []PathFilePair{{path:path, file:lastSlashPath}}
	for i := 0; i < len(lastSlashPath); i++ {
		if string(lastSlashPath[i]) == "*" {
			pairs = append(pairs, PathFilePair{path:filepath.Join(path, lastSlashPath[:i + 1]), file:lastSlashPath[i:]})
		}
	}
	return pairs
}

// We need to translate the provided download pattern to an AQL query.
// In Artifactory, for each artifact the name and path of the artifact are saved separately.
// We therefore need to build an AQL query that covers all possible paths and names the provided
// pattern can include.
// For example, the pattern a/* can include the two following file:
// a/file1.tgz and also a/b/file2.tgz
// To achieve that, this function parses the pattern by splitting it by its * characters.
// The end result is a list of PathFilePair structs.
// Each struct represent a possible path and file name pair to be included in AQL query with an "or" relationship.
func createPathFilePairs(pattern string, recursive bool) []PathFilePair {
	var defaultPath string
	if recursive {
		defaultPath = "*"
	} else {
		defaultPath = "."
	}

	pairs := []PathFilePair{}
	if pattern == "*" {
		pairs = append(pairs, PathFilePair{defaultPath, "*"})
		return pairs
	}

	slashIndex := strings.LastIndex(pattern, "/")
	var path string
	var name string
	if slashIndex < 0 {
		pairs = append(pairs, PathFilePair{".", pattern})
		path = ""
		name = pattern
	} else {
		path = pattern[:slashIndex]
		name = pattern[slashIndex+1:]
		pairs = append(pairs, PathFilePair{path, name})
	}
	if !recursive {
		return pairs
	}
	if name == "*" {
		path += "/*"
		pairs = append(pairs, PathFilePair{path, "*"})
		return pairs
	}
	pattern = name

	sections := strings.Split(pattern, "*")
	size := len(sections)
	for i := 0; i < size; i++ {
		options := []string{}
		if i + 1 < size {
			options = append(options, sections[i] + "*/")
		}
		for _, option := range options {
			str := ""
			for j := 0; j < size; j++ {
				if j > 0 {
					str += "*"
				}
				if j == i {
					str += option
				} else {
					str += sections[j]
				}
			}
			split := strings.Split(str, "/")
			filePath := split[0]
			fileName := split[1]
			if fileName == "" {
				fileName = "*"
			}
			if path != "" {
				if !strings.HasSuffix(path, "/") {
					path += "/"
				}
			}
			pairs = append(pairs, PathFilePair{path + filePath, fileName})
		}
	}
	return pairs
}

type PathFilePair struct {
	path string
	file string
}<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package lxc

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	"launchpad.net/golxc"

	coreCloudinit "launchpad.net/juju-core/cloudinit"
	"launchpad.net/juju-core/container"
	"launchpad.net/juju-core/environs/cloudinit"
	"launchpad.net/juju-core/juju/osenv"
	"launchpad.net/juju-core/utils"
	"launchpad.net/juju-core/utils/fslock"
	"launchpad.net/juju-core/utils/tailer"
)

const (
	templateShutdownUpstartFilename = "/etc/init/juju-template-restart.conf"
	templateShutdownUpstartScript   = `
description "Juju lxc template shutdown job"
author "Juju Team <juju@lists.ubuntu.com>"
start on stopped cloud-final

script
  shutdown -h now
end script

post-stop script
  rm ` + templateShutdownUpstartFilename + `
end script
`
)

var (
	TemplateLockDir = "/var/lib/juju/locks"

	TemplateStopTimeout = 5 * time.Minute
)

// templateUserData returns a minimal user data necessary for the template.
// This should have the authorized keys, base packages, the cloud archive if
// necessary,  initial apt proxy config, and it should do the apt-get
// update/upgrade initially.
func templateUserData(
	series string,
	authorizedKeys string,
	aptProxy osenv.ProxySettings,
) ([]byte, error) {
	config := coreCloudinit.New()
	config.AddScripts(
		"set -xe", // ensure we run all the scripts or abort.
	)
	config.AddSSHAuthorizedKeys(authorizedKeys)
	cloudinit.MaybeAddCloudArchiveCloudTools(config, series)
	cloudinit.AddAptCommands(aptProxy, config)
	config.AddScripts(
		fmt.Sprintf(
			"printf '%%s\n' %s > %s",
			utils.ShQuote(templateShutdownUpstartScript),
			templateShutdownUpstartFilename,
		))
	data, err := config.Render()
	if err != nil {
		return nil, err
	}
	return data, nil
}

func AcquireTemplateLock(name, message string) (*fslock.Lock, error) {
	logger.Infof("wait for fslock on %v", name)
	lock, err := fslock.NewLock(TemplateLockDir, name)
	if err != nil {
		logger.Tracef("failed to create fslock for template: %v", err)
		return nil, err
	}
	err = lock.Lock(message)
	if err != nil {
		logger.Tracef("failed to acquire lock for template: %v", err)
		return nil, err
	}
	return lock, nil
}

// Make sure a template exists that we can clone from.
func EnsureCloneTemplate(
	backingFilesystem string,
	series string,
	network *container.NetworkConfig,
	authorizedKeys string,
	aptProxy osenv.ProxySettings,
) (golxc.Container, error) {
	name := fmt.Sprintf("juju-%s-template", series)
	containerDirectory, err := container.NewDirectory(name)
	if err != nil {
		return nil, err
	}

	lock, err := AcquireTemplateLock(name, "ensure clone exists")
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	lxcContainer := LxcObjectFactory.New(name)
	// Early exit if the container has been constructed before.
	if lxcContainer.IsConstructed() {
		logger.Infof("template exists, continuing")
		return lxcContainer, nil
	}
	logger.Infof("template does not exist, creating")

	userData, err := templateUserData(series, authorizedKeys, aptProxy)
	if err != nil {
		logger.Tracef("filed to create tempalte user data for template: %v", err)
		return nil, err
	}
	userDataFilename, err := container.WriteCloudInitFile(containerDirectory, userData)
	if err != nil {
		return nil, err
	}

	configFile, err := writeLxcConfig(network, containerDirectory)
	if err != nil {
		logger.Errorf("failed to write config file: %v", err)
		return nil, err
	}
	templateParams := []string{
		"--debug",                      // Debug errors in the cloud image
		"--userdata", userDataFilename, // Our groovey cloud-init
		"--hostid", name, // Use the container name as the hostid
		"-r", series,
	}
	var extraCreateArgs []string
	if backingFilesystem == Btrfs {
		extraCreateArgs = append(extraCreateArgs, "-B", Btrfs)
	}
	// Create the container.
	logger.Tracef("create the container")
	if err := lxcContainer.Create(configFile, defaultTemplate, extraCreateArgs, templateParams); err != nil {
		logger.Errorf("lxc container creation failed: %v", err)
		return nil, err
	}
	// Make sure that the mount dir has been created.
	logger.Tracef("make the mount dir for the shared logs")
	if err := os.MkdirAll(internalLogDir(name), 0755); err != nil {
		logger.Tracef("failed to create internal /var/log/juju mount dir: %v", err)
		return nil, err
	}

	// Start the lxc container with the appropriate settings for grabbing the
	// console output and a log file.
	consoleFile := filepath.Join(containerDirectory, "console.log")
	lxcContainer.SetLogFile(filepath.Join(containerDirectory, "container.log"), golxc.LogDebug)
	logger.Tracef("start the container")
	// We explicitly don't pass through the config file to the container.Start
	// method as we have passed it through at container creation time.  This
	// is necessary to get the appropriate rootfs reference without explicitly
	// setting it ourselves.
	if err = lxcContainer.Start("", consoleFile); err != nil {
		logger.Errorf("container failed to start: %v", err)
		return nil, err
	}
	logger.Infof("template container started, now wait for it to stop")
	// Perhaps we should wait for it to finish, and the question becomes "how
	// long do we wait for it to complete?"

	console, err := os.Open(consoleFile)
	if err != nil {
		// can't listen
		return nil, err
	}

	tailWriter := &logTail{tick: time.Now()}
	consoleTailer := tailer.NewTailer(console, tailWriter, 0, nil)
	defer consoleTailer.Stop()

	// We should wait maybe 1 minute between output?
	// if no output check to see if stopped
	// If we have no output and still running, something has probably gone wrong
	for lxcContainer.IsRunning() {
		if tailWriter.lastTick().Before(time.Now().Add(-TemplateStopTimeout)) {
			logger.Infof("not heard anything from the template log for five minutes")
			return nil, fmt.Errorf("template container %q did not stop", name)
		}
		time.Sleep(time.Second)
	}

	return lxcContainer, nil
}

type logTail struct {
	tick  time.Time
	mutex sync.Mutex
}

var _ io.Writer = (*logTail)(nil)

func (t *logTail) Write(data []byte) (int, error) {
	logger.Tracef(string(data))
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.tick = time.Now()
	return len(data), nil
}

func (t *logTail) lastTick() time.Time {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	tick := t.tick
	return tick
}
<commit_msg>Use the right func signature.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package lxc

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	"launchpad.net/golxc"

	coreCloudinit "launchpad.net/juju-core/cloudinit"
	"launchpad.net/juju-core/container"
	"launchpad.net/juju-core/environs/cloudinit"
	"launchpad.net/juju-core/juju/osenv"
	"launchpad.net/juju-core/utils"
	"launchpad.net/juju-core/utils/fslock"
	"launchpad.net/juju-core/utils/tailer"
)

const (
	templateShutdownUpstartFilename = "/etc/init/juju-template-restart.conf"
	templateShutdownUpstartScript   = `
description "Juju lxc template shutdown job"
author "Juju Team <juju@lists.ubuntu.com>"
start on stopped cloud-final

script
  shutdown -h now
end script

post-stop script
  rm ` + templateShutdownUpstartFilename + `
end script
`
)

var (
	TemplateLockDir = "/var/lib/juju/locks"

	TemplateStopTimeout = 5 * time.Minute
)

// templateUserData returns a minimal user data necessary for the template.
// This should have the authorized keys, base packages, the cloud archive if
// necessary,  initial apt proxy config, and it should do the apt-get
// update/upgrade initially.
func templateUserData(
	series string,
	authorizedKeys string,
	aptProxy osenv.ProxySettings,
) ([]byte, error) {
	config := coreCloudinit.New()
	config.AddScripts(
		"set -xe", // ensure we run all the scripts or abort.
	)
	config.AddSSHAuthorizedKeys(authorizedKeys)
	cloudinit.MaybeAddCloudArchiveCloudTools(config, series)
	cloudinit.AddAptCommands(aptProxy, config)
	config.AddScripts(
		fmt.Sprintf(
			"printf '%%s\n' %s > %s",
			utils.ShQuote(templateShutdownUpstartScript),
			templateShutdownUpstartFilename,
		))
	data, err := config.Render()
	if err != nil {
		return nil, err
	}
	return data, nil
}

func AcquireTemplateLock(name, message string) (*fslock.Lock, error) {
	logger.Infof("wait for fslock on %v", name)
	lock, err := fslock.NewLock(TemplateLockDir, name)
	if err != nil {
		logger.Tracef("failed to create fslock for template: %v", err)
		return nil, err
	}
	err = lock.Lock(message)
	if err != nil {
		logger.Tracef("failed to acquire lock for template: %v", err)
		return nil, err
	}
	return lock, nil
}

// Make sure a template exists that we can clone from.
func EnsureCloneTemplate(
	backingFilesystem string,
	series string,
	network *container.NetworkConfig,
	authorizedKeys string,
	aptProxy osenv.ProxySettings,
) (golxc.Container, error) {
	name := fmt.Sprintf("juju-%s-template", series)
	containerDirectory, err := container.NewDirectory(name)
	if err != nil {
		return nil, err
	}

	lock, err := AcquireTemplateLock(name, "ensure clone exists")
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	lxcContainer := LxcObjectFactory.New(name)
	// Early exit if the container has been constructed before.
	if lxcContainer.IsConstructed() {
		logger.Infof("template exists, continuing")
		return lxcContainer, nil
	}
	logger.Infof("template does not exist, creating")

	userData, err := templateUserData(series, authorizedKeys, aptProxy)
	if err != nil {
		logger.Tracef("filed to create tempalte user data for template: %v", err)
		return nil, err
	}
	userDataFilename, err := container.WriteCloudInitFile(containerDirectory, userData)
	if err != nil {
		return nil, err
	}

	configFile, err := writeLxcConfig(network, containerDirectory)
	if err != nil {
		logger.Errorf("failed to write config file: %v", err)
		return nil, err
	}
	templateParams := []string{
		"--debug",                      // Debug errors in the cloud image
		"--userdata", userDataFilename, // Our groovey cloud-init
		"--hostid", name, // Use the container name as the hostid
		"-r", series,
	}
	var extraCreateArgs []string
	if backingFilesystem == Btrfs {
		extraCreateArgs = append(extraCreateArgs, "-B", Btrfs)
	}
	// Create the container.
	logger.Tracef("create the container")
	if err := lxcContainer.Create(configFile, defaultTemplate, extraCreateArgs, templateParams); err != nil {
		logger.Errorf("lxc container creation failed: %v", err)
		return nil, err
	}
	// Make sure that the mount dir has been created.
	logger.Tracef("make the mount dir for the shared logs")
	if err := os.MkdirAll(internalLogDir(name), 0755); err != nil {
		logger.Tracef("failed to create internal /var/log/juju mount dir: %v", err)
		return nil, err
	}

	// Start the lxc container with the appropriate settings for grabbing the
	// console output and a log file.
	consoleFile := filepath.Join(containerDirectory, "console.log")
	lxcContainer.SetLogFile(filepath.Join(containerDirectory, "container.log"), golxc.LogDebug)
	logger.Tracef("start the container")
	// We explicitly don't pass through the config file to the container.Start
	// method as we have passed it through at container creation time.  This
	// is necessary to get the appropriate rootfs reference without explicitly
	// setting it ourselves.
	if err = lxcContainer.Start("", consoleFile); err != nil {
		logger.Errorf("container failed to start: %v", err)
		return nil, err
	}
	logger.Infof("template container started, now wait for it to stop")
	// Perhaps we should wait for it to finish, and the question becomes "how
	// long do we wait for it to complete?"

	console, err := os.Open(consoleFile)
	if err != nil {
		// can't listen
		return nil, err
	}

	tailWriter := &logTail{tick: time.Now()}
	consoleTailer := tailer.NewTailer(console, tailWriter, nil)
	defer consoleTailer.Stop()

	// We should wait maybe 1 minute between output?
	// if no output check to see if stopped
	// If we have no output and still running, something has probably gone wrong
	for lxcContainer.IsRunning() {
		if tailWriter.lastTick().Before(time.Now().Add(-TemplateStopTimeout)) {
			logger.Infof("not heard anything from the template log for five minutes")
			return nil, fmt.Errorf("template container %q did not stop", name)
		}
		time.Sleep(time.Second)
	}

	return lxcContainer, nil
}

type logTail struct {
	tick  time.Time
	mutex sync.Mutex
}

var _ io.Writer = (*logTail)(nil)

func (t *logTail) Write(data []byte) (int, error) {
	logger.Tracef(string(data))
	t.mutex.Lock()
	defer t.mutex.Unlock()
	t.tick = time.Now()
	return len(data), nil
}

func (t *logTail) lastTick() time.Time {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	tick := t.tick
	return tick
}
<|endoftext|>


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

package volume

import (
	"errors"

	"fmt"
)

// DriverInit represents a function that can initialize a driver.
type DriverInit func(root string) (Driver, error)

var (
	drivers       map[string]DriverInit
	driversByRoot map[string]Driver

	ErrDriverNotSupported   = errors.New("driver not supported")
	ErrSnapshotExists       = errors.New("snapshot exists")
	ErrSnapshotDoesNotExist = errors.New("snapshot does not exist")
)

func init() {
	drivers = make(map[string]DriverInit)
	driversByRoot = make(map[string]Driver)
}

// Driver is the basic interface to the filesystem. It is able to create,
// manage and destroy volumes. It is initialized with and operates beneath
// a given directory.
type Driver interface {
	// Root returns the filesystem root this driver acts on
	Root() string
	// GetFSType returns the string describing the driver
	GetFSType() string
	// Create creates a volume with the given name and returns it. The volume
	// must not exist already.
	Create(volumeName string) (Volume, error)
	// Remove removes an existing device. If the device doesn't exist, the
	// removal is a no-op
	Remove(volumeName string) error
	// Get returns the volume with the given name. The volume must exist.
	Get(volumeName string) (Volume, error)
	// Release releases any runtime resources associated with a volume (e.g.,
	// unmounts a device)
	Release(volumeName string) error
	// List returns the names of all volumes managed by this driver
	List() []string
	// Exists returns whether or not a volume managed by this driver exists
	// with the given name
	Exists(volumeName string) bool
	// Cleanup releases any runtime resources held by the driver itself.
	Cleanup() error
}

// Volume maps, in the end, to a directory on the filesystem available to the
// application. It can be snapshotted and rolled back to snapshots. It can be
// exported to a file and restored from a file.
type Volume interface {
	// Name returns the name of this volume
	Name() string
	// Path returns the filesystem path to this volume
	Path() string
	// Driver returns the driver managing this volume
	Driver() Driver
	// Snapshot snapshots the current state of this volume and stores it
	// using the name <label>
	Snapshot(label string) (err error)
	// SnapshotMetadataPath returns the path to the directory storing this
	// snapshot's metadata.
	SnapshotMetadataPath(label string) string
	// Snapshots lists all snapshots of this volume
	Snapshots() ([]string, error)
	// RemoveSnapshot removes the snapshot with name <label>
	RemoveSnapshot(label string) error
	// Rollback replaces the current state of the volume with that snapshotted
	// as <label>
	Rollback(label string) error
	// Export exports the snapshot stored as <label> to <filename>
	Export(label, parent, filename string) error
	// Import imports the exported snapshot at <filename> as <label>
	Import(label, filename string) error
	// Tenant returns the base tenant of this volume
	Tenant() string
}

// Register registers a driver initializer under <name> so it can be looked up
func Register(name string, driverInit DriverInit) error {
	if driverInit == nil {
		return fmt.Errorf("Can't register a nil driver initializer")
	}
	if _, dup := drivers[name]; dup {
		return fmt.Errorf("Already registered driver %s", name)
	}
	drivers[name] = driverInit
	return nil
}

// Registered returns a boolean indicating whether driver <name> has been registered.
func Registered(name string) bool {
	_, ok := drivers[name]
	return ok
}

// Unregister the driver init func <name>. If it doesn't exist, it's a no-op.
func Unregister(name string) {
	delete(drivers, name)
	// Also delete any existing drivers using this name
	for root, drv := range driversByRoot {
		if drv.GetFSType() == name {
			delete(driversByRoot, root)
		}
	}
}

// GetDriver returns a driver of type <name> initialized to <root>.
func GetDriver(name, root string) (Driver, error) {
	// First make sure it's a driver that exists
	if init, exists := drivers[name]; exists {
		// Return the same driver instance every time for a root path
		if driver, ok := driversByRoot[root]; ok {
			return driver, nil
		}
		// No instance yet, so create one
		driver, err := init(root)
		if err != nil {
			return nil, err
		}
		driversByRoot[root] = driver
		return driver, nil
	}
	return nil, ErrDriverNotSupported
}

// Mount loads, mounting if necessary, a volume under a path using a specific
// driver.
func Mount(driverName, volumeName, rootDir string) (volume Volume, err error) {
	driver, err := GetDriver(driverName, rootDir)
	if err != nil {
		return nil, err
	}
	if driver.Exists(volumeName) {
		volume, err = driver.Get(volumeName)
	} else {
		volume, err = driver.Create(volumeName)
	}
	if err != nil {
		return nil, err
	}
	return volume, nil
}
<commit_msg>Add ShutdownActiveDrivers method<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package volume

import (
	"errors"

	"github.com/zenoss/glog"

	"fmt"
)

// DriverInit represents a function that can initialize a driver.
type DriverInit func(root string) (Driver, error)

var (
	drivers       map[string]DriverInit
	driversByRoot map[string]Driver

	ErrDriverNotSupported   = errors.New("driver not supported")
	ErrSnapshotExists       = errors.New("snapshot exists")
	ErrSnapshotDoesNotExist = errors.New("snapshot does not exist")
)

func init() {
	drivers = make(map[string]DriverInit)
	driversByRoot = make(map[string]Driver)
}

// Driver is the basic interface to the filesystem. It is able to create,
// manage and destroy volumes. It is initialized with and operates beneath
// a given directory.
type Driver interface {
	// Root returns the filesystem root this driver acts on
	Root() string
	// GetFSType returns the string describing the driver
	GetFSType() string
	// Create creates a volume with the given name and returns it. The volume
	// must not exist already.
	Create(volumeName string) (Volume, error)
	// Remove removes an existing device. If the device doesn't exist, the
	// removal is a no-op
	Remove(volumeName string) error
	// Get returns the volume with the given name. The volume must exist.
	Get(volumeName string) (Volume, error)
	// Release releases any runtime resources associated with a volume (e.g.,
	// unmounts a device)
	Release(volumeName string) error
	// List returns the names of all volumes managed by this driver
	List() []string
	// Exists returns whether or not a volume managed by this driver exists
	// with the given name
	Exists(volumeName string) bool
	// Cleanup releases any runtime resources held by the driver itself.
	Cleanup() error
}

// Volume maps, in the end, to a directory on the filesystem available to the
// application. It can be snapshotted and rolled back to snapshots. It can be
// exported to a file and restored from a file.
type Volume interface {
	// Name returns the name of this volume
	Name() string
	// Path returns the filesystem path to this volume
	Path() string
	// Driver returns the driver managing this volume
	Driver() Driver
	// Snapshot snapshots the current state of this volume and stores it
	// using the name <label>
	Snapshot(label string) (err error)
	// SnapshotMetadataPath returns the path to the directory storing this
	// snapshot's metadata.
	SnapshotMetadataPath(label string) string
	// Snapshots lists all snapshots of this volume
	Snapshots() ([]string, error)
	// RemoveSnapshot removes the snapshot with name <label>
	RemoveSnapshot(label string) error
	// Rollback replaces the current state of the volume with that snapshotted
	// as <label>
	Rollback(label string) error
	// Export exports the snapshot stored as <label> to <filename>
	Export(label, parent, filename string) error
	// Import imports the exported snapshot at <filename> as <label>
	Import(label, filename string) error
	// Tenant returns the base tenant of this volume
	Tenant() string
}

// Register registers a driver initializer under <name> so it can be looked up
func Register(name string, driverInit DriverInit) error {
	if driverInit == nil {
		return fmt.Errorf("Can't register a nil driver initializer")
	}
	if _, dup := drivers[name]; dup {
		return fmt.Errorf("Already registered driver %s", name)
	}
	drivers[name] = driverInit
	return nil
}

// Registered returns a boolean indicating whether driver <name> has been registered.
func Registered(name string) bool {
	_, ok := drivers[name]
	return ok
}

// Unregister the driver init func <name>. If it doesn't exist, it's a no-op.
func Unregister(name string) {
	delete(drivers, name)
	// Also delete any existing drivers using this name
	for root, drv := range driversByRoot {
		if drv.GetFSType() == name {
			delete(driversByRoot, root)
		}
	}
}

// GetDriver returns a driver of type <name> initialized to <root>.
func GetDriver(name, root string) (Driver, error) {
	// First make sure it's a driver that exists
	if init, exists := drivers[name]; exists {
		// Return the same driver instance every time for a root path
		if driver, ok := driversByRoot[root]; ok {
			return driver, nil
		}
		// No instance yet, so create one
		driver, err := init(root)
		if err != nil {
			return nil, err
		}
		driversByRoot[root] = driver
		return driver, nil
	}
	return nil, ErrDriverNotSupported
}

// Mount loads, mounting if necessary, a volume under a path using a specific
// driver.
func Mount(driverName, volumeName, rootDir string) (volume Volume, err error) {
	driver, err := GetDriver(driverName, rootDir)
	if err != nil {
		return nil, err
	}
	if driver.Exists(volumeName) {
		volume, err = driver.Get(volumeName)
	} else {
		volume, err = driver.Create(volumeName)
	}
	if err != nil {
		return nil, err
	}
	return volume, nil
}

// ShutdownActiveDrivers shuts down all drivers that have been initialized
func ShutdownActiveDrivers() error {
	errs := []error{}
	for _, driver := range driversByRoot {
		glog.Infof("Shutting down %s driver for %s", driver.GetFSType(), driver.Root())
		if err := driver.Cleanup(); err != nil {
			glog.Errorf("Unable to clean up %s driver for %s: %s", driver.GetFSType(), driver.Root(), err)
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		// TODO: Something better
		return fmt.Errorf("Errors unmounting volumes: %s")
	}
	return nil
}
<|endoftext|>


<commit_before>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
	"log"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func TestXnorNetwork(t *testing.T) {

	// create network nodes
	input_neuron1 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	input_neuron2 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: -10, ActivationFunction: sigmoid}
	sensor1 := &Sensor{}
	sensor2 := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector1 := &Injector{}
	injector2 := &Injector{}

	// give names to network nodes
	sensor1.Name = "sensor1"
	sensor2.Name = "sensor2"
	input_neuron1.Name = "input_neuron1"
	input_neuron2.Name = "input_neuron2"
	hidden_neuron1.Name = "hidden_neuron1"
	hidden_neuron2.Name = "hidden_neuron2"
	output_neuron.Name = "output_neuron"
	actuator.Name = "actuator_neuron"

	// connect nodes together
	injector1.ConnectBidirectional(sensor1)
	injector2.ConnectBidirectional(sensor2)
	sensor1.ConnectBidirectionalWeighted(input_neuron1, []float64{1})
	sensor2.ConnectBidirectionalWeighted(input_neuron2, []float64{1})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{input_neuron1, input_neuron2, hidden_neuron1, hidden_neuron2, output_neuron, sensor1, sensor2, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	testInputs := []struct{
		x1 []float64
		x2 []float64
	}{ {x1: []float64{0}, x2: []float64{1}},
		{x1: []float64{1}, x2: []float64{1}},
		{x1: []float64{1}, x2: []float64{0}},
		{x1: []float64{0}, x2: []float64{0}}}

	expectedOutputs := []float64{ 0.0000, 1.00000, 0.0000, 1.00000 }

	// inject a value into sensor
	go func() {

		for _, inputPair := range testInputs {
			injector1.outbound[0].channel <- inputPair.x1
			injector2.outbound[0].channel <- inputPair.x2
		}

		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {

		for _, expectedOuput := range expectedOutputs {
			resultVector := <- wiretap.inbound[0].channel
			result := resultVector[0]
			assert.True(t, equalsWithMaxDelta(result, expectedOuput, .01))
		}

		wg.Done()
	}()

	wg.Wait()

	log.Printf("Done")

}

func identity_activation(x float64) float64 {
	return x
}
<commit_msg>Add condensed xnor test<commit_after>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
	"log"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func TestXnorNetwork(t *testing.T) {

	// create network nodes
	input_neuron1 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	input_neuron2 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: -10, ActivationFunction: sigmoid}
	sensor1 := &Sensor{}
	sensor2 := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector1 := &Injector{}
	injector2 := &Injector{}

	// give names to network nodes
	sensor1.Name = "sensor1"
	sensor2.Name = "sensor2"
	input_neuron1.Name = "input_neuron1"
	input_neuron2.Name = "input_neuron2"
	hidden_neuron1.Name = "hidden_neuron1"
	hidden_neuron2.Name = "hidden_neuron2"
	output_neuron.Name = "output_neuron"
	actuator.Name = "actuator"

	// connect nodes together
	injector1.ConnectBidirectional(sensor1)
	injector2.ConnectBidirectional(sensor2)
	sensor1.ConnectBidirectionalWeighted(input_neuron1, []float64{1})
	sensor2.ConnectBidirectionalWeighted(input_neuron2, []float64{1})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{input_neuron1, input_neuron2, hidden_neuron1, hidden_neuron2, output_neuron, sensor1, sensor2, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	testInputs := []struct{
		x1 []float64
		x2 []float64
	}{ {x1: []float64{0}, x2: []float64{1}},
		{x1: []float64{1}, x2: []float64{1}},
		{x1: []float64{1}, x2: []float64{0}},
		{x1: []float64{0}, x2: []float64{0}}}

	expectedOutputs := []float64{ 0.0000, 1.00000, 0.0000, 1.00000 }

	// inject a value into sensor
	go func() {

		for _, inputPair := range testInputs {
			injector1.outbound[0].channel <- inputPair.x1
			injector2.outbound[0].channel <- inputPair.x2
		}

		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {

		for _, expectedOuput := range expectedOutputs {
			resultVector := <- wiretap.inbound[0].channel
			result := resultVector[0]
			assert.True(t, equalsWithMaxDelta(result, expectedOuput, .01))
		}

		wg.Done()
	}()

	wg.Wait()

	log.Printf("Done")

}

func TestXnorCondensedNetwork(t *testing.T) {

	// identical to TestXnorNetwork, but uses single sensor with vector outputs, removes
	// the input layer neurons which are useless

	// create network nodes
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: -10, ActivationFunction: sigmoid}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// give names to network nodes
	sensor.Name = "sensor"
	hidden_neuron1.Name = "hidden_neuron1"
	hidden_neuron2.Name = "hidden_neuron2"
	output_neuron.Name = "output_neuron"
	actuator.Name = "actuator"

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	sensor.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20,20})
	sensor.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20, -20})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{sensor, hidden_neuron1, hidden_neuron2, output_neuron, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	testInputs := []struct{
		x1 float64
		x2 float64
	}{ {x1: 0, x2: 1},
		{x1: 1, x2: 1},
		{x1: 1, x2: 0},
		{x1: 0, x2: 0}}

	expectedOutputs := []float64{ 0.0000, 1.00000, 0.0000, 1.00000 }

	// inject a value into sensor
	go func() {

		for _, inputPair := range testInputs {
			injector.outbound[0].channel <- []float64{inputPair.x1, inputPair.x2}
		}

		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {

		for _, expectedOuput := range expectedOutputs {
			resultVector := <- wiretap.inbound[0].channel
			result := resultVector[0]
			assert.True(t, equalsWithMaxDelta(result, expectedOuput, .01))
		}

		wg.Done()
	}()

	wg.Wait()

	log.Printf("Done")

}

func identity_activation(x float64) float64 {
	return x
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"net"

	log "github.com/cihub/seelog"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/logic"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/metrics"
	serverprotocol "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/protocol"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/servernode"
)

type NodeServer struct {
	Config           *ServerConfig         `inject:""`
	Logic            *logic.Logic          `inject:""`
	Nodes            *serverprotocol.Nodes `inject:""`
	WebsocketHandler *WebsocketHandler     `inject:""`
	ElasticSearch    *ElasticSearch        `inject:""`
	Metrics          *metrics.Metrics      `inject:""`
}

func NewNodeServer() *NodeServer {
	return &NodeServer{}
}

func (ns *NodeServer) Start() {
	log.Info("Starting NodeServer (:" + ns.Config.NodePort + ")")
	listen, err := net.Listen("tcp", ":"+ns.Config.NodePort)
	if err != nil {
		log.Error("listen error", err)
		return
	}

	ns.Logic.RestoreRulesFromFile("rules.json")
	ns.addServerNode()

	//return
	go func() {
		for {
			fd, err := listen.Accept()
			if err != nil {
				log.Error("accept error", err)
				return
			}

			go ns.newNodeConnection(fd)
		}
	}()
}

func (ns *NodeServer) newNodeConnection(connection net.Conn) {
	// Recive data
	log.Info("New client connected")
	name := ""
	uuid := ""
	decoder := json.NewDecoder(connection)
	//encoder := json.NewEncoder(os.Stdout)
	var logicChannel chan string
	for {
		node := serverprotocol.NewNode()
		err := decoder.Decode(&node)

		if err != nil {
			if err.Error() == "EOF" {
				log.Info(name, " - Client disconnected")
				if uuid != "" {
					ns.Nodes.Delete(uuid)
					close(logicChannel)
				}
				//TODO be able to not send everything always. perhaps implement remove instead of all?
				ns.WebsocketHandler.SendAllNodes()
				return
			}
			log.Warn("Not disconnect but error: ", err)
			//return here?
		} else {
			name = node.Name()
			uuid = node.Uuid()

			existingNode := ns.Nodes.ByUuid(uuid)
			if existingNode == nil {
				ns.Nodes.Add(node)
				logicChannel = ns.Logic.ListenForChanges(node.Uuid())
				node.SetConn(connection)
				ns.updateState(logicChannel, node)
			} else {
				existingNode.SetState(node.State())
				ns.updateState(logicChannel, existingNode)
			}

			ns.WebsocketHandler.SendSingleNode(uuid)
		}
	}
}

func (ns *NodeServer) updateState(updateChan chan string, node serverprotocol.Node) {
	if node == nil {
		log.Warn("Recived an updateState but no node was provided, ignoring...")
		return
	}
	ns.Logic.Update(updateChan, node)
	ns.Metrics.Update(node)
}

func (self *NodeServer) addServerNode() {
	logicChannel := self.Logic.ListenForChanges(self.Config.Uuid)
	node := servernode.New(self.Config.Uuid, logicChannel)
	self.Nodes.Add(node)
}
<commit_msg>removed unneccesery else and remove node on any error from Decoder<commit_after>package main

import (
	"encoding/json"
	"net"

	log "github.com/cihub/seelog"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/logic"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/metrics"
	serverprotocol "github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/protocol"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/servernode"
)

type NodeServer struct {
	Config           *ServerConfig         `inject:""`
	Logic            *logic.Logic          `inject:""`
	Nodes            *serverprotocol.Nodes `inject:""`
	WebsocketHandler *WebsocketHandler     `inject:""`
	ElasticSearch    *ElasticSearch        `inject:""`
	Metrics          *metrics.Metrics      `inject:""`
}

func NewNodeServer() *NodeServer {
	return &NodeServer{}
}

func (ns *NodeServer) Start() {
	log.Info("Starting NodeServer (:" + ns.Config.NodePort + ")")
	listen, err := net.Listen("tcp", ":"+ns.Config.NodePort)
	if err != nil {
		log.Error("listen error", err)
		return
	}

	ns.Logic.RestoreRulesFromFile("rules.json")
	ns.addServerNode()

	//return
	go func() {
		for {
			fd, err := listen.Accept()
			if err != nil {
				log.Error("accept error", err)
				return
			}

			go ns.newNodeConnection(fd)
		}
	}()
}

func (ns *NodeServer) newNodeConnection(connection net.Conn) {
	// Recive data
	log.Info("New client connected")
	name := ""
	uuid := ""
	decoder := json.NewDecoder(connection)
	//encoder := json.NewEncoder(os.Stdout)
	var logicChannel chan string
	for {
		node := serverprotocol.NewNode()
		err := decoder.Decode(&node)

		if err != nil {
			//if err.Error() == "EOF" {
			log.Info(name, " - Client disconnected with error:", err.Error())
			if uuid != "" {
				ns.Nodes.Delete(uuid)
				close(logicChannel)
			}
			//TODO be able to not send everything always. perhaps implement remove instead of all?
			ns.WebsocketHandler.SendAllNodes()
			//return
			//}
			//log.Warn("Not disconnect but error: ", err)
			return
		}

		name = node.Name()
		uuid = node.Uuid()

		existingNode := ns.Nodes.ByUuid(uuid)
		if existingNode == nil {
			ns.Nodes.Add(node)
			logicChannel = ns.Logic.ListenForChanges(node.Uuid())
			node.SetConn(connection)
			ns.updateState(logicChannel, node)
		} else {
			existingNode.SetState(node.State())
			ns.updateState(logicChannel, existingNode)
		}

		ns.WebsocketHandler.SendSingleNode(uuid)
	}
}

func (ns *NodeServer) updateState(updateChan chan string, node serverprotocol.Node) {
	if node == nil {
		log.Warn("Recived an updateState but no node was provided, ignoring...")
		return
	}
	ns.Logic.Update(updateChan, node)
	ns.Metrics.Update(node)
}

func (self *NodeServer) addServerNode() {
	logicChannel := self.Logic.ListenForChanges(self.Config.Uuid)
	node := servernode.New(self.Config.Uuid, logicChannel)
	self.Nodes.Add(node)
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"
	"time"

	"github.com/everpcpc/pixiv"
)

func initPixiv(cfg *PixivConfig) error {
	tokenKey := "pixiv:" + cfg.Username + ":auth"
	token := redisClient.HGet(tokenKey, "token").Val()
	refreshToken := redisClient.HGet(tokenKey, "refresh_token").Val()
	tokenDeadline, _ := time.Parse(time.RFC3339, redisClient.HGet(tokenKey, "token_deadline").Val())
	pixiv.HookAuth(func(t, rt string, td time.Time) error {
		v := map[string]interface{}{
			"token":          t,
			"refresh_token":  rt,
			"token_deadline": td.Format(time.RFC3339),
		}
		return redisClient.HMSet(tokenKey, v).Err()
	})

	var account *pixiv.Account
	var err error
	if token+refreshToken == "" {
		logger.Debugf("login with %s", cfg.Username)
		account, err = pixiv.Login(cfg.Username, cfg.Password)
	} else {
		logger.Debugf("load auth with %+v", tokenDeadline)
		account, err = pixiv.LoadAuth(token, refreshToken, tokenDeadline)
	}
	if err == nil {
		logger.Debugf("pixiv: %+v", account)
	}
	return err
}

func pixivFollow(cfg *PixivConfig, ttl int) {
	if err := initPixiv(cfg); err != nil {
		logger.Fatal(err)
	}
	if ttl < 10 {
		ttl = 10
	}
	papp := pixiv.NewApp()
	ticker := time.Tick(time.Duration(ttl) * time.Second)
	maxIDKey := "pixiv:" + cfg.Username + "follow"
	for {
		<-ticker
		maxID, err := redisClient.Get(maxIDKey).Uint64()
		if err != nil {
			logger.Error(err)
			continue
		}

		illusts, err := papp.IllustFollow("public", 0)
		if err != nil {
			logger.Error(err)
			continue
		}
		if len(illusts) == 0 {
			continue
		}
		for i := range illusts {
			if maxID >= illusts[i].ID {
				break
			}
			go telegramBot.send(telegramBot.SelfChatID, pixivURL(illusts[i].ID))
		}
		if err := redisClient.Set(maxIDKey, illusts[0].ID, 0).Err(); err != nil {
			logger.Error(err)
		}
	}
}

func pixivURL(id uint64) string {
	return "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + strconv.FormatUint(id, 10)
}
<commit_msg>fix key<commit_after>package main

import (
	"strconv"
	"time"

	"github.com/everpcpc/pixiv"
	"github.com/go-redis/redis"
)

func initPixiv(cfg *PixivConfig) error {
	tokenKey := "pixiv:" + cfg.Username + ":auth"
	token := redisClient.HGet(tokenKey, "token").Val()
	refreshToken := redisClient.HGet(tokenKey, "refresh_token").Val()
	tokenDeadline, _ := time.Parse(time.RFC3339, redisClient.HGet(tokenKey, "token_deadline").Val())
	pixiv.HookAuth(func(t, rt string, td time.Time) error {
		v := map[string]interface{}{
			"token":          t,
			"refresh_token":  rt,
			"token_deadline": td.Format(time.RFC3339),
		}
		return redisClient.HMSet(tokenKey, v).Err()
	})

	var account *pixiv.Account
	var err error
	if token+refreshToken == "" {
		logger.Debugf("login with %s", cfg.Username)
		account, err = pixiv.Login(cfg.Username, cfg.Password)
	} else {
		logger.Debugf("load auth with %+v", tokenDeadline)
		account, err = pixiv.LoadAuth(token, refreshToken, tokenDeadline)
	}
	if err == nil {
		logger.Debugf("pixiv: %+v", account)
	}
	return err
}

func pixivFollow(cfg *PixivConfig, ttl int) {
	if err := initPixiv(cfg); err != nil {
		logger.Fatal(err)
	}
	if ttl < 10 {
		ttl = 10
	}
	papp := pixiv.NewApp()
	ticker := time.Tick(time.Duration(ttl) * time.Second)
	maxIDKey := "pixiv:" + cfg.Username + ":follow"
	for {
		<-ticker
		maxID, err := redisClient.Get(maxIDKey).Uint64()
		if err != nil && err != redis.Nil {
			logger.Error(err)
			continue
		}

		illusts, err := papp.IllustFollow("public", 0)
		if err != nil {
			logger.Error(err)
			continue
		}
		if len(illusts) == 0 {
			continue
		}
		for i := range illusts {
			if maxID >= illusts[i].ID {
				break
			}
			go telegramBot.send(telegramBot.SelfChatID, pixivURL(illusts[i].ID))
		}
		if err := redisClient.Set(maxIDKey, illusts[0].ID, 0).Err(); err != nil {
			logger.Error(err)
		}
	}
}

func pixivURL(id uint64) string {
	return "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + strconv.FormatUint(id, 10)
}
<|endoftext|>