<commit_before>package worker

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	"github.com/ovh/cds/engine/api/action"
	"github.com/ovh/cds/engine/api/context"
	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

var (
	modelCapabilities       map[int64][]sdk.Requirement
	modelCapaMutex          sync.RWMutex
	actionRequirements      map[int64][]sdk.Requirement
	actionRequirementsMutex sync.RWMutex
)

func logTime(name string, then time.Time) {

	d := time.Since(then)
	if d > 2000*time.Millisecond {
		log.Warning("%s took %s to execute\n", name, d)
	}
}

func loadWorkerModelStatus(db *sql.DB, c *context.Context) ([]sdk.ModelStatus, error) {
	defer logTime("loadWorkerModelStatus", time.Now())

	switch c.Agent {
	case sdk.HatcheryAgent:
		return loadWorkerModelStatusForGroup(db, c.User.Groups[0].ID)
	default:
		return loadWorkerModelStatusForUser(db, c.User.ID)
	}
}

func loadWorkerModelStatusForGroup(db *sql.DB, groupID int64) ([]sdk.ModelStatus, error) {
	query := `
SELECT worker_model.id, worker_model.name, COALESCE(waiting.count, 0) as waiting, COALESCE(building.count,0) as building FROM worker_model
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		WHERE worker.group_id = $1 AND worker.status = 'Waiting'
		AND worker.model = worker_model.id
		GROUP BY model) AS waiting ON waiting.model = worker_model.id
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		WHERE worker.group_id = $1 AND worker.status = 'Building'
		AND worker.model = worker_model.id
		GROUP BY model) AS building ON building.model = worker_model.id
ORDER BY worker_model.name ASC;
`
	rows, err := db.Query(query, groupID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var status []sdk.ModelStatus
	for rows.Next() {
		var ms sdk.ModelStatus
		err := rows.Scan(&ms.ModelID, &ms.ModelName, &ms.CurrentCount, &ms.BuildingCount)
		if err != nil {
			return nil, err
		}
		status = append(status, ms)
	}

	return status, nil

}

// loadWorkerModelStatus loads from database the number of worker deployed for each model
// start with group permissions calling user has access to.
func loadWorkerModelStatusForUser(db *sql.DB, userID int64) ([]sdk.ModelStatus, error) {

	query := `
SELECT worker_model.id, worker_model.name, COALESCE(waiting.count, 0) as waiting, COALESCE(building.count,0) as building FROM worker_model
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		JOIN "group" ON "group".id = worker.group_id
		JOIN group_user ON "group".id = group_user.group_id
		WHERE group_user.user_id = $1 AND worker.status = 'Waiting'
		AND worker.model = worker_model.id
		GROUP BY model) AS waiting ON waiting.model = worker_model.id
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		JOIN "group" ON "group".id = worker.group_id
		JOIN group_user ON "group".id = group_user.group_id
		WHERE group_user.user_id = $1 AND worker.status = 'Building'
		AND worker.model = worker_model.id
		GROUP BY model) AS building ON building.model = worker_model.id
ORDER BY worker_model.name ASC;
`

	rows, err := db.Query(query, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var status []sdk.ModelStatus
	for rows.Next() {
		var ms sdk.ModelStatus
		err := rows.Scan(&ms.ModelID, &ms.ModelName, &ms.CurrentCount, &ms.BuildingCount)
		if err != nil {
			return nil, err
		}
		status = append(status, ms)
	}

	return status, nil
}

func modelCanRun(db *sql.DB, name string, req []sdk.Requirement, capa []sdk.Requirement) bool {
	defer logTime("compareRequirements", time.Now())

	m, err := LoadWorkerModel(db, name)
	if err != nil {
		log.Warning("modelCanRun> Unable to load model %s", name)
		return false
	}

	log.Info("Comparing %d requirements to %d capa\n", len(req), len(capa))
	for _, r := range req {
		// service requirement are only supported by docker model
		if r.Type == sdk.ServiceRequirement && m.Type != sdk.Docker {
			return false
		}

		found := false

		// If requirement is a Model requirement, it's easy. It's either can or can't run
		if r.Type == sdk.ModelRequirement {
			return r.Value == name
		}

		// If requirement is an hostname requirement, it's for a specific worker
		if r.Type == sdk.HostnameRequirement {
			return false // TODO: update when hatchery in local mode declare an hostname capa
		}

		// Skip network access requirement as we can't check it
		if r.Type == sdk.NetworkAccessRequirement {
			continue
		}

		// Everyone can play plugins
		if r.Type == sdk.PluginRequirement {
			continue
		}

		// Check binary requirement against worker model capabilities
		for _, c := range capa {
			log.Debug("Comparing [%s] and [%s]\n", r.Name, c.Name)
			if r.Value == c.Value || r.Value == c.Name {
				found = true
				break
			}
		}

		if !found {
			return false
		}
	}

	return true
}

type actioncount struct {
	Action sdk.Action
	Count  int64
}

func scanActionCount(db *sql.DB, s database.Scanner) (actioncount, error) {
	ac := actioncount{}
	var actionID int64

	err := s.Scan(&ac.Count, &actionID)
	if err != nil {
		return ac, fmt.Errorf("scanActionCount> cannot scan: %s", err)
	}

	actionRequirementsMutex.RLock()
	req, ok := actionRequirements[actionID]
	actionRequirementsMutex.RUnlock()
	if !ok {
		req, err = action.LoadActionRequirements(db, actionID)
		if err != nil {
			return ac, fmt.Errorf("scanActionCount> cannot LoadActionRequirements for %d: %s\n", actionID, err)
		}
		actionRequirementsMutex.Lock()
		actionRequirements[actionID] = req
		actionRequirementsMutex.Unlock()
	}

	log.Debug("Action %d: %d in queue with %d requirements\n", actionID, ac.Count, len(req))
	ac.Action.Requirements = req
	return ac, nil
}

func loadGroupActionCount(db *sql.DB, groupID int64) ([]actioncount, error) {
	acs := []actioncount{}
	query := `
	SELECT COUNT(action_build.id), pipeline_action.action_id
	FROM action_build
	JOIN pipeline_action ON pipeline_action.id = action_build.pipeline_action_id
  JOIN pipeline_build ON pipeline_build.id = action_build.pipeline_build_id
  JOIN pipeline ON pipeline.id = pipeline_build.pipeline_id
	JOIN pipeline_group ON pipeline_group.pipeline_id = pipeline.id
	WHERE action_build.status = $1 AND pipeline_group.group_id = $2
	GROUP BY pipeline_action.action_id
	LIMIT 1000
	`

	rows, err := db.Query(query, string(sdk.StatusWaiting), groupID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		ac, err := scanActionCount(db, rows)
		if err != nil {
			return nil, err
		}

		acs = append(acs, ac)
	}

	return acs, nil
}
func loadUserActionCount(db *sql.DB, userID int64) ([]actioncount, error) {
	acs := []actioncount{}
	query := `
	SELECT COUNT(action_build.id), pipeline_action.action_id
	FROM action_build
	JOIN pipeline_action ON pipeline_action.id = action_build.pipeline_action_id
  JOIN pipeline_build ON pipeline_build.id = action_build.pipeline_build_id
  JOIN pipeline ON pipeline.id = pipeline_build.pipeline_id
	JOIN pipeline_group ON pipeline_group.pipeline_id = pipeline.id
	JOIN group_user ON group_user.group_id = pipeline_group.group_id
	WHERE action_build.status = $1 AND group_user.user_id = $2
	GROUP BY pipeline_action.action_id
	LIMIT 1000
	`

	rows, err := db.Query(query, string(sdk.StatusWaiting), userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		ac, err := scanActionCount(db, rows)
		if err != nil {
			return nil, err
		}

		acs = append(acs, ac)
	}

	return acs, nil
}

func loadActionCount(db *sql.DB, c *context.Context) ([]actioncount, error) {
	defer logTime("EstimateWorkerModelNeeds", time.Now())

	switch c.Agent {
	case sdk.HatcheryAgent:
		return loadGroupActionCount(db, c.User.Groups[0].ID)
	default:
		return loadUserActionCount(db, c.User.ID)
	}

}

// UpdateModelCapabilitiesCache updates model capabilities cache
func UpdateModelCapabilitiesCache() {
	modelCapabilities = make(map[int64][]sdk.Requirement)

	for {
		time.Sleep(5 * time.Second)
		db := database.DB()
		if db != nil {
			wms, err := LoadWorkerModels(db)
			if err != nil {
				log.Warning("updateModelCapabilities> Cannot load worker models: %s\n", err)
			}
			modelCapaMutex.Lock()
			for _, wm := range wms {
				modelCapabilities[wm.ID] = wm.Capabilities
			}
			modelCapaMutex.Unlock()
		}
	}
}

// UpdateActionRequirementsCache updates internal action cache
func UpdateActionRequirementsCache() {
	actionRequirements = make(map[int64][]sdk.Requirement)

	for {
		time.Sleep(10 * time.Second)
		db := database.DB()
		if db != nil {
			actionRequirementsMutex.Lock()
			for actionID := range actionRequirements {
				req, err := action.LoadActionRequirements(db, actionID)
				if err != nil {
					log.Warning("UpdateActionRequirementsCache> Cannot LoadActionRequirements for %d: %s\n", actionID, err)
					continue
				}
				actionRequirements[actionID] = req
			}
			actionRequirementsMutex.Unlock()
		}
	}
}

// EstimateWorkerModelNeeds returns for each worker model the needs of instances
func EstimateWorkerModelNeeds(db *sql.DB, c *context.Context) ([]sdk.ModelStatus, error) {
	defer logTime("EstimateWorkerModelNeeds", time.Now())
	u := c.User

	// Load models stats
	ms, err := loadWorkerModelStatus(db, c)
	if err != nil {
		log.Warning("EstimateWorkerModelsNeeds> Cannot LoadWorkerModelStatus for user %d: %s\n", u.ID, err)
		return nil, fmt.Errorf("EstimateWorkerModelNeeds> Cannot loadWorkerModelStatus> %s", err)
	}

	// Load actions in queue grouped by action (same requirement, same worker model)
	acs, err := loadActionCount(db, c)
	if err != nil {
		log.Warning("EstimateWorkerModelsNeeds> Cannot LoadActionCount for user %d: %s\n", u.ID, err)
		return nil, fmt.Errorf("EstimateWorkerModelNeeds> cannot loadActionCount> %s", err)
	}

	// Now for each unique action in queue, find a worker model able to run it
	var capas []sdk.Requirement
	var ok bool
	for _, ac := range acs {
		// Loop through model in case there is multiple models with the capacity to build current ActionBuild
		// This allow a dispatch of Count via round robin on all matching models
		// Thus dispatching the load potentially on multiple architectures/hatcheries
		loopModels := true
		for loopModels {
			loopModels = false

			for i := range ms {
				modelCapaMutex.RLock()
				capas, ok = modelCapabilities[ms[i].ModelID]
				modelCapaMutex.RUnlock()
				if !ok {
					capas, err = LoadWorkerModelCapabilities(db, ms[i].ModelID)
					if err != nil {
						return nil, fmt.Errorf("EstimateWorkerModelNees> cannot loadWorkerModelCapabilities: %s\n", err)
					}
				}

				if modelCanRun(db, ms[i].ModelName, ac.Action.Requirements, capas) {
					if ac.Count > 0 {
						ms[i].WantedCount++
						ac.Count--
						loopModels = true
					}

					//Add model requirement if action has specific kind of requirements
					ms[i].Requirements = []sdk.Requirement{}
					for j := range ac.Action.Requirements {
						if ac.Action.Requirements[j].Type == sdk.ServiceRequirement {
							ms[i].Requirements = append(ms[i].Requirements, ac.Action.Requirements[j])
						}
					}

					//break
				}
			} // !range models
		} // !range loopModels
	} // !range acs

	return ms, nil
}
<commit_msg>feat (api): elasticity logs<commit_after>package worker

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	"github.com/ovh/cds/engine/api/action"
	"github.com/ovh/cds/engine/api/context"
	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/log"
	"github.com/ovh/cds/sdk"
)

var (
	modelCapabilities       map[int64][]sdk.Requirement
	modelCapaMutex          sync.RWMutex
	actionRequirements      map[int64][]sdk.Requirement
	actionRequirementsMutex sync.RWMutex
)

func logTime(name string, then time.Time) {
	d := time.Since(then)
	if d > 10*time.Second {
		log.Warning("%s took %s to execute\n", name, d)
		return
	}

	if d > 2*time.Second {
		log.Warning("%s took %s to execute\n", name, d)
		return
	}

	log.Debug("%s took %s to execute\n", name, d)
}

func loadWorkerModelStatus(db *sql.DB, c *context.Context) ([]sdk.ModelStatus, error) {
	defer logTime("loadWorkerModelStatus", time.Now())

	switch c.Agent {
	case sdk.HatcheryAgent:
		return loadWorkerModelStatusForGroup(db, c.User.Groups[0].ID)
	default:
		return loadWorkerModelStatusForUser(db, c.User.ID)
	}
}

func loadWorkerModelStatusForGroup(db *sql.DB, groupID int64) ([]sdk.ModelStatus, error) {
	query := `
SELECT worker_model.id, worker_model.name, COALESCE(waiting.count, 0) as waiting, COALESCE(building.count,0) as building FROM worker_model
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		WHERE worker.group_id = $1 AND worker.status = 'Waiting'
		AND worker.model = worker_model.id
		GROUP BY model) AS waiting ON waiting.model = worker_model.id
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		WHERE worker.group_id = $1 AND worker.status = 'Building'
		AND worker.model = worker_model.id
		GROUP BY model) AS building ON building.model = worker_model.id
ORDER BY worker_model.name ASC;
`
	rows, err := db.Query(query, groupID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var status []sdk.ModelStatus
	for rows.Next() {
		var ms sdk.ModelStatus
		err := rows.Scan(&ms.ModelID, &ms.ModelName, &ms.CurrentCount, &ms.BuildingCount)
		if err != nil {
			return nil, err
		}
		status = append(status, ms)
	}

	return status, nil

}

// loadWorkerModelStatus loads from database the number of worker deployed for each model
// start with group permissions calling user has access to.
func loadWorkerModelStatusForUser(db *sql.DB, userID int64) ([]sdk.ModelStatus, error) {

	query := `
SELECT worker_model.id, worker_model.name, COALESCE(waiting.count, 0) as waiting, COALESCE(building.count,0) as building FROM worker_model
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		JOIN "group" ON "group".id = worker.group_id
		JOIN group_user ON "group".id = group_user.group_id
		WHERE group_user.user_id = $1 AND worker.status = 'Waiting'
		AND worker.model = worker_model.id
		GROUP BY model) AS waiting ON waiting.model = worker_model.id
	LEFT JOIN LATERAL (SELECT model, COUNT(worker.id) as count FROM worker
		JOIN "group" ON "group".id = worker.group_id
		JOIN group_user ON "group".id = group_user.group_id
		WHERE group_user.user_id = $1 AND worker.status = 'Building'
		AND worker.model = worker_model.id
		GROUP BY model) AS building ON building.model = worker_model.id
ORDER BY worker_model.name ASC;
`

	rows, err := db.Query(query, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var status []sdk.ModelStatus
	for rows.Next() {
		var ms sdk.ModelStatus
		err := rows.Scan(&ms.ModelID, &ms.ModelName, &ms.CurrentCount, &ms.BuildingCount)
		if err != nil {
			return nil, err
		}
		status = append(status, ms)
	}

	return status, nil
}

func modelCanRun(db *sql.DB, name string, req []sdk.Requirement, capa []sdk.Requirement) bool {
	defer logTime("compareRequirements", time.Now())

	m, err := LoadWorkerModel(db, name)
	if err != nil {
		log.Warning("modelCanRun> Unable to load model %s", name)
		return false
	}

	log.Info("Comparing %d requirements to %d capa\n", len(req), len(capa))
	for _, r := range req {
		// service requirement are only supported by docker model
		if r.Type == sdk.ServiceRequirement && m.Type != sdk.Docker {
			return false
		}

		found := false

		// If requirement is a Model requirement, it's easy. It's either can or can't run
		if r.Type == sdk.ModelRequirement {
			return r.Value == name
		}

		// If requirement is an hostname requirement, it's for a specific worker
		if r.Type == sdk.HostnameRequirement {
			return false // TODO: update when hatchery in local mode declare an hostname capa
		}

		// Skip network access requirement as we can't check it
		if r.Type == sdk.NetworkAccessRequirement {
			continue
		}

		// Everyone can play plugins
		if r.Type == sdk.PluginRequirement {
			continue
		}

		// Check binary requirement against worker model capabilities
		for _, c := range capa {
			log.Debug("Comparing [%s] and [%s]\n", r.Name, c.Name)
			if r.Value == c.Value || r.Value == c.Name {
				found = true
				break
			}
		}

		if !found {
			return false
		}
	}

	return true
}

type actioncount struct {
	Action sdk.Action
	Count  int64
}

func scanActionCount(db *sql.DB, s database.Scanner) (actioncount, error) {
	ac := actioncount{}
	var actionID int64

	err := s.Scan(&ac.Count, &actionID)
	if err != nil {
		return ac, fmt.Errorf("scanActionCount> cannot scan: %s", err)
	}

	actionRequirementsMutex.RLock()
	req, ok := actionRequirements[actionID]
	actionRequirementsMutex.RUnlock()
	if !ok {
		req, err = action.LoadActionRequirements(db, actionID)
		if err != nil {
			return ac, fmt.Errorf("scanActionCount> cannot LoadActionRequirements for %d: %s\n", actionID, err)
		}
		actionRequirementsMutex.Lock()
		actionRequirements[actionID] = req
		actionRequirementsMutex.Unlock()
	}

	log.Debug("Action %d: %d in queue with %d requirements\n", actionID, ac.Count, len(req))
	ac.Action.Requirements = req
	return ac, nil
}

func loadGroupActionCount(db *sql.DB, groupID int64) ([]actioncount, error) {
	acs := []actioncount{}
	query := `
	SELECT COUNT(action_build.id), pipeline_action.action_id
	FROM action_build
	JOIN pipeline_action ON pipeline_action.id = action_build.pipeline_action_id
  JOIN pipeline_build ON pipeline_build.id = action_build.pipeline_build_id
  JOIN pipeline ON pipeline.id = pipeline_build.pipeline_id
	JOIN pipeline_group ON pipeline_group.pipeline_id = pipeline.id
	WHERE action_build.status = $1 AND pipeline_group.group_id = $2
	GROUP BY pipeline_action.action_id
	LIMIT 1000
	`

	rows, err := db.Query(query, string(sdk.StatusWaiting), groupID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		ac, err := scanActionCount(db, rows)
		if err != nil {
			return nil, err
		}

		acs = append(acs, ac)
	}

	return acs, nil
}
func loadUserActionCount(db *sql.DB, userID int64) ([]actioncount, error) {
	acs := []actioncount{}
	query := `
	SELECT COUNT(action_build.id), pipeline_action.action_id
	FROM action_build
	JOIN pipeline_action ON pipeline_action.id = action_build.pipeline_action_id
  JOIN pipeline_build ON pipeline_build.id = action_build.pipeline_build_id
  JOIN pipeline ON pipeline.id = pipeline_build.pipeline_id
	JOIN pipeline_group ON pipeline_group.pipeline_id = pipeline.id
	JOIN group_user ON group_user.group_id = pipeline_group.group_id
	WHERE action_build.status = $1 AND group_user.user_id = $2
	GROUP BY pipeline_action.action_id
	LIMIT 1000
	`

	rows, err := db.Query(query, string(sdk.StatusWaiting), userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		ac, err := scanActionCount(db, rows)
		if err != nil {
			return nil, err
		}

		acs = append(acs, ac)
	}

	return acs, nil
}

func loadActionCount(db *sql.DB, c *context.Context) ([]actioncount, error) {
	defer logTime("EstimateWorkerModelNeeds", time.Now())

	switch c.Agent {
	case sdk.HatcheryAgent:
		return loadGroupActionCount(db, c.User.Groups[0].ID)
	default:
		return loadUserActionCount(db, c.User.ID)
	}

}

// UpdateModelCapabilitiesCache updates model capabilities cache
func UpdateModelCapabilitiesCache() {
	modelCapabilities = make(map[int64][]sdk.Requirement)

	for {
		time.Sleep(5 * time.Second)
		db := database.DB()
		if db != nil {
			wms, err := LoadWorkerModels(db)
			if err != nil {
				log.Warning("updateModelCapabilities> Cannot load worker models: %s\n", err)
			}
			modelCapaMutex.Lock()
			for _, wm := range wms {
				modelCapabilities[wm.ID] = wm.Capabilities
			}
			modelCapaMutex.Unlock()
		}
	}
}

// UpdateActionRequirementsCache updates internal action cache
func UpdateActionRequirementsCache() {
	actionRequirements = make(map[int64][]sdk.Requirement)

	for {
		time.Sleep(10 * time.Second)
		db := database.DB()
		if db != nil {
			actionRequirementsMutex.Lock()
			for actionID := range actionRequirements {
				req, err := action.LoadActionRequirements(db, actionID)
				if err != nil {
					log.Warning("UpdateActionRequirementsCache> Cannot LoadActionRequirements for %d: %s\n", actionID, err)
					continue
				}
				actionRequirements[actionID] = req
			}
			actionRequirementsMutex.Unlock()
		}
	}
}

// EstimateWorkerModelNeeds returns for each worker model the needs of instances
func EstimateWorkerModelNeeds(db *sql.DB, c *context.Context) ([]sdk.ModelStatus, error) {
	defer logTime("EstimateWorkerModelNeeds", time.Now())
	u := c.User

	// Load models stats
	ms, err := loadWorkerModelStatus(db, c)
	if err != nil {
		log.Warning("EstimateWorkerModelsNeeds> Cannot LoadWorkerModelStatus for user %d: %s\n", u.ID, err)
		return nil, fmt.Errorf("EstimateWorkerModelNeeds> Cannot loadWorkerModelStatus> %s", err)
	}

	// Load actions in queue grouped by action (same requirement, same worker model)
	acs, err := loadActionCount(db, c)
	if err != nil {
		log.Warning("EstimateWorkerModelsNeeds> Cannot LoadActionCount for user %d: %s\n", u.ID, err)
		return nil, fmt.Errorf("EstimateWorkerModelNeeds> cannot loadActionCount> %s", err)
	}

	// Now for each unique action in queue, find a worker model able to run it
	var capas []sdk.Requirement
	var ok bool
	for _, ac := range acs {
		// Loop through model in case there is multiple models with the capacity to build current ActionBuild
		// This allow a dispatch of Count via round robin on all matching models
		// Thus dispatching the load potentially on multiple architectures/hatcheries
		loopModels := true
		for loopModels {
			loopModels = false

			for i := range ms {
				modelCapaMutex.RLock()
				capas, ok = modelCapabilities[ms[i].ModelID]
				modelCapaMutex.RUnlock()
				if !ok {
					capas, err = LoadWorkerModelCapabilities(db, ms[i].ModelID)
					if err != nil {
						return nil, fmt.Errorf("EstimateWorkerModelNees> cannot loadWorkerModelCapabilities: %s\n", err)
					}
				}

				if modelCanRun(db, ms[i].ModelName, ac.Action.Requirements, capas) {
					if ac.Count > 0 {
						ms[i].WantedCount++
						ac.Count--
						loopModels = true
					}

					//Add model requirement if action has specific kind of requirements
					ms[i].Requirements = []sdk.Requirement{}
					for j := range ac.Action.Requirements {
						if ac.Action.Requirements[j].Type == sdk.ServiceRequirement {
							ms[i].Requirements = append(ms[i].Requirements, ac.Action.Requirements[j])
						}
					}

					//break
				}
			} // !range models
		} // !range loopModels
	} // !range acs

	return ms, nil
}
<|endoftext|>


<commit_before>package web

import (
	"net/http"
	"draringi/codejam2013/src/forecasting"
	"draringi/codejam2013/src/data"
    "encoding/json"
    "time"
)

type future struct {
    Records []record
}

type record struct {
    Date time.Time
    Power float64
}

type dashboardHelper struct {
    Data *data.CSVData
    Forcast *future
}

type Dashboard struct {
	channel chan (*data.CSVData)
	JSONAid *dashboardHelper
}

func (self *Dashboard) Init () {
	self.channel = make(chan (*data.CSVData), 1)
    self.JSONAid = new(dashboardHelper)
	forecasting.PredictPulse(self.channel)
	go func () {
		for {
			tmp := <-self.channel
            if tmp != nil {
				self.JSONAid.Data = tmp
			}
		}
	} ()
}

func (self *Dashboard) ServeHTTP (w http.ResponseWriter, request *http.Request) {
	http.ServeFile(w, request, "dashboard.html")
}

func (self *dashboardHelper) Build (Data *data.CSVData) {
    self.Data = Data
    self.Forcast = new(future)
    self.Forcast.Records = make([]record,len(Data.Data))
    for i :=0; i<len(Data.Data); i++ {
        self.Forcast.Records[i].Date = Data.Data[i].Time
        self.Forcast.Records[i].Power = Data.Data[i].Power
    }
}

func (self *dashboardHelper) jsonify (w http.ResponseWriter) {
    encoder := json.NewEncoder(w)
    encoder.Encode(self.Forcast)
}

func (self *dashboardHelper) ServeHTTP (w http.ResponseWriter, request *http.Request) {
    self.jsonify(w)
}
<commit_msg>added error checking to jsonify<commit_after>package web

import (
	"net/http"
	"draringi/codejam2013/src/forecasting"
	"draringi/codejam2013/src/data"
    "encoding/json"
    "time"
)

type future struct {
    Records []record
}

type record struct {
    Date time.Time
    Power float64
}

type dashboardHelper struct {
    Data *data.CSVData
    Forcast *future
}

type Dashboard struct {
	channel chan (*data.CSVData)
	JSONAid *dashboardHelper
}

func (self *Dashboard) Init () {
	self.channel = make(chan (*data.CSVData), 1)
    self.JSONAid = new(dashboardHelper)
	forecasting.PredictPulse(self.channel)
	go func () {
		for {
			tmp := <-self.channel
            if tmp != nil {
				self.JSONAid.Data = tmp
			}
		}
	} ()
}

func (self *Dashboard) ServeHTTP (w http.ResponseWriter, request *http.Request) {
	http.ServeFile(w, request, "dashboard.html")
}

func (self *dashboardHelper) Build (Data *data.CSVData) {
    self.Data = Data
    self.Forcast = new(future)
    self.Forcast.Records = make([]record,len(Data.Data))
    for i :=0; i<len(Data.Data); i++ {
        self.Forcast.Records[i].Date = Data.Data[i].Time
        self.Forcast.Records[i].Power = Data.Data[i].Power
    }
}

func (self *dashboardHelper) jsonify (w http.ResponseWriter) {
    encoder := json.NewEncoder(w)
    if self.Data != nil {
        encoder.Encode(self.Forcast)
    } else {
        http.Error(w,"Data not loaded...", 404)
    }
}

func (self *dashboardHelper) ServeHTTP (w http.ResponseWriter, request *http.Request) {
    self.jsonify(w)
}
<|endoftext|>


<commit_before>//
// go-sonos
// ========
//
// Copyright (c) 2012-2015, Ian T. Richards <ianr@panix.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
package main

import (
	"github.com/ianr0bkny/go-sonos/ssdp"
	"log"
)

// This code identifies UPnP devices on the netork that support the
// MusicServices API.
func main() {
	log.Print("go-sonos example discovery\n")
	mgr := ssdp.MakeManager()
	mgr.Discover("eth0", "11209", false)
	qry := ssdp.ServiceQueryTerms{
		ssdp.ServiceKey("schemas-upnp-org-MusicServices"): -1,
	}
	result := mgr.QueryServices(qry)
	if dev_list, has := result["schemas-upnp-org-MusicServices"]; has {
		for _, dev := range dev_list {
			log.Printf("%s %s %s %s %s\n", dev.Product(), dev.ProductVersion(), dev.Name(), dev.Location(), dev.UUID())
		}
	}
	mgr.Close()
}
<commit_msg>adding comments to example code<commit_after>//
// go-sonos
// ========
//
// Copyright (c) 2012-2015, Ian T. Richards <ianr@panix.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
package main

import (
	"github.com/ianr0bkny/go-sonos/ssdp"
	"log"
)

// This code identifies UPnP devices on the netork that support the
// MusicServices API.
func main() {
	log.Print("go-sonos example discovery\n")

	mgr := ssdp.MakeManager()

	// Discover()
	//  eth0 := Network device to query for UPnP devices
	// 11209 := Free local port for discovery replies
	// false := Do not subscribe for asynchronous updates
	mgr.Discover("eth0", "11209", false)

	// SericeQueryTerms
	// A map of service keys to minimum required version
	qry := ssdp.ServiceQueryTerms{
		ssdp.ServiceKey("schemas-upnp-org-MusicServices"): -1,
	}

	// Look for the service keys in qry in the database of discovered devices
	result := mgr.QueryServices(qry)
	if dev_list, has := result["schemas-upnp-org-MusicServices"]; has {
		for _, dev := range dev_list {
			log.Printf("%s %s %s %s %s\n", dev.Product(), dev.ProductVersion(), dev.Name(), dev.Location(), dev.UUID())
		}
	}
	mgr.Close()
}
<|endoftext|>


<commit_before>// Copyright 2015 The Cockroach 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.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package sql_test

import (
	"bytes"
	"database/sql"
	"flag"
	"fmt"
	"math/rand"
	"testing"

	"github.com/cockroachdb/cockroach/util/log"
)

var maxTransfer = flag.Int("max-transfer", 999, "Maximum amount to transfer in one transaction.")
var numAccounts = flag.Int("num-accounts", 999, "Number of accounts.")

// runBenchmarkBank mirrors the SQL performed by examples/sql_bank, but
// structured as a benchmark for easier usage of the Go performance analysis
// tools like pprof, memprof and trace.
func runBenchmarkBank(b *testing.B, db *sql.DB) {
	if _, err := db.Exec(`CREATE DATABASE IF NOT EXISTS bank`); err != nil {
		b.Fatal(err)
	}

	{
		// Initialize the "accounts" table.
		schema := `
CREATE TABLE IF NOT EXISTS bank.accounts (
  id INT PRIMARY KEY,
  balance INT NOT NULL
)`
		if _, err := db.Exec(schema); err != nil {
			b.Fatal(err)
		}
		if _, err := db.Exec("TRUNCATE TABLE bank.accounts"); err != nil {
			b.Fatal(err)
		}

		var placeholders bytes.Buffer
		var values []interface{}
		for i := 0; i < *numAccounts; i++ {
			if i > 0 {
				placeholders.WriteString(", ")
			}
			fmt.Fprintf(&placeholders, "($%d, 0)", i+1)
			values = append(values, i)
		}
		stmt := `INSERT INTO bank.accounts (id, balance) VALUES ` + placeholders.String()
		if _, err := db.Exec(stmt, values...); err != nil {
			b.Fatal(err)
		}
	}

	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			from := rand.Intn(*numAccounts)
			to := rand.Intn(*numAccounts - 1)
			if from == to {
				to = *numAccounts - 1
			}

			amount := rand.Intn(*maxTransfer)

			update := `
UPDATE bank.accounts
  SET balance = CASE id WHEN $1 THEN balance-$3 WHEN $2 THEN balance+$3 END
  WHERE id IN ($1, $2) AND (SELECT balance >= $3 FROM bank.accounts WHERE id = $1)
`
			if _, err := db.Exec(update, from, to, amount); err != nil {
				if log.V(1) {
					log.Warning(err)
				}
				continue
			}
		}
	})
	b.StopTimer()
}

func BenchmarkBank(b *testing.B) {
	benchmarkCockroach(b, runBenchmarkBank)
}
<commit_msg>Fix the bank benchmark.<commit_after>// Copyright 2015 The Cockroach 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.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package sql_test

import (
	"bytes"
	"database/sql"
	"flag"
	"fmt"
	"math/rand"
	"testing"

	"github.com/cockroachdb/cockroach/util/log"
)

var maxTransfer = flag.Int("max-transfer", 999, "Maximum amount to transfer in one transaction.")
var numAccounts = flag.Int("num-accounts", 999, "Number of accounts.")

// runBenchmarkBank mirrors the SQL performed by examples/sql_bank, but
// structured as a benchmark for easier usage of the Go performance analysis
// tools like pprof, memprof and trace.
func runBenchmarkBank(b *testing.B, db *sql.DB) {
	{
		// Initialize the "bank" table.
		schema := `
CREATE TABLE IF NOT EXISTS bench.bank (
  id INT PRIMARY KEY,
  balance INT NOT NULL
)`
		if _, err := db.Exec(schema); err != nil {
			b.Fatal(err)
		}
		if _, err := db.Exec("TRUNCATE TABLE bench.bank"); err != nil {
			b.Fatal(err)
		}

		var placeholders bytes.Buffer
		var values []interface{}
		for i := 0; i < *numAccounts; i++ {
			if i > 0 {
				placeholders.WriteString(", ")
			}
			fmt.Fprintf(&placeholders, "($%d, 0)", i+1)
			values = append(values, i)
		}
		stmt := `INSERT INTO bench.bank (id, balance) VALUES ` + placeholders.String()
		if _, err := db.Exec(stmt, values...); err != nil {
			b.Fatal(err)
		}
	}

	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			from := rand.Intn(*numAccounts)
			to := rand.Intn(*numAccounts - 1)
			if from == to {
				to = *numAccounts - 1
			}

			amount := rand.Intn(*maxTransfer)

			// TODO(mjibson): We can't use query parameters with this query because
			// it fails type checking on the CASE expression.
			update := fmt.Sprintf(`
UPDATE bench.bank
  SET balance = CASE id WHEN %[1]d THEN balance-%[3]d WHEN %[2]d THEN balance+%[3]d END
  WHERE id IN (%[1]d, %[2]d) AND (SELECT balance >= %[3]d FROM bench.bank WHERE id = %[1]d)
`, from, to, amount)
			if _, err := db.Exec(update); err != nil {
				if log.V(1) {
					log.Warning(err)
				}
				continue
			}
		}
	})
	b.StopTimer()
}

func BenchmarkBank_Cockroach(b *testing.B) {
	benchmarkCockroach(b, runBenchmarkBank)
}

func BenchmarkBank_Postgres(b *testing.B) {
	benchmarkPostgres(b, runBenchmarkBank)
}
<|endoftext|>


<commit_before>package executor_test

import (
	"encoding/json"
	"fmt"
	"os"
	"testing"

	"code.cloudfoundry.org/consuladapter/consulrunner"
	"code.cloudfoundry.org/localip"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/inigo/helpers"
	"code.cloudfoundry.org/inigo/helpers/certauthority"
	"code.cloudfoundry.org/inigo/helpers/portauthority"
	"code.cloudfoundry.org/inigo/world"
)

var (
	componentMaker world.ComponentMaker

	gardenProcess ifrit.Process
	gardenClient  garden.Client
	suiteTempDir  string
)

var _ = SynchronizedBeforeSuite(func() []byte {
	suiteTempDir = world.TempDir("before-suite")
	payload, err := json.Marshal(world.BuiltArtifacts{
		Executables: CompileTestedExecutables(),
	})
	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(encodedBuiltArtifacts []byte) {
	var builtArtifacts world.BuiltArtifacts

	err := json.Unmarshal(encodedBuiltArtifacts, &builtArtifacts)
	Expect(err).NotTo(HaveOccurred())

	_, dbBaseConnectionString := world.DBInfo()

	localIP, err := localip.LocalIP()
	Expect(err).NotTo(HaveOccurred())

	addresses := world.ComponentAddresses{
		Garden:              fmt.Sprintf("127.0.0.1:%d", 10000+config.GinkgoConfig.ParallelNode),
		NATS:                fmt.Sprintf("127.0.0.1:%d", 11000+config.GinkgoConfig.ParallelNode),
		Consul:              fmt.Sprintf("127.0.0.1:%d", 12750+config.GinkgoConfig.ParallelNode*consulrunner.PortOffsetLength),
		Rep:                 fmt.Sprintf("127.0.0.1:%d", 14000+config.GinkgoConfig.ParallelNode),
		FileServer:          fmt.Sprintf("%s:%d", localIP, 17000+config.GinkgoConfig.ParallelNode),
		Router:              fmt.Sprintf("127.0.0.1:%d", 18000+config.GinkgoConfig.ParallelNode),
		BBS:                 fmt.Sprintf("127.0.0.1:%d", 20500+config.GinkgoConfig.ParallelNode*2),
		Health:              fmt.Sprintf("127.0.0.1:%d", 20500+config.GinkgoConfig.ParallelNode*2+1),
		Auctioneer:          fmt.Sprintf("127.0.0.1:%d", 23000+config.GinkgoConfig.ParallelNode),
		SSHProxy:            fmt.Sprintf("127.0.0.1:%d", 23500+config.GinkgoConfig.ParallelNode),
		SSHProxyHealthCheck: fmt.Sprintf("127.0.0.1:%d", 24500+config.GinkgoConfig.ParallelNode),
		FakeVolmanDriver:    fmt.Sprintf("127.0.0.1:%d", 25500+config.GinkgoConfig.ParallelNode),
		Locket:              fmt.Sprintf("127.0.0.1:%d", 26500+config.GinkgoConfig.ParallelNode),
		SQL:                 fmt.Sprintf("%sdiego_%d", dbBaseConnectionString, config.GinkgoConfig.ParallelNode),
	}

	node := GinkgoParallelNode()
	startPort := 1000 * node
	portRange := 950
	endPort := startPort + portRange

	allocator, err := portauthority.New(startPort, endPort)
	Expect(err).NotTo(HaveOccurred())

	certDepot := world.TempDirWithParent(suiteTempDir, "cert-depot")

	certAuthority, err := certauthority.NewCertAuthority(certDepot, "ca")
	Expect(err).NotTo(HaveOccurred())

	componentMaker = world.MakeComponentMaker(builtArtifacts, addresses, allocator, certAuthority)
	componentMaker.Setup()
})

var _ = AfterSuite(func() {
	componentMaker.Teardown()

	deleteSuiteTempDir := func() error { return os.RemoveAll(suiteTempDir) }
	Eventually(deleteSuiteTempDir).Should(Succeed())
})

var _ = BeforeEach(func() {
	gardenProcess = ginkgomon.Invoke(componentMaker.Garden())
	gardenClient = componentMaker.GardenClient()
})

var _ = AfterEach(func() {
	destroyContainerErrors := helpers.CleanupGarden(gardenClient)

	helpers.StopProcesses(gardenProcess)

	Expect(destroyContainerErrors).To(
		BeEmpty(),
		"%d containers failed to be destroyed!",
		len(destroyContainerErrors),
	)
})

func TestExecutor(t *testing.T) {
	helpers.RegisterDefaultTimeouts()

	RegisterFailHandler(Fail)

	RunSpecs(t, "Executor Integration Suite")
}

func CompileTestedExecutables() world.BuiltExecutables {
	var err error

	builtExecutables := world.BuiltExecutables{}

	builtExecutables["garden"], err = gexec.BuildIn(os.Getenv("GARDEN_GOPATH"), "guardian/cmd/gdn", "-race", "-a", "-tags", "daemon")
	Expect(err).NotTo(HaveOccurred())

	return builtExecutables
}
<commit_msg>fix executor's suite<commit_after>package executor_test

import (
	"encoding/json"
	"fmt"
	"os"
	"testing"

	"code.cloudfoundry.org/consuladapter/consulrunner"
	"code.cloudfoundry.org/localip"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/inigo/helpers"
	"code.cloudfoundry.org/inigo/helpers/certauthority"
	"code.cloudfoundry.org/inigo/helpers/portauthority"
	"code.cloudfoundry.org/inigo/world"
)

var (
	componentMaker world.ComponentMaker

	gardenProcess ifrit.Process
	gardenClient  garden.Client
	suiteTempDir  string
)

var _ = SynchronizedBeforeSuite(func() []byte {
	suiteTempDir = world.TempDir("before-suite")
	payload, err := json.Marshal(world.BuiltArtifacts{
		Executables: CompileTestedExecutables(),
	})
	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(encodedBuiltArtifacts []byte) {
	var builtArtifacts world.BuiltArtifacts

	err := json.Unmarshal(encodedBuiltArtifacts, &builtArtifacts)
	Expect(err).NotTo(HaveOccurred())

	_, dbBaseConnectionString := world.DBInfo()

	localIP, err := localip.LocalIP()
	Expect(err).NotTo(HaveOccurred())

	addresses := world.ComponentAddresses{
		Garden:              fmt.Sprintf("127.0.0.1:%d", 10000+config.GinkgoConfig.ParallelNode),
		NATS:                fmt.Sprintf("127.0.0.1:%d", 11000+config.GinkgoConfig.ParallelNode),
		Consul:              fmt.Sprintf("127.0.0.1:%d", 12750+config.GinkgoConfig.ParallelNode*consulrunner.PortOffsetLength),
		Rep:                 fmt.Sprintf("127.0.0.1:%d", 14000+config.GinkgoConfig.ParallelNode),
		FileServer:          fmt.Sprintf("%s:%d", localIP, 17000+config.GinkgoConfig.ParallelNode),
		Router:              fmt.Sprintf("127.0.0.1:%d", 18000+config.GinkgoConfig.ParallelNode),
		BBS:                 fmt.Sprintf("127.0.0.1:%d", 20500+config.GinkgoConfig.ParallelNode*2),
		Health:              fmt.Sprintf("127.0.0.1:%d", 20500+config.GinkgoConfig.ParallelNode*2+1),
		Auctioneer:          fmt.Sprintf("127.0.0.1:%d", 23000+config.GinkgoConfig.ParallelNode),
		SSHProxy:            fmt.Sprintf("127.0.0.1:%d", 23500+config.GinkgoConfig.ParallelNode),
		SSHProxyHealthCheck: fmt.Sprintf("127.0.0.1:%d", 24500+config.GinkgoConfig.ParallelNode),
		FakeVolmanDriver:    fmt.Sprintf("127.0.0.1:%d", 25500+config.GinkgoConfig.ParallelNode),
		Locket:              fmt.Sprintf("127.0.0.1:%d", 26500+config.GinkgoConfig.ParallelNode),
		SQL:                 fmt.Sprintf("%sdiego_%d", dbBaseConnectionString, config.GinkgoConfig.ParallelNode),
	}

	node := GinkgoParallelNode()
	startPort := 1000 * node
	portRange := 950
	endPort := startPort + portRange

	allocator, err := portauthority.New(startPort, endPort)
	Expect(err).NotTo(HaveOccurred())

	certDepot := world.TempDirWithParent(suiteTempDir, "cert-depot")

	certAuthority, err := certauthority.NewCertAuthority(certDepot, "ca")
	Expect(err).NotTo(HaveOccurred())

	componentMaker = world.MakeComponentMaker(builtArtifacts, addresses, allocator, certAuthority)
	componentMaker.Setup()
})

var _ = AfterSuite(func() {
	componentMaker.Teardown()

	deleteSuiteTempDir := func() error { return os.RemoveAll(suiteTempDir) }
	Eventually(deleteSuiteTempDir).Should(Succeed())
})

var _ = BeforeEach(func() {
	gardenProcess = ginkgomon.Invoke(componentMaker.Garden())
	gardenClient = componentMaker.GardenClient()
})

var _ = AfterEach(func() {
	destroyContainerErrors := helpers.CleanupGarden(gardenClient)

	helpers.StopProcesses(gardenProcess)

	Expect(destroyContainerErrors).To(
		BeEmpty(),
		"%d containers failed to be destroyed!",
		len(destroyContainerErrors),
	)
})

func TestExecutor(t *testing.T) {
	helpers.RegisterDefaultTimeouts()

	RegisterFailHandler(Fail)

	RunSpecs(t, "Executor Integration Suite")
}

func CompileTestedExecutables() world.BuiltExecutables {
	var err error

	builtExecutables := world.BuiltExecutables{}

	cwd, err := os.Getwd()
	Expect(err).NotTo(HaveOccurred())
	Expect(os.Chdir(os.Getenv("GARDEN_GOPATH"))).To(Succeed())
	builtExecutables["garden"], err = gexec.Build("./cmd/gdn", "-race", "-a", "-tags", "daemon")
	Expect(err).NotTo(HaveOccurred())
	Expect(os.Chdir(cwd)).To(Succeed())

	return builtExecutables
}
<|endoftext|>


<commit_before>package chart

import (
	"errors"
	"fmt"
	"io"

	"github.com/golang/freetype/truetype"
)

// StackedBar is a bar within a StackedBarChart.
type StackedBar struct {
	Name   string
	Width  int
	Values []Value
}

// GetWidth returns the width of the bar.
func (sb StackedBar) GetWidth() int {
	if sb.Width == 0 {
		return 50
	}
	return sb.Width
}

// StackedBarChart is a chart that draws sections of a bar based on percentages.
type StackedBarChart struct {
	Title      string
	TitleStyle Style

	Width  int
	Height int
	DPI    float64

	Background Style
	Canvas     Style

	XAxis Style
	YAxis Style

	BarSpacing int

	Font        *truetype.Font
	defaultFont *truetype.Font

	Bars     []StackedBar
	Elements []Renderable
}

// GetDPI returns the dpi for the chart.
func (sbc StackedBarChart) GetDPI(defaults ...float64) float64 {
	if sbc.DPI == 0 {
		if len(defaults) > 0 {
			return defaults[0]
		}
		return DefaultDPI
	}
	return sbc.DPI
}

// GetFont returns the text font.
func (sbc StackedBarChart) GetFont() *truetype.Font {
	if sbc.Font == nil {
		return sbc.defaultFont
	}
	return sbc.Font
}

// GetWidth returns the chart width or the default value.
func (sbc StackedBarChart) GetWidth() int {
	if sbc.Width == 0 {
		return DefaultChartWidth
	}
	return sbc.Width
}

// GetHeight returns the chart height or the default value.
func (sbc StackedBarChart) GetHeight() int {
	if sbc.Height == 0 {
		return DefaultChartWidth
	}
	return sbc.Height
}

// GetBarSpacing returns the spacing between bars.
func (sbc StackedBarChart) GetBarSpacing() int {
	if sbc.BarSpacing == 0 {
		return 100
	}
	return sbc.BarSpacing
}

// Render renders the chart with the given renderer to the given io.Writer.
func (sbc StackedBarChart) Render(rp RendererProvider, w io.Writer) error {
	if len(sbc.Bars) == 0 {
		return errors.New("Please provide at least one bar.")
	}

	r, err := rp(sbc.GetWidth(), sbc.GetHeight())
	if err != nil {
		return err
	}

	if sbc.Font == nil {
		defaultFont, err := GetDefaultFont()
		if err != nil {
			return err
		}
		sbc.defaultFont = defaultFont
	}
	r.SetDPI(sbc.GetDPI(DefaultDPI))

	canvasBox := sbc.getAdjustedCanvasBox(sbc.getDefaultCanvasBox())
	sbc.drawBars(r, canvasBox)
	sbc.drawXAxis(r, canvasBox)
	sbc.drawYAxis(r, canvasBox)

	sbc.drawTitle(r)
	for _, a := range sbc.Elements {
		a(r, canvasBox, sbc.styleDefaultsElements())
	}

	return r.Save(w)
}

func (sbc StackedBarChart) drawBars(r Renderer, canvasBox Box) {
	xoffset := canvasBox.Left
	for _, bar := range sbc.Bars {
		sbc.drawBar(r, canvasBox, xoffset, bar)
		xoffset += sbc.GetBarSpacing()
	}
}

func (sbc StackedBarChart) drawBar(r Renderer, canvasBox Box, xoffset int, bar StackedBar) int {
	bxl := xoffset + Math.AbsInt(bar.GetWidth()>>1-sbc.GetBarSpacing()>>1)
	bxr := bxl + bar.GetWidth()

	normalizedBarComponents := Values(bar.Values).Normalize()
	yoffset := canvasBox.Top
	for index, bv := range normalizedBarComponents {
		barHeight := int(bv.Value * float64(canvasBox.Height()))
		barBox := Box{Top: yoffset, Left: bxl, Right: bxr, Bottom: yoffset + barHeight}
		Draw.Box(r, barBox, bv.Style.InheritFrom(sbc.styleDefaultsStackedBarValue(index)))
		yoffset += barHeight
	}

	return bxr
}

func (sbc StackedBarChart) drawXAxis(r Renderer, canvasBox Box) {
	if sbc.XAxis.Show {
		axisStyle := sbc.XAxis.InheritFrom(sbc.styleDefaultsAxes())
		axisStyle.WriteToRenderer(r)

		r.MoveTo(canvasBox.Left, canvasBox.Bottom)
		r.LineTo(canvasBox.Right, canvasBox.Bottom)
		r.Stroke()

		r.MoveTo(canvasBox.Left, canvasBox.Bottom)
		r.LineTo(canvasBox.Left, canvasBox.Bottom+DefaultVerticalTickHeight)
		r.Stroke()

		cursor := canvasBox.Left
		for _, bar := range sbc.Bars {

			spacing := (sbc.GetBarSpacing() >> 1)

			barLabelBox := Box{
				Top:    canvasBox.Bottom + DefaultXAxisMargin,
				Left:   cursor,
				Right:  cursor + bar.GetWidth() + spacing,
				Bottom: sbc.GetHeight(),
			}
			if len(bar.Name) > 0 {
				Draw.TextWithin(r, bar.Name, barLabelBox, axisStyle)
			}
			axisStyle.WriteToRenderer(r)
			r.MoveTo(barLabelBox.Right, canvasBox.Bottom)
			r.LineTo(barLabelBox.Right, canvasBox.Bottom+DefaultVerticalTickHeight)
			r.Stroke()
			cursor += bar.GetWidth() + spacing
		}
	}
}

func (sbc StackedBarChart) drawYAxis(r Renderer, canvasBox Box) {
	if sbc.YAxis.Show {
		axisStyle := sbc.YAxis.InheritFrom(sbc.styleDefaultsAxes())
		axisStyle.WriteToRenderer(r)
		r.MoveTo(canvasBox.Right, canvasBox.Top)
		r.LineTo(canvasBox.Right, canvasBox.Bottom)
		r.Stroke()

		r.MoveTo(canvasBox.Right, canvasBox.Bottom)
		r.LineTo(canvasBox.Right+DefaultHorizontalTickWidth, canvasBox.Bottom)
		r.Stroke()

		ticks := Sequence.Float64(1.0, 0.0, 0.2)
		for _, t := range ticks {
			axisStyle.GetStrokeOptions().WriteToRenderer(r)
			ty := canvasBox.Bottom - int(t*float64(canvasBox.Height()))
			r.MoveTo(canvasBox.Right, ty)
			r.LineTo(canvasBox.Right+DefaultHorizontalTickWidth, ty)
			r.Stroke()

			axisStyle.GetTextOptions().WriteToRenderer(r)
			text := fmt.Sprintf("%0.0f%%", t*100)

			tb := r.MeasureText(text)
			Draw.Text(r, text, canvasBox.Right+DefaultYAxisMargin+5, ty+(tb.Height()>>1), axisStyle)
		}

	}
}

func (sbc StackedBarChart) drawTitle(r Renderer) {
	if len(sbc.Title) > 0 && sbc.TitleStyle.Show {
		Draw.TextWithin(r, sbc.Title, sbc.Box(), sbc.styleDefaultsTitle())
	}
}

func (sbc StackedBarChart) getDefaultCanvasBox() Box {
	return sbc.Box()
}

func (sbc StackedBarChart) getAdjustedCanvasBox(canvasBox Box) Box {
	var totalWidth int
	for index, bar := range sbc.Bars {
		totalWidth += bar.GetWidth()
		if index < len(sbc.Bars)-1 {
			totalWidth += sbc.GetBarSpacing()
		}
	}

	return Box{
		Top:    canvasBox.Top,
		Left:   canvasBox.Left,
		Right:  canvasBox.Left + totalWidth,
		Bottom: canvasBox.Bottom,
	}
}

// Box returns the chart bounds as a box.
func (sbc StackedBarChart) Box() Box {
	dpr := sbc.Background.Padding.GetRight(10)
	dpb := sbc.Background.Padding.GetBottom(50)

	return Box{
		Top:    20,
		Left:   20,
		Right:  sbc.GetWidth() - dpr,
		Bottom: sbc.GetHeight() - dpb,
	}
}

func (sbc StackedBarChart) styleDefaultsStackedBarValue(index int) Style {
	return Style{
		StrokeColor: GetAlternateColor(index),
		StrokeWidth: 3.0,
		FillColor:   GetAlternateColor(index),
	}
}

func (sbc StackedBarChart) styleDefaultsTitle() Style {
	return sbc.TitleStyle.InheritFrom(Style{
		FontColor:           DefaultTextColor,
		Font:                sbc.GetFont(),
		FontSize:            sbc.getTitleFontSize(),
		TextHorizontalAlign: TextHorizontalAlignCenter,
		TextVerticalAlign:   TextVerticalAlignTop,
		TextWrap:            TextWrapWord,
	})
}

func (sbc StackedBarChart) getTitleFontSize() float64 {
	effectiveDimension := Math.MinInt(sbc.GetWidth(), sbc.GetHeight())
	if effectiveDimension >= 2048 {
		return 48
	} else if effectiveDimension >= 1024 {
		return 24
	} else if effectiveDimension >= 512 {
		return 18
	} else if effectiveDimension >= 256 {
		return 12
	}
	return 10
}

func (sbc StackedBarChart) styleDefaultsAxes() Style {
	return Style{
		StrokeColor:         DefaultAxisColor,
		Font:                sbc.GetFont(),
		FontSize:            DefaultAxisFontSize,
		FontColor:           DefaultAxisColor,
		TextHorizontalAlign: TextHorizontalAlignCenter,
		TextVerticalAlign:   TextVerticalAlignTop,
		TextWrap:            TextWrapWord,
	}
}
func (sbc StackedBarChart) styleDefaultsElements() Style {
	return Style{
		Font: sbc.GetFont(),
	}
}
<commit_msg>looking spiffy.<commit_after>package chart

import (
	"errors"
	"fmt"
	"io"
	"math"

	"github.com/golang/freetype/truetype"
)

// StackedBar is a bar within a StackedBarChart.
type StackedBar struct {
	Name   string
	Width  int
	Values []Value
}

// GetWidth returns the width of the bar.
func (sb StackedBar) GetWidth() int {
	if sb.Width == 0 {
		return 50
	}
	return sb.Width
}

// StackedBarChart is a chart that draws sections of a bar based on percentages.
type StackedBarChart struct {
	Title      string
	TitleStyle Style

	Width  int
	Height int
	DPI    float64

	Background Style
	Canvas     Style

	XAxis Style
	YAxis Style

	BarSpacing int

	Font        *truetype.Font
	defaultFont *truetype.Font

	Bars     []StackedBar
	Elements []Renderable
}

// GetDPI returns the dpi for the chart.
func (sbc StackedBarChart) GetDPI(defaults ...float64) float64 {
	if sbc.DPI == 0 {
		if len(defaults) > 0 {
			return defaults[0]
		}
		return DefaultDPI
	}
	return sbc.DPI
}

// GetFont returns the text font.
func (sbc StackedBarChart) GetFont() *truetype.Font {
	if sbc.Font == nil {
		return sbc.defaultFont
	}
	return sbc.Font
}

// GetWidth returns the chart width or the default value.
func (sbc StackedBarChart) GetWidth() int {
	if sbc.Width == 0 {
		return DefaultChartWidth
	}
	return sbc.Width
}

// GetHeight returns the chart height or the default value.
func (sbc StackedBarChart) GetHeight() int {
	if sbc.Height == 0 {
		return DefaultChartWidth
	}
	return sbc.Height
}

// GetBarSpacing returns the spacing between bars.
func (sbc StackedBarChart) GetBarSpacing() int {
	if sbc.BarSpacing == 0 {
		return 100
	}
	return sbc.BarSpacing
}

// Render renders the chart with the given renderer to the given io.Writer.
func (sbc StackedBarChart) Render(rp RendererProvider, w io.Writer) error {
	if len(sbc.Bars) == 0 {
		return errors.New("Please provide at least one bar.")
	}

	r, err := rp(sbc.GetWidth(), sbc.GetHeight())
	if err != nil {
		return err
	}

	if sbc.Font == nil {
		defaultFont, err := GetDefaultFont()
		if err != nil {
			return err
		}
		sbc.defaultFont = defaultFont
	}
	r.SetDPI(sbc.GetDPI(DefaultDPI))

	canvasBox := sbc.getAdjustedCanvasBox(sbc.getDefaultCanvasBox())
	sbc.drawBars(r, canvasBox)
	sbc.drawXAxis(r, canvasBox)
	sbc.drawYAxis(r, canvasBox)

	sbc.drawTitle(r)
	for _, a := range sbc.Elements {
		a(r, canvasBox, sbc.styleDefaultsElements())
	}

	return r.Save(w)
}

func (sbc StackedBarChart) drawBars(r Renderer, canvasBox Box) {
	xoffset := canvasBox.Left
	for _, bar := range sbc.Bars {
		sbc.drawBar(r, canvasBox, xoffset, bar)
		xoffset += sbc.GetBarSpacing()
	}
}

func (sbc StackedBarChart) drawBar(r Renderer, canvasBox Box, xoffset int, bar StackedBar) int {
	bxl := xoffset + Math.AbsInt(bar.GetWidth()>>1-sbc.GetBarSpacing()>>1)
	bxr := bxl + bar.GetWidth()

	normalizedBarComponents := Values(bar.Values).Normalize()
	yoffset := canvasBox.Top
	for index, bv := range normalizedBarComponents {
		barHeight := int(math.Ceil(bv.Value * float64(canvasBox.Height())))
		barBox := Box{Top: yoffset, Left: bxl, Right: bxr, Bottom: Math.MinInt(yoffset+barHeight, canvasBox.Bottom-DefaultStrokeWidth)}
		Draw.Box(r, barBox, bv.Style.InheritFrom(sbc.styleDefaultsStackedBarValue(index)))
		yoffset += barHeight
	}

	return bxr
}

func (sbc StackedBarChart) drawXAxis(r Renderer, canvasBox Box) {
	if sbc.XAxis.Show {
		axisStyle := sbc.XAxis.InheritFrom(sbc.styleDefaultsAxes())
		axisStyle.WriteToRenderer(r)

		r.MoveTo(canvasBox.Left, canvasBox.Bottom)
		r.LineTo(canvasBox.Right, canvasBox.Bottom)
		r.Stroke()

		r.MoveTo(canvasBox.Left, canvasBox.Bottom)
		r.LineTo(canvasBox.Left, canvasBox.Bottom+DefaultVerticalTickHeight)
		r.Stroke()

		cursor := canvasBox.Left
		for _, bar := range sbc.Bars {

			spacing := (sbc.GetBarSpacing() >> 1)

			barLabelBox := Box{
				Top:    canvasBox.Bottom + DefaultXAxisMargin,
				Left:   cursor,
				Right:  cursor + bar.GetWidth() + spacing,
				Bottom: sbc.GetHeight(),
			}
			if len(bar.Name) > 0 {
				Draw.TextWithin(r, bar.Name, barLabelBox, axisStyle)
			}
			axisStyle.WriteToRenderer(r)
			r.MoveTo(barLabelBox.Right, canvasBox.Bottom)
			r.LineTo(barLabelBox.Right, canvasBox.Bottom+DefaultVerticalTickHeight)
			r.Stroke()
			cursor += bar.GetWidth() + spacing
		}
	}
}

func (sbc StackedBarChart) drawYAxis(r Renderer, canvasBox Box) {
	if sbc.YAxis.Show {
		axisStyle := sbc.YAxis.InheritFrom(sbc.styleDefaultsAxes())
		axisStyle.WriteToRenderer(r)
		r.MoveTo(canvasBox.Right, canvasBox.Top)
		r.LineTo(canvasBox.Right, canvasBox.Bottom)
		r.Stroke()

		r.MoveTo(canvasBox.Right, canvasBox.Bottom)
		r.LineTo(canvasBox.Right+DefaultHorizontalTickWidth, canvasBox.Bottom)
		r.Stroke()

		ticks := Sequence.Float64(1.0, 0.0, 0.2)
		for _, t := range ticks {
			axisStyle.GetStrokeOptions().WriteToRenderer(r)
			ty := canvasBox.Bottom - int(t*float64(canvasBox.Height()))
			r.MoveTo(canvasBox.Right, ty)
			r.LineTo(canvasBox.Right+DefaultHorizontalTickWidth, ty)
			r.Stroke()

			axisStyle.GetTextOptions().WriteToRenderer(r)
			text := fmt.Sprintf("%0.0f%%", t*100)

			tb := r.MeasureText(text)
			Draw.Text(r, text, canvasBox.Right+DefaultYAxisMargin+5, ty+(tb.Height()>>1), axisStyle)
		}

	}
}

func (sbc StackedBarChart) drawTitle(r Renderer) {
	if len(sbc.Title) > 0 && sbc.TitleStyle.Show {
		Draw.TextWithin(r, sbc.Title, sbc.Box(), sbc.styleDefaultsTitle())
	}
}

func (sbc StackedBarChart) getDefaultCanvasBox() Box {
	return sbc.Box()
}

func (sbc StackedBarChart) getAdjustedCanvasBox(canvasBox Box) Box {
	var totalWidth int
	for index, bar := range sbc.Bars {
		totalWidth += bar.GetWidth()
		if index < len(sbc.Bars)-1 {
			totalWidth += sbc.GetBarSpacing()
		}
	}

	return Box{
		Top:    canvasBox.Top,
		Left:   canvasBox.Left,
		Right:  canvasBox.Left + totalWidth,
		Bottom: canvasBox.Bottom,
	}
}

// Box returns the chart bounds as a box.
func (sbc StackedBarChart) Box() Box {
	dpr := sbc.Background.Padding.GetRight(10)
	dpb := sbc.Background.Padding.GetBottom(50)

	return Box{
		Top:    20,
		Left:   20,
		Right:  sbc.GetWidth() - dpr,
		Bottom: sbc.GetHeight() - dpb,
	}
}

func (sbc StackedBarChart) styleDefaultsStackedBarValue(index int) Style {
	return Style{
		StrokeColor: GetAlternateColor(index),
		StrokeWidth: 3.0,
		FillColor:   GetAlternateColor(index),
	}
}

func (sbc StackedBarChart) styleDefaultsTitle() Style {
	return sbc.TitleStyle.InheritFrom(Style{
		FontColor:           DefaultTextColor,
		Font:                sbc.GetFont(),
		FontSize:            sbc.getTitleFontSize(),
		TextHorizontalAlign: TextHorizontalAlignCenter,
		TextVerticalAlign:   TextVerticalAlignTop,
		TextWrap:            TextWrapWord,
	})
}

func (sbc StackedBarChart) getTitleFontSize() float64 {
	effectiveDimension := Math.MinInt(sbc.GetWidth(), sbc.GetHeight())
	if effectiveDimension >= 2048 {
		return 48
	} else if effectiveDimension >= 1024 {
		return 24
	} else if effectiveDimension >= 512 {
		return 18
	} else if effectiveDimension >= 256 {
		return 12
	}
	return 10
}

func (sbc StackedBarChart) styleDefaultsAxes() Style {
	return Style{
		StrokeColor:         DefaultAxisColor,
		Font:                sbc.GetFont(),
		FontSize:            DefaultAxisFontSize,
		FontColor:           DefaultAxisColor,
		TextHorizontalAlign: TextHorizontalAlignCenter,
		TextVerticalAlign:   TextVerticalAlignTop,
		TextWrap:            TextWrapWord,
	}
}
func (sbc StackedBarChart) styleDefaultsElements() Style {
	return Style{
		Font: sbc.GetFont(),
	}
}
<|endoftext|>


<commit_before>package keeper

import (
	"context"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/validator/types"
)

func (k msgServer) ApproveDisableValidator(goCtx context.Context, msg *types.MsgApproveDisableValidator) (*types.MsgApproveDisableValidatorResponse, error) {
	ctx := sdk.UnwrapSDKContext(goCtx)

	creatorAddr, err := sdk.AccAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid creator address: (%s)", err)
	}

	validatorAddr, err := sdk.ValAddressFromBech32(msg.Address)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid validator address: (%s)", err)
	}

	// check if message creator has enough rights to approve disable validator
	if !k.dclauthKeeper.HasRole(ctx, creatorAddr, types.VoteForDisableValidatorRole) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"MsgApproveDisableValidator transaction should be signed by an account with the %s role",
			types.VoteForDisableValidatorRole,
		)
	}

	// check if proposed disable validator exists
	proposedDisableValidator, isFound := k.GetProposedDisableValidator(ctx, validatorAddr.String())
	if !isFound {
		return nil, types.NewErrProposedDisableValidatorDoesNotExist(msg.Address)
	}

	// check if disable validator already has approval form message creator
	if proposedDisableValidator.HasApprovalFrom(creatorAddr) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"Disabled validator with address=%v already has approval from=%v",
			msg.Address, msg.Creator,
		)
	}

	// append approval
	grant := types.Grant{
		Address: creatorAddr.String(),
		Time:    msg.Time,
		Info:    msg.Info,
	}

	proposedDisableValidator.Approvals = append(proposedDisableValidator.Approvals, &grant)

	// check if proposed disable validator has enough approvals
	if len(proposedDisableValidator.Approvals) == k.DisableValidatorApprovalsCount(ctx) {
		// remove disable validator
		k.RemoveProposedDisableValidator(ctx, proposedDisableValidator.Address)

		approvedDisableValidator := types.DisabledValidator{
			Address:             proposedDisableValidator.Address,
			Creator:             proposedDisableValidator.Creator,
			Approvals:           proposedDisableValidator.Approvals,
			DisabledByNodeAdmin: false,
		}

		// Disable validator
		validator, _ := k.GetValidator(ctx, validatorAddr)
		k.Jail(ctx, validator, proposedDisableValidator.Approvals[0].Info)

		k.SetDisabledValidator(ctx, approvedDisableValidator)
	} else {
		// update proposed disable validator
		k.SetProposedDisableValidator(ctx, proposedDisableValidator)
	}

	return &types.MsgApproveDisableValidatorResponse{}, nil
}
<commit_msg>Add checking for double vote for proposedDisableValidator and ApproveDisableValidator from same Trustee<commit_after>package keeper

import (
	"context"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	"github.com/zigbee-alliance/distributed-compliance-ledger/x/validator/types"
)

func (k msgServer) ApproveDisableValidator(goCtx context.Context, msg *types.MsgApproveDisableValidator) (*types.MsgApproveDisableValidatorResponse, error) {
	ctx := sdk.UnwrapSDKContext(goCtx)

	creatorAddr, err := sdk.AccAddressFromBech32(msg.Creator)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid creator address: (%s)", err)
	}

	validatorAddr, err := sdk.ValAddressFromBech32(msg.Address)
	if err != nil {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid validator address: (%s)", err)
	}

	// check if message creator has enough rights to approve disable validator
	if !k.dclauthKeeper.HasRole(ctx, creatorAddr, types.VoteForDisableValidatorRole) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"MsgApproveDisableValidator transaction should be signed by an account with the %s role",
			types.VoteForDisableValidatorRole,
		)
	}

	// check if proposed disable validator exists
	proposedDisableValidator, isFound := k.GetProposedDisableValidator(ctx, validatorAddr.String())
	if !isFound {
		return nil, types.NewErrProposedDisableValidatorDoesNotExist(msg.Address)
	}

	// check if disable validator already has reject from message creator
	if proposedDisableValidator.HasRejectDisableFrom(creatorAddr) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"Disabled validator with address=%v already has reject from=%v",
			msg.Address,
			msg.Creator,
		)
	}

	// check if disable validator already has approval form message creator
	if proposedDisableValidator.HasApprovalFrom(creatorAddr) {
		return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized,
			"Disabled validator with address=%v already has approval from=%v",
			msg.Address, msg.Creator,
		)
	}

	// append approval
	grant := types.Grant{
		Address: creatorAddr.String(),
		Time:    msg.Time,
		Info:    msg.Info,
	}

	proposedDisableValidator.Approvals = append(proposedDisableValidator.Approvals, &grant)

	// check if proposed disable validator has enough approvals
	if len(proposedDisableValidator.Approvals) == k.DisableValidatorApprovalsCount(ctx) {
		// remove disable validator
		k.RemoveProposedDisableValidator(ctx, proposedDisableValidator.Address)

		approvedDisableValidator := types.DisabledValidator{
			Address:             proposedDisableValidator.Address,
			Creator:             proposedDisableValidator.Creator,
			Approvals:           proposedDisableValidator.Approvals,
			RejectApprovals:     proposedDisableValidator.RejectApprovals,
			DisabledByNodeAdmin: false,
		}

		// Disable validator
		validator, _ := k.GetValidator(ctx, validatorAddr)
		k.Jail(ctx, validator, proposedDisableValidator.Approvals[0].Info)

		k.SetDisabledValidator(ctx, approvedDisableValidator)
	} else {
		// update proposed disable validator
		k.SetProposedDisableValidator(ctx, proposedDisableValidator)
	}

	return &types.MsgApproveDisableValidatorResponse{}, nil
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2016 All Rights Reserved.

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

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

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

package main

//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
//to be modified as well with the new ID of chaincode_example02.
//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
//hard-coding.

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

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var err error

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

	// Initialize the chaincode
	A = args[0]
	Aval, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	B = args[2]
	Bval, err = strconv.Atoi(args[3])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	// Write the state to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
    var key, value string
    var err error
    fmt.Println("Storing the parameters in hyperledger fabric...")

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

	if(len(args)%2 != 0) {
		  fmt.Printf("Incorrect number of arguments. One of the keys or values is missing.")
		  fmt.Println("")

    }else{
	     for i := 0; i < len(args); i++ {
	     if(i%2 == 0){
		     if args[i] != "" {
                  fmt.Printf("Key: %s", args[i])
				  fmt.Println("")
				  key = args[i]
				  i++
             }
		     if(i!=len(args)) {
			      fmt.Printf("Value: %s", args[i])
			      fmt.Println("")
				  value = args[i]
			 }
		     err = stub.PutState(key, []byte(value))  //write the variable into the chaincode state
			 if err != nil {
				return nil, err
			 }
		 }
    }
	}

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

    return nil, nil
}

// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if function == "delete" {
		// Deletes an entity from its state
		return t.delete(stub, args)
	}
	if function == "write" {
		fmt.Println("Calling write()")
        return t.write(stub, args)
    }

	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var X int          // Transaction value
	var err error

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

	A = args[0]
	B = args[1]

	// Get the state from the ledger
	// TODO: will be nice to have a GetAllState call to ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		return nil, errors.New("Failed to get state")
	}
	if Avalbytes == nil {
		return nil, errors.New("Entity not found")
	}
	Aval, _ = strconv.Atoi(string(Avalbytes))

	Bvalbytes, err := stub.GetState(B)
	if err != nil {
		return nil, errors.New("Failed to get state")
	}
	if Bvalbytes == nil {
		return nil, errors.New("Entity not found")
	}
	Bval, _ = strconv.Atoi(string(Bvalbytes))

	// Perform the execution
	X, err = strconv.Atoi(args[2])
	Aval = Aval - X
	Bval = Bval + X
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	//Store state for transactions
	var transacted, historyval string
	transacted = "T_"+args[0]+"|"+args[1]
	Tvalbytes, err := stub.GetState(transacted)
	if err != nil {
		return nil, errors.New("Failed to get transacted state")
	}
	if Tvalbytes == nil {
		historyval = args[2]
	}else{
		historyval = string(Tvalbytes)
		historyval = historyval+","+args[2]
	}
	err = stub.PutState(transacted, []byte(historyval))
	if err != nil {
		return nil, err
	}

	//Store state for sponsor transactions
	var s_transactions, s_history string
	s_transactions = "T_"+args[0]
	Svalbytes, err := stub.GetState(s_transactions)
	if err != nil {
		return nil, errors.New("Failed to get sponsor transacted state")
	}
	if Svalbytes == nil {
		s_history = args[1]+"|"+args[2]
	}else{
		s_history = string(Svalbytes)
		s_history = s_history+","+args[1]+"|"+args[2]
	}
	err = stub.PutState(s_transactions, []byte(s_history))
	if err != nil {
		return nil, err
	}

	//Store state for Idea transactions
	var i_transactions, i_history string
	i_transactions = "T_"+args[1]
	Ivalbytes, err := stub.GetState(i_transactions)
	if err != nil {
		return nil, errors.New("Failed to get idea transacted state")
	}
	if Ivalbytes == nil {
		i_history = args[0]+"|"+args[2]
	}else{
		i_history = string(Ivalbytes)
		i_history = i_history+","+args[0]+"|"+args[2]
	}
	err = stub.PutState(i_transactions, []byte(i_history))
	if err != nil {
		return nil, err
	}

	// Write the state back to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	A := args[0]

	// Delete the key from the state in ledger
	err := stub.DelState(A)
	if err != nil {
		return nil, errors.New("Failed to delete state")
	}

	return nil, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	/*if function != "query" {
		return nil, errors.New("Invalid query function name. Expecting \"query\"")
	}*/

	if function == "queryAll" {
		fmt.Println("Calling QueryAll()")
        return t.queryAll(stub, args)
    }

	if function == "queryTransact" {
		fmt.Println("Calling QueryTransact()")
        return t.queryTransact(stub, args)
    }

	var A string // Entities
	var err error

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

	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		Avalbytes = []byte("0")
		//jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		//return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) queryAll(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	//var A string // Entities
	//var err error

	/*if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}*/
    var RetValue []byte
	var buffer bytes.Buffer
    var jsonRespString string
		for i := 0; i < len(args); i++ {
		    Avalbytes, err := stub.GetState(args[i])
			if err != nil {
				jsonResp := "{\"Error\":\"Failed to get state for " + args[i] + "\"}"
				return nil, errors.New(jsonResp)
			}

			if Avalbytes == nil {
				Avalbytes = []byte("0")
				//jsonResp := "{\"Error\":\"Nil amount for " + args[i] + "\"}"
				//return nil, errors.New(jsonResp)
			}
			if(i!=len(args)-1) {
			   jsonRespString =  string(Avalbytes)+","
			}else{
			   jsonRespString =  string(Avalbytes)
			}
			buffer.WriteString(jsonRespString)
			RetValue = []byte(buffer.String())

		}
		jsonResp := "{"+buffer.String()+"}"
		fmt.Printf("Query Response:%s\n", jsonResp)
		return RetValue, nil

	/*
	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
	*/
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) queryTransact(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	//var A string // Entities
	//var err error

	/*if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}*/
    var RetValue []byte
	var buffer bytes.Buffer
    var jsonRespString, queryparam string
	queryparam = "T_"+args[0]

		Tvalbytes, err := stub.GetState(queryparam)
		if err != nil {
			jsonResp := "{\"Error\":\"Failed to get state for " + args[0] + "\"}"
			return nil, errors.New(jsonResp)
		}

		if Tvalbytes == nil {
			Tvalbytes = []byte("0")
			//jsonResp := "{\"Error\":\"Nil amount for " + args[i] + "\"}"
			//return nil, errors.New(jsonResp)
		}

		jsonRespString =  string(Tvalbytes)
		buffer.WriteString(jsonRespString)
		RetValue = []byte(buffer.String())
		jsonResp := "{"+buffer.String()+"}"
		fmt.Printf("Query Response:%s\n", jsonResp)
		return RetValue, nil

	/*
	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
	*/
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
<commit_msg>Updated write method<commit_after>/*
Copyright IBM Corp. 2016 All Rights Reserved.

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

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

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

package main

//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
//to be modified as well with the new ID of chaincode_example02.
//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
//hard-coding.

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

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var err error

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

	// Initialize the chaincode
	A = args[0]
	Aval, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	B = args[2]
	Bval, err = strconv.Atoi(args[3])
	if err != nil {
		return nil, errors.New("Expecting integer value for asset holding")
	}
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	// Write the state to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

func (t *SimpleChaincode) write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
    var key, value string
    var err error
    fmt.Println("Storing the parameters in hyperledger fabric...")

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

	if(len(args)%2 != 0) {
		  fmt.Printf("Incorrect number of arguments. One of the keys or values is missing.")
		  fmt.Println("")

    }else{
	     for i := 0; i < len(args); i++ {
	     if(i%2 == 0){
		     if args[i] != "" {
                  fmt.Printf("Key: %s", args[i])
				  fmt.Println("")
				  key = args[i]
				  i++
             }
		     if(i!=len(args)) {
			      fmt.Printf("Value: %s", args[i])
			      fmt.Println("")
				  value = args[i]
			 }

			 //check if the state exists. If not initialize the state
			 Avalbytes, err := stub.GetState(key)
			if err != nil {
				jsonResp := "{\"Error\":\"Failed to get state for " + key + "\"}"
				return nil, errors.New(jsonResp)
			}

			if Avalbytes == nil {
				Avalbytes = []byte("0")
				err = stub.PutState(key, Avalbytes)

				//jsonResp := "{\"Error\":\"Nil amount for " + key + "\"}"
				//return nil, errors.New(jsonResp)
			}

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

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

    return nil, nil
}

// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if function == "delete" {
		// Deletes an entity from its state
		return t.delete(stub, args)
	}
	if function == "write" {
		fmt.Println("Calling write()")
        return t.write(stub, args)
    }

	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var X int          // Transaction value
	var err error

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

	A = args[0]
	B = args[1]

	// Get the state from the ledger
	// TODO: will be nice to have a GetAllState call to ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		return nil, errors.New("Failed to get state")
	}
	if Avalbytes == nil {
		return nil, errors.New("Entity not found")
	}
	Aval, _ = strconv.Atoi(string(Avalbytes))

	Bvalbytes, err := stub.GetState(B)
	if err != nil {
		return nil, errors.New("Failed to get state")
	}
	if Bvalbytes == nil {
		return nil, errors.New("Entity not found")
	}
	Bval, _ = strconv.Atoi(string(Bvalbytes))

	// Perform the execution
	X, err = strconv.Atoi(args[2])
	Aval = Aval - X
	Bval = Bval + X
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	//Store state for transactions
	var transacted, historyval string
	transacted = "T_"+args[0]+"|"+args[1]
	Tvalbytes, err := stub.GetState(transacted)
	if err != nil {
		return nil, errors.New("Failed to get transacted state")
	}
	if Tvalbytes == nil {
		historyval = args[2]
	}else{
		historyval = string(Tvalbytes)
		historyval = historyval+","+args[2]
	}
	err = stub.PutState(transacted, []byte(historyval))
	if err != nil {
		return nil, err
	}

	//Store state for sponsor transactions
	var s_transactions, s_history string
	s_transactions = "T_"+args[0]
	Svalbytes, err := stub.GetState(s_transactions)
	if err != nil {
		return nil, errors.New("Failed to get sponsor transacted state")
	}
	if Svalbytes == nil {
		s_history = args[1]+"|"+args[2]
	}else{
		s_history = string(Svalbytes)
		s_history = s_history+","+args[1]+"|"+args[2]
	}
	err = stub.PutState(s_transactions, []byte(s_history))
	if err != nil {
		return nil, err
	}

	//Store state for Idea transactions
	var i_transactions, i_history string
	i_transactions = "T_"+args[1]
	Ivalbytes, err := stub.GetState(i_transactions)
	if err != nil {
		return nil, errors.New("Failed to get idea transacted state")
	}
	if Ivalbytes == nil {
		i_history = args[0]+"|"+args[2]
	}else{
		i_history = string(Ivalbytes)
		i_history = i_history+","+args[0]+"|"+args[2]
	}
	err = stub.PutState(i_transactions, []byte(i_history))
	if err != nil {
		return nil, err
	}

	// Write the state back to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return nil, err
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	A := args[0]

	// Delete the key from the state in ledger
	err := stub.DelState(A)
	if err != nil {
		return nil, errors.New("Failed to delete state")
	}

	return nil, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	/*if function != "query" {
		return nil, errors.New("Invalid query function name. Expecting \"query\"")
	}*/

	if function == "queryAll" {
		fmt.Println("Calling QueryAll()")
        return t.queryAll(stub, args)
    }

	if function == "queryTransact" {
		fmt.Println("Calling QueryTransact()")
        return t.queryTransact(stub, args)
    }

	var A string // Entities
	var err error

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

	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		Avalbytes = []byte("0")
		//jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		//return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) queryAll(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	//var A string // Entities
	//var err error

	/*if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}*/
    var RetValue []byte
	var buffer bytes.Buffer
    var jsonRespString string
		for i := 0; i < len(args); i++ {
		    Avalbytes, err := stub.GetState(args[i])
			if err != nil {
				jsonResp := "{\"Error\":\"Failed to get state for " + args[i] + "\"}"
				return nil, errors.New(jsonResp)
			}

			if Avalbytes == nil {
				Avalbytes = []byte("0")
				//jsonResp := "{\"Error\":\"Nil amount for " + args[i] + "\"}"
				//return nil, errors.New(jsonResp)
			}
			if(i!=len(args)-1) {
			   jsonRespString =  string(Avalbytes)+","
			}else{
			   jsonRespString =  string(Avalbytes)
			}
			buffer.WriteString(jsonRespString)
			RetValue = []byte(buffer.String())

		}
		jsonResp := "{"+buffer.String()+"}"
		fmt.Printf("Query Response:%s\n", jsonResp)
		return RetValue, nil

	/*
	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
	*/
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) queryTransact(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	//var A string // Entities
	//var err error

	/*if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
	}*/
    var RetValue []byte
	var buffer bytes.Buffer
    var jsonRespString, queryparam string
	queryparam = "T_"+args[0]

		Tvalbytes, err := stub.GetState(queryparam)
		if err != nil {
			jsonResp := "{\"Error\":\"Failed to get state for " + args[0] + "\"}"
			return nil, errors.New(jsonResp)
		}

		if Tvalbytes == nil {
			Tvalbytes = []byte("0")
			//jsonResp := "{\"Error\":\"Nil amount for " + args[i] + "\"}"
			//return nil, errors.New(jsonResp)
		}

		jsonRespString =  string(Tvalbytes)
		buffer.WriteString(jsonRespString)
		RetValue = []byte(buffer.String())
		jsonResp := "{"+buffer.String()+"}"
		fmt.Printf("Query Response:%s\n", jsonResp)
		return RetValue, nil

	/*
	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	if Avalbytes == nil {
		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return Avalbytes, nil
	*/
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

// Opts ...
type Opts struct {
	debugFlag    bool
	helpFlag     bool
	loadFlag     bool
	prettyFlag   bool
	scriptFlag   bool
	tableFlag    bool
	typeFlag     bool
	versionFlag  bool
	planetsCount int
	command      string
	currentDBDet string
	currentDet   string
	scriptName   string
	template     string
	planets      []string
}

/**
*	Returns the contents of args in following order:
*	prettyprint flag
*	script flag
*	script path
*	command
*	planets
 */
func (opts *Opts) procArgs(args []string) {
	flag.BoolVar(&opts.helpFlag, "h", false, "help")
	flag.BoolVar(&opts.prettyFlag, "pp", false, "prettyprint")
	flag.BoolVar(&opts.typeFlag, "t", false, "type")
	flag.BoolVar(&opts.debugFlag, "d", false, "verbose")
	flag.BoolVar(&opts.loadFlag, "l", false, "ssh profile loading")
	flag.BoolVar(&opts.versionFlag, "v", false, "version")
	flag.StringVar(&opts.template, "tp", "", "filename of template")
	flag.StringVar(&opts.scriptName, "s", "", "name of the script(regardless wether db or bash) to be executed")
	flag.StringVar(&opts.command, "c", "", "command to be executed in quotes")
	flag.Parse()
	opts.scriptFlag = !(opts.scriptName == "")
	opts.tableFlag = !(opts.template == "")
	if opts.scriptFlag && !(opts.command == "") {
		var err error
		throwErrExt(err, "providing both a script AND a command is not possible")
	}

	planets := flag.Args()
	opts.command = strings.TrimSuffix(strings.TrimPrefix(opts.command, "\""), "\"")
	opts.template = strings.TrimSuffix(strings.TrimPrefix(opts.template, "\""), "\"")
	opts.scriptName = strings.TrimSuffix(strings.TrimPrefix(opts.scriptName, "\""), "\"")

	for _, argument := range planets {
		if isSupported(argument) {
			opts.planets = append(opts.planets, argument)
			opts.planetsCount++
		} else {
			fmt.Fprintf(os.Stderr, "This Type of Connection is not supported.")
			os.Exit(1)
		}
	}
	if len(args) == 1 {
		opts.helpFlag = true
	}

}

/**
*	Splits the given connectiondetails and returns the hostname
*	@params:
*		connDet: Connection details in following form: user@hostname
*	@return: hostname
 */
func getHost(connDet string) string {
	toReturn := strings.Split(connDet, "@")
	return toReturn[1]
}

/**
*	Splits the given connectiondetails and returns the user
*	@params:
*		connDet: Connection details in following form: user@hostname
*	@return: user
 */
func getUser(connDet string) string {
	toReturn := strings.Split(connDet, "@")
	return toReturn[0]
}

/**
*	Returns the type of a given planet
*	@params:
*		id: The planets id
*	@return: The planets type
 */
func getType(id string) string {
	cmd := exec.Command("ff", "-t", id)
	out, err := cmd.CombinedOutput()
	if err != nil {
		throwErrOut(out, err)
	}
	return strings.TrimSpace(string(out))
}

/**
*	Returns the connection details to a given planet
*	@params:
*		id: The planets id
*	@return: The connection details to the planet
 */
func getPlanetDetails(id string) string {
	cmd := exec.Command("ff", id, "-f=pqdb")
	out, err := cmd.CombinedOutput()
	if err != nil {
		throwErrOut(out, err)
	}
	return strings.TrimSpace(string(out))
}

/**
*	counts the supported planets in a list of planets
 */
func countSupported(planets []string) int {
	i := 0
	for _, planet := range planets {
		if getType(planet) == linuxServer {
			i++
		}
	}
	return i
}

/**
*	checks, wether a planet is supported by goo or not
 */
func isSupported(planet string) bool {
	switch getType(planet) {
	case linuxServer:
		return true
	case database:
		return true
	case webServer:
		return false
	default:
		return false

	}

}

func getMaxLength(toProcess string) int {
	_ = toProcess
	return 0
}

/**
*	splits db details (dbID:user@host) and returns them as dbID,user@host
 */
func procDBDets(dbDet string) (string, string) {
	parts := strings.Split(dbDet, ":")
	return parts[0], parts[1]
}
<commit_msg>shortened flags<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

// Opts ...
type Opts struct {
	debugFlag    bool
	helpFlag     bool
	loadFlag     bool
	prettyFlag   bool
	scriptFlag   bool
	tableFlag    bool
	typeFlag     bool
	versionFlag  bool
	planetsCount int
	command      string
	currentDBDet string
	currentDet   string
	scriptName   string
	template     string
	planets      []string
}

/**
*	Returns the contents of args in following order:
*	prettyprint flag
*	script flag
*	script path
*	command
*	planets
 */
func (opts *Opts) procArgs(args []string) {
	flag.BoolVar(&opts.helpFlag, "h", false, "help")
	flag.BoolVar(&opts.prettyFlag, "p", false, "prettyprint")
	flag.BoolVar(&opts.typeFlag, "t", false, "type")
	flag.BoolVar(&opts.debugFlag, "d", false, "verbose")
	flag.BoolVar(&opts.loadFlag, "l", false, "ssh profile loading")
	flag.BoolVar(&opts.versionFlag, "v", false, "version")
	flag.StringVar(&opts.template, "t", "", "filename of template")
	flag.StringVar(&opts.scriptName, "s", "", "name of the script(regardless wether db or bash) to be executed")
	flag.StringVar(&opts.command, "c", "", "command to be executed in quotes")
	flag.Parse()
	opts.scriptFlag = !(opts.scriptName == "")
	opts.tableFlag = !(opts.template == "")
	if opts.scriptFlag && !(opts.command == "") {
		var err error
		throwErrExt(err, "providing both a script AND a command is not possible")
	}

	planets := flag.Args()
	opts.command = strings.TrimSuffix(strings.TrimPrefix(opts.command, "\""), "\"")
	opts.template = strings.TrimSuffix(strings.TrimPrefix(opts.template, "\""), "\"")
	opts.scriptName = strings.TrimSuffix(strings.TrimPrefix(opts.scriptName, "\""), "\"")

	for _, argument := range planets {
		if isSupported(argument) {
			opts.planets = append(opts.planets, argument)
			opts.planetsCount++
		} else {
			fmt.Fprintf(os.Stderr, "This Type of Connection is not supported.")
			os.Exit(1)
		}
	}
	if len(args) == 1 {
		opts.helpFlag = true
	}

}

/**
*	Splits the given connectiondetails and returns the hostname
*	@params:
*		connDet: Connection details in following form: user@hostname
*	@return: hostname
 */
func getHost(connDet string) string {
	toReturn := strings.Split(connDet, "@")
	return toReturn[1]
}

/**
*	Splits the given connectiondetails and returns the user
*	@params:
*		connDet: Connection details in following form: user@hostname
*	@return: user
 */
func getUser(connDet string) string {
	toReturn := strings.Split(connDet, "@")
	return toReturn[0]
}

/**
*	Returns the type of a given planet
*	@params:
*		id: The planets id
*	@return: The planets type
 */
func getType(id string) string {
	cmd := exec.Command("ff", "-t", id)
	out, err := cmd.CombinedOutput()
	if err != nil {
		throwErrOut(out, err)
	}
	return strings.TrimSpace(string(out))
}

/**
*	Returns the connection details to a given planet
*	@params:
*		id: The planets id
*	@return: The connection details to the planet
 */
func getPlanetDetails(id string) string {
	cmd := exec.Command("ff", id, "-f=pqdb")
	out, err := cmd.CombinedOutput()
	if err != nil {
		throwErrOut(out, err)
	}
	return strings.TrimSpace(string(out))
}

/**
*	counts the supported planets in a list of planets
 */
func countSupported(planets []string) int {
	i := 0
	for _, planet := range planets {
		if getType(planet) == linuxServer {
			i++
		}
	}
	return i
}

/**
*	checks, wether a planet is supported by goo or not
 */
func isSupported(planet string) bool {
	switch getType(planet) {
	case linuxServer:
		return true
	case database:
		return true
	case webServer:
		return false
	default:
		return false

	}

}

func getMaxLength(toProcess string) int {
	_ = toProcess
	return 0
}

/**
*	splits db details (dbID:user@host) and returns them as dbID,user@host
 */
func procDBDets(dbDet string) (string, string) {
	parts := strings.Split(dbDet, ":")
	return parts[0], parts[1]
}
<|endoftext|>