<commit_before>// Copyright 2015 The Prometheus 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.

// +build !nofilesystem

package collector

import (
	"bytes"
	"unsafe"

	"github.com/go-kit/kit/log/level"
	"golang.org/x/sys/unix"
)

const (
	defIgnoredMountPoints = "^/(dev)($|/)"
	defIgnoredFSTypes     = "^devfs$"
	readOnly              = 0x1 // MNT_RDONLY
	noWait                = 0x2 // MNT_NOWAIT
)

func gostring(b []int8) string {
	bb := *(*[]byte)(unsafe.Pointer(&b))
	idx := bytes.IndexByte(bb, 0)
	if idx < 0 {
		return ""
	}
	return string(bb[:idx])
}

// Expose filesystem fullness.
func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
	n, err := unix.Getfsstat(nil, noWait)
	if err != nil {
		return nil, err
	}
	buf := make([]unix.Statfs_t, n)
	_, err = unix.Getfsstat(buf, noWait)
	if err != nil {
		return nil, err
	}
	stats := []filesystemStats{}
	for _, fs := range buf {
		mountpoint := gostring(fs.Mntonname[:])
		if c.ignoredMountPointsPattern.MatchString(mountpoint) {
			level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint)
			continue
		}

		device := gostring(fs.Mntfromname[:])
		fstype := gostring(fs.Fstypename[:])
		if c.ignoredFSTypesPattern.MatchString(fstype) {
			level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype)
			continue
		}

		var ro float64
		if (fs.Flags & readOnly) != 0 {
			ro = 1
		}

		stats = append(stats, filesystemStats{
			labels: filesystemLabels{
				device:     device,
				mountPoint: rootfsStripPrefix(mountpoint),
				fsType:     fstype,
			},
			size:      float64(fs.Blocks) * float64(fs.Bsize),
			free:      float64(fs.Bfree) * float64(fs.Bsize),
			avail:     float64(fs.Bavail) * float64(fs.Bsize),
			files:     float64(fs.Files),
			filesFree: float64(fs.Ffree),
			ro:        ro,
		})
	}
	return stats, nil
}
<commit_msg>Update filesystem freebsd<commit_after>// Copyright 2015 The Prometheus 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.

// +build !nofilesystem

package collector

import (
	"github.com/go-kit/kit/log/level"
	"golang.org/x/sys/unix"
)

const (
	defIgnoredMountPoints = "^/(dev)($|/)"
	defIgnoredFSTypes     = "^devfs$"
	readOnly              = 0x1 // MNT_RDONLY
	noWait                = 0x2 // MNT_NOWAIT
)

// Expose filesystem fullness.
func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
	n, err := unix.Getfsstat(nil, noWait)
	if err != nil {
		return nil, err
	}
	buf := make([]unix.Statfs_t, n)
	_, err = unix.Getfsstat(buf, noWait)
	if err != nil {
		return nil, err
	}
	stats := []filesystemStats{}
	for _, fs := range buf {
		mountpoint := string(fs.Mntonname[:])
		if c.ignoredMountPointsPattern.MatchString(mountpoint) {
			level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint)
			continue
		}

		device := string(fs.Mntfromname[:])
		fstype := string(fs.Fstypename[:])
		if c.ignoredFSTypesPattern.MatchString(fstype) {
			level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype)
			continue
		}

		var ro float64
		if (fs.Flags & readOnly) != 0 {
			ro = 1
		}

		stats = append(stats, filesystemStats{
			labels: filesystemLabels{
				device:     device,
				mountPoint: rootfsStripPrefix(mountpoint),
				fsType:     fstype,
			},
			size:      float64(fs.Blocks) * float64(fs.Bsize),
			free:      float64(fs.Bfree) * float64(fs.Bsize),
			avail:     float64(fs.Bavail) * float64(fs.Bsize),
			files:     float64(fs.Files),
			filesFree: float64(fs.Ffree),
			ro:        ro,
		})
	}
	return stats, nil
}
<|endoftext|>


<commit_before>// Package v1 implements the first version of the Ripple API.
package v1

import (
	"database/sql"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/osuripple/api/common"
)

type userData struct {
	ID             int       `json:"id"`
	Username       string    `json:"username"`
	UsernameAKA    string    `json:"username_aka"`
	RegisteredOn   time.Time `json:"registered_on"`
	Rank           int       `json:"rank"`
	LatestActivity time.Time `json:"latest_activity"`
	Country        string    `json:"country"`
	Badges         []int     `json:"badges"`
}

// UserGET is the API handler for GET /user/:id
func UserGET(md common.MethodData) (r common.Response) {
	var err error
	var uid int
	uidStr := md.C.Param("id")
	if uidStr == "self" {
		uid = md.User.UserID
	} else {
		uid, err = strconv.Atoi(uidStr)
		if err != nil {
			r.Code = 400
			r.Message = fmt.Sprintf("%s ain't a number", uidStr)
			return
		}
	}

	user := userData{}

	registeredOn := int64(0)
	latestActivity := int64(0)
	var badges string
	var showcountry bool
	err = md.DB.QueryRow("SELECT users.id, users.username, register_datetime, rank, latest_activity, users_stats.username_aka, users_stats.badges_shown, users_stats.country, users_stats.show_country FROM users LEFT JOIN users_stats ON users.id=users_stats.id WHERE users.id=?", uid).Scan(
		&user.ID, &user.Username, &registeredOn, &user.Rank, &latestActivity, &user.UsernameAKA, &badges, &user.Country, &showcountry)
	switch {
	case err == sql.ErrNoRows:
		r.Code = 404
		r.Message = "No such user was found!"
		return
	case err != nil:
		md.C.Error(err)
		r = Err500
		return
	}

	user.RegisteredOn = time.Unix(registeredOn, 0)
	user.LatestActivity = time.Unix(latestActivity, 0)

	badgesSl := strings.Split(badges, ",")
	for _, badge := range badgesSl {
		if badge != "" && badge != "0" {
			// We are ignoring errors because who really gives a shit if something's gone wrong on our end in this
			// particular thing, we can just silently ignore this.
			nb, err := strconv.Atoi(badge)
			if err == nil && nb != 0 {
				user.Badges = append(user.Badges, nb)
			}
		}
	}

	if !showcountry {
		user.Country = "XX"
	}

	r.Code = 200
	r.Data = user
	return
}
<commit_msg>Show country if we have confidential privileges and we're looking at our user<commit_after>// Package v1 implements the first version of the Ripple API.
package v1

import (
	"database/sql"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/osuripple/api/common"
)

type userData struct {
	ID             int       `json:"id"`
	Username       string    `json:"username"`
	UsernameAKA    string    `json:"username_aka"`
	RegisteredOn   time.Time `json:"registered_on"`
	Rank           int       `json:"rank"`
	LatestActivity time.Time `json:"latest_activity"`
	Country        string    `json:"country"`
	Badges         []int     `json:"badges"`
}

// UserGET is the API handler for GET /user/:id
func UserGET(md common.MethodData) (r common.Response) {
	var err error
	var uid int
	uidStr := md.C.Param("id")
	if uidStr == "self" {
		uid = md.User.UserID
	} else {
		uid, err = strconv.Atoi(uidStr)
		if err != nil {
			r.Code = 400
			r.Message = fmt.Sprintf("%s ain't a number", uidStr)
			return
		}
	}

	user := userData{}

	registeredOn := int64(0)
	latestActivity := int64(0)
	var badges string
	var showcountry bool
	err = md.DB.QueryRow("SELECT users.id, users.username, register_datetime, rank, latest_activity, users_stats.username_aka, users_stats.badges_shown, users_stats.country, users_stats.show_country FROM users LEFT JOIN users_stats ON users.id=users_stats.id WHERE users.id=?", uid).Scan(
		&user.ID, &user.Username, &registeredOn, &user.Rank, &latestActivity, &user.UsernameAKA, &badges, &user.Country, &showcountry)
	switch {
	case err == sql.ErrNoRows:
		r.Code = 404
		r.Message = "No such user was found!"
		return
	case err != nil:
		md.C.Error(err)
		r = Err500
		return
	}

	user.RegisteredOn = time.Unix(registeredOn, 0)
	user.LatestActivity = time.Unix(latestActivity, 0)

	badgesSl := strings.Split(badges, ",")
	for _, badge := range badgesSl {
		if badge != "" && badge != "0" {
			// We are ignoring errors because who really gives a shit if something's gone wrong on our end in this
			// particular thing, we can just silently ignore this.
			nb, err := strconv.Atoi(badge)
			if err == nil && nb != 0 {
				user.Badges = append(user.Badges, nb)
			}
		}
	}

	// If the user wants to stay anonymous, don't show their country.
	// This can be overriden if we have the ReadConfidential privilege and the user we are accessing is the token owner.
	if !(showcountry || (md.User.Privileges.HasPrivilegeReadConfidential() && user.ID == md.User.UserID)) {
		user.Country = "XX"
	}

	r.Code = 200
	r.Data = user
	return
}
<|endoftext|>


<commit_before>package middleware

import (
	"net/http"
)

// Interface is the shared contract for all middlesware, and allows middlesware
// to wrap handlers.
type Interface interface {
	Wrap(http.Handler) http.Handler
}

// Func is to Interface as http.HandlerFunc is to http.Handler
type Func func(http.Handler) http.Handler

// Wrap implements Interface
func (m Func) Wrap(next http.Handler) http.Handler {
	return m(next)
}

// Merge produces a middleware that applies multiple middlesware in turn;
// ie Merge(f,g,h).Wrap(handler) == f.Wrap(g.Wrap(h.Wrap(handler)))
func Merge(middlesware ...Interface) Interface {
	return Func(func(next http.Handler) http.Handler {
		for i := len(middlesware) - 1; i >= 0; i-- {
			next = middlesware[i].Wrap(next)
		}
		return next
	})
}
<commit_msg>Add Indentity middleware<commit_after>package middleware

import (
	"net/http"
)

// Interface is the shared contract for all middlesware, and allows middlesware
// to wrap handlers.
type Interface interface {
	Wrap(http.Handler) http.Handler
}

// Func is to Interface as http.HandlerFunc is to http.Handler
type Func func(http.Handler) http.Handler

// Wrap implements Interface
func (m Func) Wrap(next http.Handler) http.Handler {
	return m(next)
}

// Identity is an Interface which doesn't do anything.
var Identity Interface = Func(func(h http.Handler) http.Handler { return h })

// Merge produces a middleware that applies multiple middlesware in turn;
// ie Merge(f,g,h).Wrap(handler) == f.Wrap(g.Wrap(h.Wrap(handler)))
func Merge(middlesware ...Interface) Interface {
	return Func(func(next http.Handler) http.Handler {
		for i := len(middlesware) - 1; i >= 0; i-- {
			next = middlesware[i].Wrap(next)
		}
		return next
	})
}
<|endoftext|>


<commit_before>package asana

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/manishrjain/asanawarrior/x"
	"github.com/pkg/errors"
)

var token = flag.String("token", "", "Token provided by Asana.")
var domain = flag.String("domain", "", "Workspace name, generally your domain name in Asana.")
var cache *acache = new(acache)

const (
	prefix = "https://app.asana.com/api/1.0"
	stamp  = "2006-01-02T15:04:05.999Z"
)

func runRequest(method, url string) ([]byte, error) {
RUNLOOP:
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Add("Authorization", "Bearer "+*token)
	client := &http.Client{
		Timeout: 10 * time.Minute,
	}

	resp, err := client.Do(req)
	statusCode := resp.StatusCode
	if err != nil || statusCode != http.StatusOK {
		log.Printf("runRequest method: [%v] url: [%v] status: [%v] err: [%v]", method, url, http.StatusText(statusCode), err)
		time.Sleep(5 * time.Second)
		goto RUNLOOP
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

func runGetter(i interface{}, suffix string, fields ...string) error {
	url := fmt.Sprintf("%s/%s?opt_fields=%s", prefix, suffix, strings.Join(fields, ","))
	body, err := runRequest("GET", url)
	if err != nil {
		return errors.Wrapf(err, "runGetter: %q", body)
	}
	if err := json.Unmarshal(body, i); err != nil {
		return errors.Wrapf(err, "Unmarshal: %q", body)
	}
	return nil
}

type Basic struct {
	Id    uint64 `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}
type BasicData struct {
	Data []Basic `json:"data"`
}
type BasicDataOne struct {
	Data Basic `json:"data"`
}

func getVarious(suffix string, opts ...string) ([]Basic, error) {
	var bd BasicData
	if err := runGetter(&bd, suffix, opts...); err != nil {
		return nil, err
	}
	return bd.Data, nil
}

type psec struct {
	Project Basic `json:"project"`
	Section Basic `json:"section"`
}

type task struct {
	Basic
	Assignee    Basic   `json:"assignee"`
	Tags        []Basic `json:"tags"`
	CompletedAt string  `json:"completed_at"`
	ModifiedAt  string  `json:"modified_at"`
	CreatedAt   string  `json:"created_at"`
	Memberships []psec  `json:"memberships"`
}

type tasks struct {
	Data []task `json:"data"`
}

type oneTask struct {
	Data task `json:"data"`
}

func convert(tsk task, proj, section string) (x.WarriorTask, error) {
	e := x.WarriorTask{}

	mts, err := time.Parse(stamp, tsk.ModifiedAt)
	if err != nil {
		return e, errors.Wrap(err, "asana modified at")
	}
	cts, err := time.Parse(stamp, tsk.CreatedAt)
	if err != nil {
		return e, errors.Wrap(err, "asana created at")
	}
	var dts time.Time
	if len(tsk.CompletedAt) > 0 {
		dts, err = time.Parse(stamp, tsk.CompletedAt)
		if err != nil {
			return e, errors.Wrap(err, "asana completed at")
		}
	}

	wt := x.WarriorTask{
		Name:      tsk.Name,
		Project:   proj,
		Xid:       tsk.Id,
		Assignee:  cache.User(tsk.Assignee.Id),
		Modified:  mts,
		Created:   cts,
		Completed: dts,
		Section:   section,
	}
	for _, tag := range tsk.Tags {
		wt.Tags = append(wt.Tags, cache.Tag(tag.Id))
	}
	return wt, nil
}

func getTasks(proj Basic, out chan x.WarriorTask, errc chan error) {
	var sectionName string
	var t tasks
	if err := runGetter(&t, fmt.Sprintf("projects/%d/tasks", proj.Id),
		"assignee,name,tags,completed_at,modified_at,created_at"); err != nil {
		errc <- errors.Wrapf(err, "getTasks for project: %v", proj.Name)
		return
	}

	for _, tsk := range t.Data {
		if len(tsk.Name) == 0 {
			// Don't sync such tasks.
			continue
		}
		if strings.HasSuffix(tsk.Name, ":") {
			sec := Basic{
				Id:   tsk.Id,
				Name: tsk.Name,
			}
			sectionName = cache.AddSection(proj.Id, sec)
			continue
		}

		wt, err := convert(tsk, proj.Name, sectionName)
		if err != nil {
			errc <- errors.Wrapf(err, "convert: getTasks for project: %v", proj.Name)
			return
		}
		out <- wt
	}
	errc <- nil
}

func GetTasks() ([]x.WarriorTask, error) {
	if err := cache.update(); err != nil {
		return nil, errors.Wrap(err, "cache.update")
	}

	out := make(chan x.WarriorTask, 100)
	projects := cache.Projects()
	errc := make(chan error, len(projects))
	for _, proj := range projects {
		go getTasks(proj, out, errc)
	}

	// Asana can send back the same task multiple times, if it's part of multiple projects.
	// So, let's dedup them.
	seen := make(map[uint64]bool)
	wtasks := make([]x.WarriorTask, 0, 100)
	done := make(chan struct{})
	go func() {
		for wt := range out {
			if _, has := seen[wt.Xid]; has {
				// ignore
				continue
			}
			wtasks = append(wtasks, wt)
			seen[wt.Xid] = true
		}
		done <- struct{}{}
	}()

	var rerr error
	for _ = range projects {
		if err := <-errc; err != nil {
			rerr = err
		}
	}
	close(out)
	<-done // Wait for all tasks to be picked up by goroutine.
	return wtasks, rerr
}

// runPost would run a PUT or POST to Asana. No locks should be acquired.
func runPost(method, suffix string, values url.Values) ([]byte, error) {
POSTLOOP:
	url := fmt.Sprintf("%s/%s", prefix, suffix)
	fmt.Println(url, values.Encode())
	req, err := http.NewRequest(method, url, bytes.NewBufferString(values.Encode()))
	if err != nil {
		log.Fatal(errors.Wrap(err, "runPost http.NewRequest"))
	}

	req.Header.Add("Authorization", "Bearer "+*token)
	req.Header.Add("content-type", "application/x-www-form-urlencoded")
	client := &http.Client{
		Timeout: 10 * time.Minute,
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("runPost url: [%v] err: [%v]", url, err)
		time.Sleep(5 * time.Second)
		goto POSTLOOP
	}
	defer resp.Body.Close()

	return ioutil.ReadAll(resp.Body)
}

func toTagIds(tnames []string) []string {
	var tags []string
	for _, t := range tnames {
		tid := cache.TagId(t)
		if tid == 0 {
			tid = cache.CreateTag(t)
			fmt.Printf("New Tag created. ID: %d", tid)
		}
		if tid > 0 {
			tags = append(tags, strconv.FormatUint(tid, 10))
		}
	}
	return tags
}

func removeProject(tid, pid uint64) error {
	v := url.Values{}
	v.Add("project", strconv.FormatUint(pid, 10))
	_, err := runPost("POST", fmt.Sprintf("tasks/%d/removeProject", tid), v)
	return err
}

func updateSection(tid, pid uint64, section string) error {
	v := url.Values{}
	v.Add("project", strconv.FormatUint(pid, 10))

	sid := cache.SectionId(pid, section)
	if sid > 0 {
		v.Add("section", strconv.FormatUint(sid, 10))
	}

	_, err := runPost("POST", fmt.Sprintf("tasks/%d/addProject", tid), v)
	return err
}

func AddNew(wt x.WarriorTask) (x.WarriorTask, error) {
	e := x.WarriorTask{}

	// Ensure that project actually exists before proceeding.
	pid := cache.ProjectId(wt.Project)
	if pid == 0 {
		return e, fmt.Errorf("Project not found: %v", wt.Project)
	}

	v := url.Values{}
	v.Add("workspace", strconv.FormatUint(cache.Workspace(), 10))
	v.Add("name", wt.Name)
	aid := cache.UserId(wt.Assignee)
	if aid > 0 {
		v.Add("assignee", strconv.FormatUint(aid, 10))
	}
	if !wt.Completed.IsZero() {
		v.Add("completed", "true")
	}

	tags := toTagIds(wt.Tags)
	v.Add("tags", strings.Join(tags, ","))
	resp, err := runPost("POST", "tasks", v)
	if err != nil {
		return e, errors.Wrap(err, "AddNew runPost")
	}
	fmt.Println(string(resp))

	var ot oneTask
	if err := json.Unmarshal(resp, &ot); err != nil {
		return e, errors.Wrap(err, "AddNew unmarshal")
	}
	if ot.Data.Id == 0 {
		return e, fmt.Errorf("Unable to find ID assigned by Asana: %+v", ot.Data)
	}

	// Now set the project and section.
	if err := updateSection(ot.Data.Id, pid, wt.Section); err != nil {
		return e, errors.Wrap(err, "AddNew updateSection")
	}

	// Now retrieve the task back again so we can sync it up with TW.
	return GetOneTask(ot.Data.Id)
}

func diff(t1 []string, t2 []string) []string {
	m := make(map[string]bool)
	for _, s := range t2 {
		m[s] = true
	}

	var result []string
	for _, t := range t1 {
		if has := m[t]; !has {
			result = append(result, t)
		}
	}
	return result
}

func updateOneTag(tagid, taskid, instruction string, errc chan error) {
	v := url.Values{}
	v.Add("tag", tagid)
	suffix := fmt.Sprintf("tasks/%s/%s", taskid, instruction)
	_, err := runPost("POST", suffix, v)
	if err != nil {
		errc <- errors.Wrap(err, "updateTags")
		return
	}
	errc <- nil
}

func updateTags(tw x.WarriorTask, asana x.WarriorTask) error {
	taskid := strconv.FormatUint(tw.Xid, 10)
	add := diff(tw.Tags, asana.Tags)
	rem := diff(asana.Tags, tw.Tags)

	addids := toTagIds(add)
	remids := toTagIds(rem)
	sz := len(addids) + len(remids)

	errc := make(chan error, sz)
	for _, id := range addids {
		go updateOneTag(id, taskid, "addTag", errc)
	}
	for _, id := range remids {
		go updateOneTag(id, taskid, "removeTag", errc)
	}

	var rerr error
	for i := 0; i < sz; i++ {
		if err := <-errc; err != nil {
			rerr = err
		}
	}

	return rerr
}

func UpdateTask(tw x.WarriorTask, asana x.WarriorTask) error {
	v := url.Values{}
	if tw.Name != asana.Name {
		v.Add("name", tw.Name)
	}
	if tw.Assignee != asana.Assignee {
		a := cache.UserId(tw.Assignee)
		if a > 0 {
			v.Add("assignee", strconv.FormatUint(a, 10))
		}
	}
	if !tw.Completed.IsZero() && asana.Completed.IsZero() {
		v.Add("completed", "true")
	}

	if len(v) > 0 {
		resp, err := runPost("PUT", "tasks/"+strconv.FormatUint(tw.Xid, 10), v)
		if err != nil {
			return errors.Wrap(err, "UpdateAsanaTask")
		}
		fmt.Println(string(resp))
	}

	if err := updateTags(tw, asana); err != nil {
		return errors.Wrap(err, "asana.UpdateTask updateTags")
	}

	// Update project or section if changed.
	pid := cache.ProjectId(tw.Project)
	if pid > 0 && (tw.Project != asana.Project || tw.Section != asana.Section) {
		fmt.Printf("Updating project and section: %v %v\n", tw.Project, tw.Section)
		if err := updateSection(tw.Xid, pid, tw.Section); err != nil {
			return errors.Wrap(err, "asana.UpdateTask updateSection")
		}
		if tw.Project == asana.Project {
			return nil
		}
		// Project was changed. So, remove the last one.
		fmt.Printf("Removing from project: %v\n", asana.Project)
		if previd := cache.ProjectId(asana.Project); previd > 0 {
			if err := removeProject(tw.Xid, previd); err != nil {
				return err
			}
		}
	}
	return nil
}

func GetOneTask(taskid uint64) (x.WarriorTask, error) {
	e := x.WarriorTask{}
	var ot oneTask
	if err := runGetter(&ot, "tasks/"+strconv.FormatUint(taskid, 10)); err != nil {
		return e, errors.Wrap(err, "AddNew runGetter")
	}

	if len(ot.Data.Memberships) == 0 {
		return e, fmt.Errorf("Member of no project")
	}
	member := ot.Data.Memberships[0]

	sname := cache.SectionName(member.Project.Id, member.Section.Id)
	return convert(ot.Data, member.Project.Name, sname)
}

func Delete(taskid uint64) error {
	url := fmt.Sprintf("%s/tasks/%d", prefix, taskid)
	_, err := runRequest("DELETE", url)
	return err
}
<commit_msg>Fix a bug which caused asana to crash on error<commit_after>package asana

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/manishrjain/asanawarrior/x"
	"github.com/pkg/errors"
)

var token = flag.String("token", "", "Token provided by Asana.")
var domain = flag.String("domain", "", "Workspace name, generally your domain name in Asana.")
var cache *acache = new(acache)

const (
	prefix = "https://app.asana.com/api/1.0"
	stamp  = "2006-01-02T15:04:05.999Z"
)

func runRequest(method, url string) ([]byte, error) {
RUNLOOP:
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Add("Authorization", "Bearer "+*token)
	client := &http.Client{
		Timeout: 10 * time.Minute,
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Printf("runRequest method: [%v] url: [%v] err: [%v]", method, url, err)
		time.Sleep(5 * time.Second)
		goto RUNLOOP
	}
	code := resp.StatusCode
	if code != http.StatusOK {
		log.Printf("runRequest method: [%v] url: [%v] status: [%v]",
			method, url, http.StatusText(resp.StatusCode))
		time.Sleep(5 * time.Second)
		goto RUNLOOP
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

func runGetter(i interface{}, suffix string, fields ...string) error {
	url := fmt.Sprintf("%s/%s?opt_fields=%s", prefix, suffix, strings.Join(fields, ","))
	body, err := runRequest("GET", url)
	if err != nil {
		return errors.Wrapf(err, "runGetter: %q", body)
	}
	if err := json.Unmarshal(body, i); err != nil {
		return errors.Wrapf(err, "Unmarshal: %q", body)
	}
	return nil
}

type Basic struct {
	Id    uint64 `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}
type BasicData struct {
	Data []Basic `json:"data"`
}
type BasicDataOne struct {
	Data Basic `json:"data"`
}

func getVarious(suffix string, opts ...string) ([]Basic, error) {
	var bd BasicData
	if err := runGetter(&bd, suffix, opts...); err != nil {
		return nil, err
	}
	return bd.Data, nil
}

type psec struct {
	Project Basic `json:"project"`
	Section Basic `json:"section"`
}

type task struct {
	Basic
	Assignee    Basic   `json:"assignee"`
	Tags        []Basic `json:"tags"`
	CompletedAt string  `json:"completed_at"`
	ModifiedAt  string  `json:"modified_at"`
	CreatedAt   string  `json:"created_at"`
	Memberships []psec  `json:"memberships"`
}

type tasks struct {
	Data []task `json:"data"`
}

type oneTask struct {
	Data task `json:"data"`
}

func convert(tsk task, proj, section string) (x.WarriorTask, error) {
	e := x.WarriorTask{}

	mts, err := time.Parse(stamp, tsk.ModifiedAt)
	if err != nil {
		return e, errors.Wrap(err, "asana modified at")
	}
	cts, err := time.Parse(stamp, tsk.CreatedAt)
	if err != nil {
		return e, errors.Wrap(err, "asana created at")
	}
	var dts time.Time
	if len(tsk.CompletedAt) > 0 {
		dts, err = time.Parse(stamp, tsk.CompletedAt)
		if err != nil {
			return e, errors.Wrap(err, "asana completed at")
		}
	}

	wt := x.WarriorTask{
		Name:      tsk.Name,
		Project:   proj,
		Xid:       tsk.Id,
		Assignee:  cache.User(tsk.Assignee.Id),
		Modified:  mts,
		Created:   cts,
		Completed: dts,
		Section:   section,
	}
	for _, tag := range tsk.Tags {
		wt.Tags = append(wt.Tags, cache.Tag(tag.Id))
	}
	return wt, nil
}

func getTasks(proj Basic, out chan x.WarriorTask, errc chan error) {
	var sectionName string
	var t tasks
	if err := runGetter(&t, fmt.Sprintf("projects/%d/tasks", proj.Id),
		"assignee,name,tags,completed_at,modified_at,created_at"); err != nil {
		errc <- errors.Wrapf(err, "getTasks for project: %v", proj.Name)
		return
	}

	for _, tsk := range t.Data {
		if len(tsk.Name) == 0 {
			// Don't sync such tasks.
			continue
		}
		if strings.HasSuffix(tsk.Name, ":") {
			sec := Basic{
				Id:   tsk.Id,
				Name: tsk.Name,
			}
			sectionName = cache.AddSection(proj.Id, sec)
			continue
		}

		wt, err := convert(tsk, proj.Name, sectionName)
		if err != nil {
			errc <- errors.Wrapf(err, "convert: getTasks for project: %v", proj.Name)
			return
		}
		out <- wt
	}
	errc <- nil
}

func GetTasks() ([]x.WarriorTask, error) {
	if err := cache.update(); err != nil {
		return nil, errors.Wrap(err, "cache.update")
	}

	out := make(chan x.WarriorTask, 100)
	projects := cache.Projects()
	errc := make(chan error, len(projects))
	for _, proj := range projects {
		go getTasks(proj, out, errc)
	}

	// Asana can send back the same task multiple times, if it's part of multiple projects.
	// So, let's dedup them.
	seen := make(map[uint64]bool)
	wtasks := make([]x.WarriorTask, 0, 100)
	done := make(chan struct{})
	go func() {
		for wt := range out {
			if _, has := seen[wt.Xid]; has {
				// ignore
				continue
			}
			wtasks = append(wtasks, wt)
			seen[wt.Xid] = true
		}
		done <- struct{}{}
	}()

	var rerr error
	for _ = range projects {
		if err := <-errc; err != nil {
			rerr = err
		}
	}
	close(out)
	<-done // Wait for all tasks to be picked up by goroutine.
	return wtasks, rerr
}

// runPost would run a PUT or POST to Asana. No locks should be acquired.
func runPost(method, suffix string, values url.Values) ([]byte, error) {
POSTLOOP:
	url := fmt.Sprintf("%s/%s", prefix, suffix)
	fmt.Println(url, values.Encode())
	req, err := http.NewRequest(method, url, bytes.NewBufferString(values.Encode()))
	if err != nil {
		log.Fatal(errors.Wrap(err, "runPost http.NewRequest"))
	}

	req.Header.Add("Authorization", "Bearer "+*token)
	req.Header.Add("content-type", "application/x-www-form-urlencoded")
	client := &http.Client{
		Timeout: 10 * time.Minute,
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("runPost url: [%v] err: [%v]", url, err)
		time.Sleep(5 * time.Second)
		goto POSTLOOP
	}
	defer resp.Body.Close()

	return ioutil.ReadAll(resp.Body)
}

func toTagIds(tnames []string) []string {
	var tags []string
	for _, t := range tnames {
		tid := cache.TagId(t)
		if tid == 0 {
			tid = cache.CreateTag(t)
			fmt.Printf("New Tag created. ID: %d", tid)
		}
		if tid > 0 {
			tags = append(tags, strconv.FormatUint(tid, 10))
		}
	}
	return tags
}

func removeProject(tid, pid uint64) error {
	v := url.Values{}
	v.Add("project", strconv.FormatUint(pid, 10))
	_, err := runPost("POST", fmt.Sprintf("tasks/%d/removeProject", tid), v)
	return err
}

func updateSection(tid, pid uint64, section string) error {
	v := url.Values{}
	v.Add("project", strconv.FormatUint(pid, 10))

	sid := cache.SectionId(pid, section)
	if sid > 0 {
		v.Add("section", strconv.FormatUint(sid, 10))
	}

	_, err := runPost("POST", fmt.Sprintf("tasks/%d/addProject", tid), v)
	return err
}

func AddNew(wt x.WarriorTask) (x.WarriorTask, error) {
	e := x.WarriorTask{}

	// Ensure that project actually exists before proceeding.
	pid := cache.ProjectId(wt.Project)
	if pid == 0 {
		return e, fmt.Errorf("Project not found: %v", wt.Project)
	}

	v := url.Values{}
	v.Add("workspace", strconv.FormatUint(cache.Workspace(), 10))
	v.Add("name", wt.Name)
	aid := cache.UserId(wt.Assignee)
	if aid > 0 {
		v.Add("assignee", strconv.FormatUint(aid, 10))
	}
	if !wt.Completed.IsZero() {
		v.Add("completed", "true")
	}

	tags := toTagIds(wt.Tags)
	v.Add("tags", strings.Join(tags, ","))
	resp, err := runPost("POST", "tasks", v)
	if err != nil {
		return e, errors.Wrap(err, "AddNew runPost")
	}
	fmt.Println(string(resp))

	var ot oneTask
	if err := json.Unmarshal(resp, &ot); err != nil {
		return e, errors.Wrap(err, "AddNew unmarshal")
	}
	if ot.Data.Id == 0 {
		return e, fmt.Errorf("Unable to find ID assigned by Asana: %+v", ot.Data)
	}

	// Now set the project and section.
	if err := updateSection(ot.Data.Id, pid, wt.Section); err != nil {
		return e, errors.Wrap(err, "AddNew updateSection")
	}

	// Now retrieve the task back again so we can sync it up with TW.
	return GetOneTask(ot.Data.Id)
}

func diff(t1 []string, t2 []string) []string {
	m := make(map[string]bool)
	for _, s := range t2 {
		m[s] = true
	}

	var result []string
	for _, t := range t1 {
		if has := m[t]; !has {
			result = append(result, t)
		}
	}
	return result
}

func updateOneTag(tagid, taskid, instruction string, errc chan error) {
	v := url.Values{}
	v.Add("tag", tagid)
	suffix := fmt.Sprintf("tasks/%s/%s", taskid, instruction)
	_, err := runPost("POST", suffix, v)
	if err != nil {
		errc <- errors.Wrap(err, "updateTags")
		return
	}
	errc <- nil
}

func updateTags(tw x.WarriorTask, asana x.WarriorTask) error {
	taskid := strconv.FormatUint(tw.Xid, 10)
	add := diff(tw.Tags, asana.Tags)
	rem := diff(asana.Tags, tw.Tags)

	addids := toTagIds(add)
	remids := toTagIds(rem)
	sz := len(addids) + len(remids)

	errc := make(chan error, sz)
	for _, id := range addids {
		go updateOneTag(id, taskid, "addTag", errc)
	}
	for _, id := range remids {
		go updateOneTag(id, taskid, "removeTag", errc)
	}

	var rerr error
	for i := 0; i < sz; i++ {
		if err := <-errc; err != nil {
			rerr = err
		}
	}

	return rerr
}

func UpdateTask(tw x.WarriorTask, asana x.WarriorTask) error {
	v := url.Values{}
	if tw.Name != asana.Name {
		v.Add("name", tw.Name)
	}
	if tw.Assignee != asana.Assignee {
		a := cache.UserId(tw.Assignee)
		if a > 0 {
			v.Add("assignee", strconv.FormatUint(a, 10))
		}
	}
	if !tw.Completed.IsZero() && asana.Completed.IsZero() {
		v.Add("completed", "true")
	}

	if len(v) > 0 {
		resp, err := runPost("PUT", "tasks/"+strconv.FormatUint(tw.Xid, 10), v)
		if err != nil {
			return errors.Wrap(err, "UpdateAsanaTask")
		}
		fmt.Println(string(resp))
	}

	if err := updateTags(tw, asana); err != nil {
		return errors.Wrap(err, "asana.UpdateTask updateTags")
	}

	// Update project or section if changed.
	pid := cache.ProjectId(tw.Project)
	if pid > 0 && (tw.Project != asana.Project || tw.Section != asana.Section) {
		fmt.Printf("Updating project and section: %v %v\n", tw.Project, tw.Section)
		if err := updateSection(tw.Xid, pid, tw.Section); err != nil {
			return errors.Wrap(err, "asana.UpdateTask updateSection")
		}
		if tw.Project == asana.Project {
			return nil
		}
		// Project was changed. So, remove the last one.
		fmt.Printf("Removing from project: %v\n", asana.Project)
		if previd := cache.ProjectId(asana.Project); previd > 0 {
			if err := removeProject(tw.Xid, previd); err != nil {
				return err
			}
		}
	}
	return nil
}

func GetOneTask(taskid uint64) (x.WarriorTask, error) {
	e := x.WarriorTask{}
	var ot oneTask
	if err := runGetter(&ot, "tasks/"+strconv.FormatUint(taskid, 10)); err != nil {
		return e, errors.Wrap(err, "AddNew runGetter")
	}

	if len(ot.Data.Memberships) == 0 {
		return e, fmt.Errorf("Member of no project")
	}
	member := ot.Data.Memberships[0]

	sname := cache.SectionName(member.Project.Id, member.Section.Id)
	return convert(ot.Data, member.Project.Name, sname)
}

func Delete(taskid uint64) error {
	url := fmt.Sprintf("%s/tasks/%d", prefix, taskid)
	_, err := runRequest("DELETE", url)
	return err
}
<|endoftext|>


<commit_before>// This file is for statements by syntax form, such as set!

package scheme

import (
	"fmt"
)

var (
	builtinSyntaxes = Binding{
		"and":    NewSyntax(andSyntax),
		"begin":  NewSyntax(beginSyntax),
		"cond":   NewSyntax(condSyntax),
		"define": NewSyntax(defineSyntax),
		"do":     NewSyntax(doSyntax),
		"if":     NewSyntax(ifSyntax),
		"lambda": NewSyntax(lambdaSyntax),
		"let":    NewSyntax(letSyntax),
		"let*":   NewSyntax(letSyntax),
		"letrec": NewSyntax(letSyntax),
		"or":     NewSyntax(orSyntax),
		"quote":  NewSyntax(quoteSyntax),
		"set!":   NewSyntax(setSyntax),
	}
)

type Syntax struct {
	ObjectBase
	function func(*Syntax, Object) Object
}

func NewSyntax(function func(*Syntax, Object) Object) *Syntax {
	return &Syntax{ObjectBase: ObjectBase{parent: nil}, function: function}
}

func (s *Syntax) Invoke(arguments Object) Object {
	return s.function(s, arguments)
}

func (s *Syntax) String() string {
	return fmt.Sprintf("#<syntax %s>", s.Bounder())
}

func (s *Syntax) isSyntax() bool {
	return true
}

func (s *Syntax) malformedError() {
	syntaxError("malformed %s: %s", s.Bounder(), s.Bounder().Parent())
}

func (s *Syntax) assertListEqual(arguments Object, length int) {
	if !arguments.isList() || arguments.(*Pair).ListLength() != length {
		s.malformedError()
	}
}

func (s *Syntax) assertListMinimum(arguments Object, minimum int) {
	if !arguments.isList() || arguments.(*Pair).ListLength() < minimum {
		s.malformedError()
	}
}

func (s *Syntax) assertListRange(arguments Object, lengthRange []int) {
	if !arguments.isList() {
		s.malformedError()
	}

	for _, length := range lengthRange {
		if length == arguments.(*Pair).ListLength() {
			return
		}
	}
	s.malformedError()
}

// Returns elements in list object with type assertion (syntax form specific error message)
// Assertion is minimum
func (s *Syntax) elementsMinimum(list Object, minimum int) []Object {
	if list.isApplication() {
		list = list.(*Application).toList()
	}
	s.assertListMinimum(list, minimum)
	return list.(*Pair).Elements()
}

// Returns elements in list object with type assertion (syntax form specific error message)
// Assertion is equal
func (s *Syntax) elementsExact(list Object, value int) []Object {
	if list.isApplication() {
		list = list.(*Application).toList()
	}
	s.assertListEqual(list, value)
	return list.(*Pair).Elements()
}

func andSyntax(s *Syntax, arguments Object) Object {
	s.assertListMinimum(arguments, 0)

	lastResult := Object(NewBoolean(true))
	for _, object := range arguments.(*Pair).Elements() {
		lastResult = object.Eval()
		if lastResult.isBoolean() && lastResult.(*Boolean).value == false {
			return NewBoolean(false)
		}
	}
	return lastResult
}

func beginSyntax(s *Syntax, arguments Object) Object {
	s.assertListMinimum(arguments, 0)

	lastResult := undef
	for _, object := range arguments.(*Pair).Elements() {
		lastResult = object.Eval()
	}
	return lastResult
}

func condSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsMinimum(arguments, 0)
	if len(elements) == 0 {
		syntaxError("at least one clause is required for cond")
	}

	// First: syntax check
	elseExists := false
	for _, element := range elements {
		if elseExists {
			syntaxError("'else' clause followed by more clauses")
		} else if element.isApplication() && element.(*Application).procedure.isVariable() &&
			element.(*Application).procedure.(*Variable).identifier == "else" {
			elseExists = true
		}

		if element.isNull() || !element.isApplication() {
			syntaxError("bad clause in cond")
		}
	}

	// Second: eval cases
	for _, element := range elements {
		lastResult := undef
		application := element.(*Application)

		isElse := application.procedure.isVariable() && application.procedure.(*Variable).identifier == "else"
		if !isElse {
			lastResult = application.procedure.Eval()
		}

		// first element is 'else' or not '#f'
		if isElse || !lastResult.isBoolean() || lastResult.(*Boolean).value == true {
			for _, object := range application.arguments.(*Pair).Elements() {
				lastResult = object.Eval()
			}
			return lastResult
		}
	}
	return undef
}

func defineSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsExact(arguments, 2)

	if !elements[0].isVariable() {
		syntaxError("%s", s.Bounder().Parent())
	}
	variable := elements[0].(*Variable)
	s.Bounder().define(variable.identifier, elements[1].Eval())

	return NewSymbol(variable.identifier)
}

func doSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())

	// Parse iterator list and define first variable
	elements := s.elementsMinimum(arguments, 2)
	iteratorBodies := s.elementsMinimum(elements[0], 0)
	for _, iteratorBody := range iteratorBodies {
		iteratorElements := s.elementsMinimum(iteratorBody, 2)
		if len(iteratorElements) > 3 {
			compileError("bad update expr in %s: %s", s.Bounder(), s.Bounder().Parent())
		}
		closure.tryDefine(iteratorElements[0], iteratorElements[1].Eval())
	}

	// eval test ->
	//   true: eval testBody and returns its result
	//  false: eval continueBody, eval iterator's update
	testElements := s.elementsMinimum(elements[1], 1)
	continueElements := elements[2:]

	for {
		testResult := testElements[0].Eval()
		if !testResult.isBoolean() || testResult.(*Boolean).value == true {
			for _, element := range testElements[1:] {
				testResult = element.Eval()
			}
			return testResult
		} else {
			// eval continueBody
			for _, element := range continueElements {
				element.Eval()
			}

			// update iterators
			for _, iteratorBody := range iteratorBodies {
				iteratorElements := s.elementsMinimum(iteratorBody, 2)
				if len(iteratorElements) == 3 {
					closure.tryDefine(iteratorElements[0], iteratorElements[2].Eval())
				}
			}
		}
	}
	return undef
}

func ifSyntax(s *Syntax, arguments Object) Object {
	s.assertListRange(arguments, []int{2, 3})
	elements := arguments.(*Pair).Elements()

	result := elements[0].Eval()
	if result.isBoolean() && !result.(*Boolean).value {
		if len(elements) == 3 {
			return elements[2].Eval()
		} else {
			return undef
		}
	} else {
		return elements[1].Eval()
	}
}

func lambdaSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())

	elements := s.elementsMinimum(arguments, 1)
	variables := s.elementsMinimum(elements[0], 0)

	// generate function
	closure.function = func(givenArguments Object) Object {
		// assert given arguments
		givenElements := s.elementsMinimum(givenArguments, 0)
		if len(variables) != len(givenElements) {
			compileError("wrong number of arguments: requires %d, but got %d", len(variables), len(givenElements))
		}

		// define arguments to local scope
		for index, variable := range variables {
			closure.tryDefine(variable, givenElements[index].Eval())
		}

		// returns last eval result
		lastResult := undef
		for _, element := range elements[1:] {
			lastResult = element.Eval()
		}
		return lastResult
	}
	return closure
}

func letSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())
	elements := s.elementsMinimum(arguments, 1)

	// define arguments to local scope
	for _, argumentElement := range s.elementsMinimum(elements[0], 0) {
		variableElements := s.elementsExact(argumentElement, 2)
		closure.tryDefine(variableElements[0], variableElements[1])
	}

	// eval body
	lastResult := undef
	for _, element := range elements[1:] {
		lastResult = element.Eval()
	}
	return lastResult
}

func orSyntax(s *Syntax, arguments Object) Object {
	s.assertListMinimum(arguments, 0)

	lastResult := Object(NewBoolean(false))
	for _, object := range arguments.(*Pair).Elements() {
		lastResult = object.Eval()
		if !lastResult.isBoolean() || lastResult.(*Boolean).value != false {
			return lastResult
		}
	}
	return lastResult
}

func quoteSyntax(s *Syntax, arguments Object) Object {
	s.assertListEqual(arguments, 1)
	object := arguments.(*Pair).ElementAt(0)

	p := NewParser(object.String())
	p.Peek()
	return p.parseQuotedObject(s.Bounder())
}

func setSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsExact(arguments, 2)

	variable := elements[0]
	if !variable.isVariable() {
		s.malformedError()
	}
	value := elements[1].Eval()
	s.Bounder().set(variable.(*Variable).identifier, value)
	return value
}
<commit_msg>Refactor about evaluating all objects<commit_after>// This file is for statements by syntax form, such as set!

package scheme

import (
	"fmt"
)

var (
	builtinSyntaxes = Binding{
		"and":    NewSyntax(andSyntax),
		"begin":  NewSyntax(beginSyntax),
		"cond":   NewSyntax(condSyntax),
		"define": NewSyntax(defineSyntax),
		"do":     NewSyntax(doSyntax),
		"if":     NewSyntax(ifSyntax),
		"lambda": NewSyntax(lambdaSyntax),
		"let":    NewSyntax(letSyntax),
		"let*":   NewSyntax(letSyntax),
		"letrec": NewSyntax(letSyntax),
		"or":     NewSyntax(orSyntax),
		"quote":  NewSyntax(quoteSyntax),
		"set!":   NewSyntax(setSyntax),
	}
)

type Syntax struct {
	ObjectBase
	function func(*Syntax, Object) Object
}

func NewSyntax(function func(*Syntax, Object) Object) *Syntax {
	return &Syntax{ObjectBase: ObjectBase{parent: nil}, function: function}
}

func (s *Syntax) Invoke(arguments Object) Object {
	return s.function(s, arguments)
}

func (s *Syntax) String() string {
	return fmt.Sprintf("#<syntax %s>", s.Bounder())
}

func (s *Syntax) isSyntax() bool {
	return true
}

func (s *Syntax) malformedError() {
	syntaxError("malformed %s: %s", s.Bounder(), s.Bounder().Parent())
}

func (s *Syntax) assertListEqual(arguments Object, length int) {
	if !arguments.isList() || arguments.(*Pair).ListLength() != length {
		s.malformedError()
	}
}

func (s *Syntax) assertListMinimum(arguments Object, minimum int) {
	if !arguments.isList() || arguments.(*Pair).ListLength() < minimum {
		s.malformedError()
	}
}

func (s *Syntax) assertListRange(arguments Object, lengthRange []int) {
	if !arguments.isList() {
		s.malformedError()
	}

	for _, length := range lengthRange {
		if length == arguments.(*Pair).ListLength() {
			return
		}
	}
	s.malformedError()
}

// Returns elements in list object with type assertion (syntax form specific error message)
// Assertion is minimum
func (s *Syntax) elementsMinimum(list Object, minimum int) []Object {
	if list.isApplication() {
		list = list.(*Application).toList()
	}
	s.assertListMinimum(list, minimum)
	return list.(*Pair).Elements()
}

// Returns elements in list object with type assertion (syntax form specific error message)
// Assertion is equal
func (s *Syntax) elementsExact(list Object, value int) []Object {
	if list.isApplication() {
		list = list.(*Application).toList()
	}
	s.assertListEqual(list, value)
	return list.(*Pair).Elements()
}

// Eval all given objects and returns last object's eval result.
// When 'objects' is empty, returns #<undef>.
func evalAll(objects []Object) Object {
	lastResult := undef
	for _, object := range objects {
		lastResult = object.Eval()
	}
	return lastResult
}

func andSyntax(s *Syntax, arguments Object) Object {
	s.assertListMinimum(arguments, 0)

	lastResult := Object(NewBoolean(true))
	for _, object := range arguments.(*Pair).Elements() {
		lastResult = object.Eval()
		if lastResult.isBoolean() && lastResult.(*Boolean).value == false {
			return NewBoolean(false)
		}
	}
	return lastResult
}

func beginSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsMinimum(arguments, 0)
	return evalAll(elements)
}

func condSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsMinimum(arguments, 0)
	if len(elements) == 0 {
		syntaxError("at least one clause is required for cond")
	}

	// First: syntax check
	elseExists := false
	for _, element := range elements {
		if elseExists {
			syntaxError("'else' clause followed by more clauses")
		} else if element.isApplication() && element.(*Application).procedure.isVariable() &&
			element.(*Application).procedure.(*Variable).identifier == "else" {
			elseExists = true
		}

		if element.isNull() || !element.isApplication() {
			syntaxError("bad clause in cond")
		}
	}

	// Second: eval cases
	for _, element := range elements {
		lastResult := undef
		application := element.(*Application)

		isElse := application.procedure.isVariable() && application.procedure.(*Variable).identifier == "else"
		if !isElse {
			lastResult = application.procedure.Eval()
		}

		// first element is 'else' or not '#f'
		if isElse || !lastResult.isBoolean() || lastResult.(*Boolean).value == true {
			for _, object := range application.arguments.(*Pair).Elements() {
				lastResult = object.Eval()
			}
			return lastResult
		}
	}
	return undef
}

func defineSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsExact(arguments, 2)

	if !elements[0].isVariable() {
		syntaxError("%s", s.Bounder().Parent())
	}
	variable := elements[0].(*Variable)
	s.Bounder().define(variable.identifier, elements[1].Eval())

	return NewSymbol(variable.identifier)
}

func doSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())

	// Parse iterator list and define first variable
	elements := s.elementsMinimum(arguments, 2)
	iteratorBodies := s.elementsMinimum(elements[0], 0)
	for _, iteratorBody := range iteratorBodies {
		iteratorElements := s.elementsMinimum(iteratorBody, 2)
		if len(iteratorElements) > 3 {
			compileError("bad update expr in %s: %s", s.Bounder(), s.Bounder().Parent())
		}
		closure.tryDefine(iteratorElements[0], iteratorElements[1].Eval())
	}

	// eval test ->
	//   true: eval testBody and returns its result
	//  false: eval continueBody, eval iterator's update
	testElements := s.elementsMinimum(elements[1], 1)
	for {
		testResult := testElements[0].Eval()
		if !testResult.isBoolean() || testResult.(*Boolean).value == true {
			for _, element := range testElements[1:] {
				testResult = element.Eval()
			}
			return testResult
		} else {
			// eval continueBody
			evalAll(elements[2:])

			// update iterators
			for _, iteratorBody := range iteratorBodies {
				iteratorElements := s.elementsMinimum(iteratorBody, 2)
				if len(iteratorElements) == 3 {
					closure.tryDefine(iteratorElements[0], iteratorElements[2].Eval())
				}
			}
		}
	}
	return undef
}

func ifSyntax(s *Syntax, arguments Object) Object {
	s.assertListRange(arguments, []int{2, 3})
	elements := arguments.(*Pair).Elements()

	result := elements[0].Eval()
	if result.isBoolean() && !result.(*Boolean).value {
		if len(elements) == 3 {
			return elements[2].Eval()
		} else {
			return undef
		}
	} else {
		return elements[1].Eval()
	}
}

func lambdaSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())

	elements := s.elementsMinimum(arguments, 1)
	variables := s.elementsMinimum(elements[0], 0)

	// generate function
	closure.function = func(givenArguments Object) Object {
		// assert given arguments
		givenElements := s.elementsMinimum(givenArguments, 0)
		if len(variables) != len(givenElements) {
			compileError("wrong number of arguments: requires %d, but got %d", len(variables), len(givenElements))
		}

		// define arguments to local scope
		for index, variable := range variables {
			closure.tryDefine(variable, givenElements[index].Eval())
		}

		// returns last eval result
		return evalAll(elements[1:])
	}
	return closure
}

func letSyntax(s *Syntax, arguments Object) Object {
	closure := WrapClosure(arguments.Parent())
	elements := s.elementsMinimum(arguments, 1)

	// define arguments to local scope
	for _, argumentElement := range s.elementsMinimum(elements[0], 0) {
		variableElements := s.elementsExact(argumentElement, 2)
		closure.tryDefine(variableElements[0], variableElements[1])
	}

	// eval body
	return evalAll(elements[1:])
}

func orSyntax(s *Syntax, arguments Object) Object {
	s.assertListMinimum(arguments, 0)

	lastResult := Object(NewBoolean(false))
	for _, object := range arguments.(*Pair).Elements() {
		lastResult = object.Eval()
		if !lastResult.isBoolean() || lastResult.(*Boolean).value != false {
			return lastResult
		}
	}
	return lastResult
}

func quoteSyntax(s *Syntax, arguments Object) Object {
	s.assertListEqual(arguments, 1)
	object := arguments.(*Pair).ElementAt(0)

	p := NewParser(object.String())
	p.Peek()
	return p.parseQuotedObject(s.Bounder())
}

func setSyntax(s *Syntax, arguments Object) Object {
	elements := s.elementsExact(arguments, 2)

	variable := elements[0]
	if !variable.isVariable() {
		s.malformedError()
	}
	value := elements[1].Eval()
	s.Bounder().set(variable.(*Variable).identifier, value)
	return value
}
<|endoftext|>


<commit_before>package rendering

// Should provide universal calls for all graphics systems we support
<commit_msg>More rendering placeholder stuff<commit_after>package rendering

import "github.com/go-gl/gl/v3.2-core/gl"

// Should provide universal calls for all graphics systems we support, like OGL, SDL, etc..
// Generally focusing on OGL is a good idea. Using stuff from https://github.com/go-gl is probably the best idea.

func Init() {
	if err := gl.Init(); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package termite

import (
	"bytes"
	"crypto/hmac"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"rand"
	"sync"
	"time"
)

const challengeLength = 20

func sign(conn net.Conn, challenge []byte, secret []byte, local bool) []byte {
	h := hmac.NewSHA1(secret)
	h.Write(challenge)
	l := conn.LocalAddr()
	r := conn.RemoteAddr()
	if local {
		h.Write([]byte(fmt.Sprintf("%v-%v", l, r)))
	} else {
		h.Write([]byte(fmt.Sprintf("%v-%v", r, l)))
	}
	return h.Sum()
}

// Symmetrical authentication using HMAC-SHA1.
//
// To authenticate, we do  the following:
//
// * Receive 20-byte random challenge
// * Using the secret, sign (challenge + remote address + local address)
// * Return the signature
//
// TODO - should probably use SSL/TLS? Figure out what is useful and
// necessary here.
func Authenticate(conn net.Conn, secret []byte) os.Error {
	challenge := RandomBytes(challengeLength)

	_, err := conn.Write(challenge)
	if err != nil {
		return err
	}
	expected := sign(conn, challenge, secret, true)

	remoteChallenge := make([]byte, challengeLength)
	n, err := conn.Read(remoteChallenge)
	if err != nil {
		return err
	}
	remoteChallenge = remoteChallenge[:n]
	_, err = conn.Write(sign(conn, remoteChallenge, secret, false))

	response := make([]byte, len(expected))
	n, err = conn.Read(response)
	if err != nil {
		return err
	}
	response = response[:n]

	if bytes.Compare(response, expected) != 0 {
		log.Println("Authentication failure from", conn.RemoteAddr())
		conn.Close()
		return os.NewError("Mismatch in response")
	}

	expectAck := []byte("OK")
	conn.Write(expectAck)

	ack := make([]byte, len(expectAck))
	n, err = conn.Read(ack)
	if err != nil {
		return err
	}

	ack = ack[:n]
	if bytes.Compare(expectAck, ack) != 0 {
		fmt.Println(expectAck, ack)
		return os.NewError("Missing ack reply")
	}

	return nil
}

func SetupServer(port int, secret []byte, output chan net.Conn) {
	host, _ := os.Hostname()
	addr := fmt.Sprintf("%s:%d", host, port)
	// TODO - also listen on localhost.
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal("net.Listen", err)
	}
	log.Println("Listening to", addr)

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}

		err = Authenticate(conn, secret)
		if err != nil {
			log.Println("Authentication error: ", err)
			conn.Close()
			continue
		}
		output <- conn
	}
}

// ids:
//
const (
	RPC_CHANNEL = "rpc....."
	_ID_FMT     = "id%06d"
	HEADER_LEN  = 8
)

func ConnectionId() string {
	id := rand.Intn(1e6)
	return fmt.Sprintf(_ID_FMT, id)
}

type PendingConnection struct {
	Id    string
	Ready sync.Cond
	Conn  net.Conn
}

// PendingConnections manages a list of connections, indexed by ID.
// The id is sent as the first 8 bytes, after the authentication.
type PendingConnections struct {
	connectionsMutex sync.Mutex
	connections      map[string]*PendingConnection
}

func NewPendingConnections() *PendingConnections {
	return &PendingConnections{
		connections: make(map[string]*PendingConnection),
	}
}

func (me *PendingConnections) newPendingConnection(id string) *PendingConnection {
	p := &PendingConnection{
		Id: id,
	}
	p.Ready.L = &me.connectionsMutex
	return p
}

func (me *PendingConnections) WaitConnection(id string) net.Conn {
	me.connectionsMutex.Lock()
	defer me.connectionsMutex.Unlock()
	p := me.connections[id]
	if p == nil {
		p = me.newPendingConnection(id)
		me.connections[id] = p
	}

	for p.Conn == nil {
		p.Ready.Wait()
	}

	me.connections[id] = nil
	return p.Conn
}

func (me *PendingConnections) Accept(conn net.Conn) bool {
	idBytes := make([]byte, HEADER_LEN)
	n, err := conn.Read(idBytes)
	if n != HEADER_LEN || err != nil {
		// TODO -an error?
		conn.Close()
		return true
	}
	id := string(idBytes)
	if id == RPC_CHANNEL {
		return false
	}

	me.connectionsMutex.Lock()
	defer me.connectionsMutex.Unlock()
	p := me.connections[id]
	if p == nil {
		p = me.newPendingConnection(id)
		me.connections[id] = p
	}
	if p.Conn != nil {
		panic(fmt.Sprintf("accepted the same connection id twice: %s", id))
	}
	p.Conn = conn
	p.Ready.Signal()
	return true
}

func DialTypedConnection(addr string, id string, secret []byte) (net.Conn, os.Error) {
	if len(id) != HEADER_LEN {
		log.Fatal("id != 8", id, len(id))
	}
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	err = Authenticate(conn, secret)
	if err != nil {
		return nil, err
	}
	_, err = io.WriteString(conn, id)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

const _MAXTRY = 3

func OpenSocketConnection(socket string, channel string) net.Conn {
	delay := int64(0)
	conn, err := net.Dial("unix", socket)
	for try := 0; err != nil && try < _MAXTRY; try++ {
		if err == os.EAGAIN {
			delay = int64(1.0 + rand.Float64()) * delay + 0.01e9
			time.Sleep(int64(delay))
			conn, err = net.Dial("unix", socket)
			continue
		}
		if err != nil {
			log.Fatal("Dial:", err)
		}
	}
	if len(channel) != HEADER_LEN {
		panic(channel)
	}
	_, err = io.WriteString(conn, channel)
	if err != nil {
		log.Fatal("WriteString", err)
	}
	return conn
}
<commit_msg>Always do retry; too much hassle to deconstruct error messages.<commit_after>package termite

import (
	"bytes"
	"crypto/hmac"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"rand"
	"sync"
	"time"
)

const challengeLength = 20

func sign(conn net.Conn, challenge []byte, secret []byte, local bool) []byte {
	h := hmac.NewSHA1(secret)
	h.Write(challenge)
	l := conn.LocalAddr()
	r := conn.RemoteAddr()
	if local {
		h.Write([]byte(fmt.Sprintf("%v-%v", l, r)))
	} else {
		h.Write([]byte(fmt.Sprintf("%v-%v", r, l)))
	}
	return h.Sum()
}

// Symmetrical authentication using HMAC-SHA1.
//
// To authenticate, we do  the following:
//
// * Receive 20-byte random challenge
// * Using the secret, sign (challenge + remote address + local address)
// * Return the signature
//
// TODO - should probably use SSL/TLS? Figure out what is useful and
// necessary here.
func Authenticate(conn net.Conn, secret []byte) os.Error {
	challenge := RandomBytes(challengeLength)

	_, err := conn.Write(challenge)
	if err != nil {
		return err
	}
	expected := sign(conn, challenge, secret, true)

	remoteChallenge := make([]byte, challengeLength)
	n, err := conn.Read(remoteChallenge)
	if err != nil {
		return err
	}
	remoteChallenge = remoteChallenge[:n]
	_, err = conn.Write(sign(conn, remoteChallenge, secret, false))

	response := make([]byte, len(expected))
	n, err = conn.Read(response)
	if err != nil {
		return err
	}
	response = response[:n]

	if bytes.Compare(response, expected) != 0 {
		log.Println("Authentication failure from", conn.RemoteAddr())
		conn.Close()
		return os.NewError("Mismatch in response")
	}

	expectAck := []byte("OK")
	conn.Write(expectAck)

	ack := make([]byte, len(expectAck))
	n, err = conn.Read(ack)
	if err != nil {
		return err
	}

	ack = ack[:n]
	if bytes.Compare(expectAck, ack) != 0 {
		fmt.Println(expectAck, ack)
		return os.NewError("Missing ack reply")
	}

	return nil
}

func SetupServer(port int, secret []byte, output chan net.Conn) {
	host, _ := os.Hostname()
	addr := fmt.Sprintf("%s:%d", host, port)
	// TODO - also listen on localhost.
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal("net.Listen", err)
	}
	log.Println("Listening to", addr)

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}

		err = Authenticate(conn, secret)
		if err != nil {
			log.Println("Authentication error: ", err)
			conn.Close()
			continue
		}
		output <- conn
	}
}

// ids:
//
const (
	RPC_CHANNEL = "rpc....."
	_ID_FMT     = "id%06d"
	HEADER_LEN  = 8
)

func ConnectionId() string {
	id := rand.Intn(1e6)
	return fmt.Sprintf(_ID_FMT, id)
}

type PendingConnection struct {
	Id    string
	Ready sync.Cond
	Conn  net.Conn
}

// PendingConnections manages a list of connections, indexed by ID.
// The id is sent as the first 8 bytes, after the authentication.
type PendingConnections struct {
	connectionsMutex sync.Mutex
	connections      map[string]*PendingConnection
}

func NewPendingConnections() *PendingConnections {
	return &PendingConnections{
		connections: make(map[string]*PendingConnection),
	}
}

func (me *PendingConnections) newPendingConnection(id string) *PendingConnection {
	p := &PendingConnection{
		Id: id,
	}
	p.Ready.L = &me.connectionsMutex
	return p
}

func (me *PendingConnections) WaitConnection(id string) net.Conn {
	me.connectionsMutex.Lock()
	defer me.connectionsMutex.Unlock()
	p := me.connections[id]
	if p == nil {
		p = me.newPendingConnection(id)
		me.connections[id] = p
	}

	for p.Conn == nil {
		p.Ready.Wait()
	}

	me.connections[id] = nil
	return p.Conn
}

func (me *PendingConnections) Accept(conn net.Conn) bool {
	idBytes := make([]byte, HEADER_LEN)
	n, err := conn.Read(idBytes)
	if n != HEADER_LEN || err != nil {
		// TODO -an error?
		conn.Close()
		return true
	}
	id := string(idBytes)
	if id == RPC_CHANNEL {
		return false
	}

	me.connectionsMutex.Lock()
	defer me.connectionsMutex.Unlock()
	p := me.connections[id]
	if p == nil {
		p = me.newPendingConnection(id)
		me.connections[id] = p
	}
	if p.Conn != nil {
		panic(fmt.Sprintf("accepted the same connection id twice: %s", id))
	}
	p.Conn = conn
	p.Ready.Signal()
	return true
}

func DialTypedConnection(addr string, id string, secret []byte) (net.Conn, os.Error) {
	if len(id) != HEADER_LEN {
		log.Fatal("id != 8", id, len(id))
	}
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	err = Authenticate(conn, secret)
	if err != nil {
		return nil, err
	}
	_, err = io.WriteString(conn, id)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

const _MAXTRY = 5

func OpenSocketConnection(socket string, channel string) net.Conn {
	delay := int64(0)
	conn, err := net.Dial("unix", socket)
	for try := 0; err != nil && try < _MAXTRY; try++ {
		log.Println("Retrying dial:", err)
		delay = int64(1.5 + 0.5 * rand.Float64() * float64(delay)) + 0.02e9
		time.Sleep(int64(delay))
		conn, err = net.Dial("unix", socket)
		continue
	}
	if err != nil {
		log.Fatal("OpenSocketConnection: ", err)
	}

	if len(channel) != HEADER_LEN {
		panic(channel)
	}
	_, err = io.WriteString(conn, channel)
	if err != nil {
		log.Fatal("WriteString", err)
	}
	return conn
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"github.com/hashicorp/terraform/config"
)

// Resource encapsulates a resource, its configuration, its provider,
// its current state, and potentially a desired diff from the state it
// wants to reach.
type Resource struct {
	Id           string
	Config       *ResourceConfig
	Diff         *ResourceDiff
	Provider     ResourceProvider
	State        *ResourceState
	Provisioners []ResourceProvisioner
}

// Vars returns the mapping of variables that should be replaced in
// configuration based on the attributes of this resource.
func (r *Resource) Vars() map[string]string {
	if r.State == nil {
		return nil
	}

	vars := make(map[string]string)
	for ak, av := range r.State.Attributes {
		vars[fmt.Sprintf("%s.%s", r.Id, ak)] = av
	}

	return vars
}

// ResourceConfig holds the configuration given for a resource. This is
// done instead of a raw `map[string]interface{}` type so that rich
// methods can be added to it to make dealing with it easier.
type ResourceConfig struct {
	ComputedKeys []string
	Raw          map[string]interface{}
	Config       map[string]interface{}

	raw *config.RawConfig
}

// NewResourceConfig creates a new ResourceConfig from a config.RawConfig.
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
	result := &ResourceConfig{raw: c}
	result.interpolate(nil)
	return result
}

// CheckSet checks that the given list of configuration keys is
// properly set. If not, errors are returned for each unset key.
//
// This is useful to be called in the Validate method of a ResourceProvider.
func (c *ResourceConfig) CheckSet(keys []string) []error {
	var errs []error

	for _, k := range keys {
		if !c.IsSet(k) {
			errs = append(errs, fmt.Errorf("%s must be set", k))
		}
	}

	return errs
}

// Get looks up a configuration value by key and returns the value.
//
// The second return value is true if the get was successful. Get will
// not succeed if the value is being computed.
func (c *ResourceConfig) Get(k string) (interface{}, bool) {
	parts := strings.Split(k, ".")

	var current interface{} = c.Raw
	for _, part := range parts {
		if current == nil {
			return nil, false
		}

		cv := reflect.ValueOf(current)
		switch cv.Kind() {
		case reflect.Map:
			v := cv.MapIndex(reflect.ValueOf(part))
			if !v.IsValid() {
				return nil, false
			}
			current = v.Interface()
		case reflect.Slice:
			i, err := strconv.ParseInt(part, 0, 0)
			if err != nil {
				return nil, false
			}
			current = cv.Index(int(i)).Interface()
		default:
			panic(fmt.Sprintf("Unknown kind: %s", cv.Kind()))
		}
	}

	return current, true
}

// IsSet checks if the key in the configuration is set. A key is set if
// it has a value or the value is being computed (is unknown currently).
//
// This function should be used rather than checking the keys of the
// raw configuration itself, since a key may be omitted from the raw
// configuration if it is being computed.
func (c *ResourceConfig) IsSet(k string) bool {
	if c == nil {
		return false
	}

	for _, ck := range c.ComputedKeys {
		if ck == k {
			return true
		}
	}

	if _, ok := c.Get(k); ok {
		return true
	}

	return false
}

func (c *ResourceConfig) interpolate(ctx *Context) error {
	if c == nil {
		return nil
	}

	if ctx != nil {
		if err := ctx.computeVars(c.raw); err != nil {
			return err
		}
	}

	if c.raw != nil {
		c.ComputedKeys = c.raw.UnknownKeys()
		c.Raw = c.raw.Raw
		c.Config = c.raw.Config()
	}

	return nil
}
<commit_msg>terraform: Store resource config along side provisioner<commit_after>package terraform

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"github.com/hashicorp/terraform/config"
)

// ResourceProvisionerConfig is used to pair a provisioner
// with it's provided configuration. This allows us to use singleton
// instances of each ResourceProvisioner and to keep the relevant
// configuration instead of instantiating a new Provisioner for each
// resource.
type ResourceProvisionerConfig struct {
	Provisioner ResourceProvisioner
	Config      *ResourceConfig
}

// Resource encapsulates a resource, its configuration, its provider,
// its current state, and potentially a desired diff from the state it
// wants to reach.
type Resource struct {
	Id           string
	Config       *ResourceConfig
	Diff         *ResourceDiff
	Provider     ResourceProvider
	State        *ResourceState
	Provisioners []*ResourceProvisionerConfig
}

// Vars returns the mapping of variables that should be replaced in
// configuration based on the attributes of this resource.
func (r *Resource) Vars() map[string]string {
	if r.State == nil {
		return nil
	}

	vars := make(map[string]string)
	for ak, av := range r.State.Attributes {
		vars[fmt.Sprintf("%s.%s", r.Id, ak)] = av
	}

	return vars
}

// ResourceConfig holds the configuration given for a resource. This is
// done instead of a raw `map[string]interface{}` type so that rich
// methods can be added to it to make dealing with it easier.
type ResourceConfig struct {
	ComputedKeys []string
	Raw          map[string]interface{}
	Config       map[string]interface{}

	raw *config.RawConfig
}

// NewResourceConfig creates a new ResourceConfig from a config.RawConfig.
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
	result := &ResourceConfig{raw: c}
	result.interpolate(nil)
	return result
}

// CheckSet checks that the given list of configuration keys is
// properly set. If not, errors are returned for each unset key.
//
// This is useful to be called in the Validate method of a ResourceProvider.
func (c *ResourceConfig) CheckSet(keys []string) []error {
	var errs []error

	for _, k := range keys {
		if !c.IsSet(k) {
			errs = append(errs, fmt.Errorf("%s must be set", k))
		}
	}

	return errs
}

// Get looks up a configuration value by key and returns the value.
//
// The second return value is true if the get was successful. Get will
// not succeed if the value is being computed.
func (c *ResourceConfig) Get(k string) (interface{}, bool) {
	parts := strings.Split(k, ".")

	var current interface{} = c.Raw
	for _, part := range parts {
		if current == nil {
			return nil, false
		}

		cv := reflect.ValueOf(current)
		switch cv.Kind() {
		case reflect.Map:
			v := cv.MapIndex(reflect.ValueOf(part))
			if !v.IsValid() {
				return nil, false
			}
			current = v.Interface()
		case reflect.Slice:
			i, err := strconv.ParseInt(part, 0, 0)
			if err != nil {
				return nil, false
			}
			current = cv.Index(int(i)).Interface()
		default:
			panic(fmt.Sprintf("Unknown kind: %s", cv.Kind()))
		}
	}

	return current, true
}

// IsSet checks if the key in the configuration is set. A key is set if
// it has a value or the value is being computed (is unknown currently).
//
// This function should be used rather than checking the keys of the
// raw configuration itself, since a key may be omitted from the raw
// configuration if it is being computed.
func (c *ResourceConfig) IsSet(k string) bool {
	if c == nil {
		return false
	}

	for _, ck := range c.ComputedKeys {
		if ck == k {
			return true
		}
	}

	if _, ok := c.Get(k); ok {
		return true
	}

	return false
}

func (c *ResourceConfig) interpolate(ctx *Context) error {
	if c == nil {
		return nil
	}

	if ctx != nil {
		if err := ctx.computeVars(c.raw); err != nil {
			return err
		}
	}

	if c.raw != nil {
		c.ComputedKeys = c.raw.UnknownKeys()
		c.Raw = c.raw.Raw
		c.Config = c.raw.Config()
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup

import (
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"os"
	"path"
)

// An object that knows how to save directories to some underlying storage.
type DirectorySaver interface {
	// Recursively save the contents of the supplied directory to the underlying
	// storage, returning the score of a blob representing the directory's
	// listing in a format hat can be recovered with repr.Unmarshal.
	Save(dirpath string) (score blob.Score, err error)
}

type directorySaver struct {
	blobStore blob.Store
	fileSystem fs.FileSystem
	fileSaver FileSaver
	wrapped DirectorySaver
}

func convertCommon(fi os.FileInfo) (fs.DirectoryEntry, error) {
}

func (s *directorySaver) saveDir(parent string, fi os.FileInfo) ([]blob.Score, error) {
	// Recurse.
	score, err := s.wrapped.Save(path.Join(parent, fi.Name()))
	if err != nil {
		return nil, err
	}

	return []blob.Score{score}, nil
}

func (s *directorySaver) saveFile(parent string, fi os.FileInfo) ([]blob.Score, error) {
}

func (s *directorySaver) Save(dirpath string) (score blob.Score, err error) {
	// Grab a listing for the directory.
	fileInfos, err := s.fileSystem.ReadDir(dirpath)
	if err != nil {
		return nil, fmt.Errorf("Listing directory: %v", err)
	}

	// Process each entry in the directory, building a list of DirectoryEntry
	// structs.
	entries := []fs.DirectoryEntry{}
	for _, fileInfo := range fileInfos {
		entry, err := convertCommon(fileInfo)
		if err != nil {
			return nil, err
		}

		// Call the appropriate method based on this entry's type.
		switch {
		case fileInfo.IsDir():
			entry.Scores, err = s.saveDir(dirpath, fileInfo)
		case fileInfo.Mode() & os.ModeType == 0:
			entry.Scores, err = s.saveFile(dirpath, fileInfo)
	  default:
			err = fmt.Errorf("Unhandled mode: %v", fileInfo.Mode())
		}

		if err != nil {
			return nil, err
		}

		entries = append(entries, entry)
	}
}
<commit_msg>Implemented saveFile.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup

import (
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"os"
	"path"
)

// An object that knows how to save directories to some underlying storage.
type DirectorySaver interface {
	// Recursively save the contents of the supplied directory to the underlying
	// storage, returning the score of a blob representing the directory's
	// listing in a format hat can be recovered with repr.Unmarshal.
	Save(dirpath string) (score blob.Score, err error)
}

type directorySaver struct {
	blobStore blob.Store
	fileSystem fs.FileSystem
	fileSaver FileSaver
	wrapped DirectorySaver
}

func convertCommon(fi os.FileInfo) (fs.DirectoryEntry, error) {
}

func (s *directorySaver) saveDir(parent string, fi os.FileInfo) ([]blob.Score, error) {
	// Recurse.
	score, err := s.wrapped.Save(path.Join(parent, fi.Name()))
	if err != nil {
		return nil, err
	}

	return []blob.Score{score}, nil
}

func (s *directorySaver) saveFile(parent string, fi os.FileInfo) ([]blob.Score, error) {
	// Open the file.
	f, err := os.Open(path.Join(parent, fi.Name()))
	if err != nil {
		return nil, fmt.Errorf("Opening file: %v", err)
	}

	// Defer to the file saver.
	return s.fileSaver.Save(f)
}

func (s *directorySaver) Save(dirpath string) (score blob.Score, err error) {
	// Grab a listing for the directory.
	fileInfos, err := s.fileSystem.ReadDir(dirpath)
	if err != nil {
		return nil, fmt.Errorf("Listing directory: %v", err)
	}

	// Process each entry in the directory, building a list of DirectoryEntry
	// structs.
	entries := []fs.DirectoryEntry{}
	for _, fileInfo := range fileInfos {
		entry, err := convertCommon(fileInfo)
		if err != nil {
			return nil, err
		}

		// Call the appropriate method based on this entry's type.
		switch {
		case fileInfo.IsDir():
			entry.Scores, err = s.saveDir(dirpath, fileInfo)
		case fileInfo.Mode() & os.ModeType == 0:
			entry.Scores, err = s.saveFile(dirpath, fileInfo)
	  default:
			err = fmt.Errorf("Unhandled mode: %v", fileInfo.Mode())
		}

		if err != nil {
			return nil, err
		}

		entries = append(entries, entry)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"sync"
)

/// Basket interface ///

type memoryBasket struct {
	sync.RWMutex
	token      string
	config     BasketConfig
	requests   []*RequestData
	totalCount int
}

func (basket *memoryBasket) applyLimit() {
	// Keep requests up to specified capacity
	if len(basket.requests) > basket.config.Capacity {
		basket.requests = basket.requests[:basket.config.Capacity]
	}
}

func (basket *memoryBasket) Config() BasketConfig {
	return basket.config
}

func (basket *memoryBasket) Update(config BasketConfig) {
	basket.Lock()
	defer basket.Unlock()

	basket.config = config
	basket.applyLimit()
}

func (basket *memoryBasket) Authorize(token string) bool {
	return token == basket.token
}

func (basket *memoryBasket) Add(req *http.Request) *RequestData {
	basket.Lock()
	defer basket.Unlock()

	data := ToRequestData(req)
	// insert in front of collection
	basket.requests = append([]*RequestData{data}, basket.requests...)

	// keep total number of all collected requests
	basket.totalCount++
	// apply limits according to basket capacity
	basket.applyLimit()

	return data
}

func (basket *memoryBasket) Clear() {
	basket.Lock()
	defer basket.Unlock()

	// reset collected requests and total counter
	basket.requests = make([]*RequestData, 0, basket.config.Capacity)
	basket.totalCount = 0
}

func (basket *memoryBasket) Size() int {
	return len(basket.requests)
}

func (basket *memoryBasket) GetRequests(max int, skip int) RequestsPage {
	basket.RLock()
	defer basket.RUnlock()

	size := basket.Size()
	last := skip + max

	requestsPage := RequestsPage{
		Count:      size,
		TotalCount: basket.totalCount,
		HasMore:    last < size}

	if skip < size {
		if last > size {
			last = size
		}
		requestsPage.Requests = basket.requests[skip:last]
	}

	return requestsPage
}

/// BasketsDatabase interface ///

type memoryDatabase struct {
	sync.RWMutex
	baskets map[string]*memoryBasket
	names   []string
}

func (db *memoryDatabase) Create(name string, config BasketConfig) (BasketAuth, error) {
	db.Lock()
	defer db.Unlock()

	auth := BasketAuth{}

	_, exists := db.baskets[name]
	if exists {
		return auth, fmt.Errorf("Basket with name '%s' already exists", name)
	}

	token, err := GenerateToken()
	if err != nil {
		return auth, fmt.Errorf("Failed to generate token: %s", err.Error())
	}

	basket := new(memoryBasket)
	basket.token = token
	basket.config = config
	basket.requests = make([]*RequestData, 0, config.Capacity)
	basket.totalCount = 0

	db.baskets[name] = basket
	db.names = append(db.names, name)
	// Uncomment if sorting is expected
	// sort.Strings(db.names)

	auth.Token = token

	return auth, nil
}

func (db *memoryDatabase) Get(name string) Basket {
	basket, _ := db.baskets[name]
	return basket
}

func (db *memoryDatabase) Delete(name string) {
	db.Lock()
	defer db.Unlock()

	delete(db.baskets, name)
	for i, v := range db.names {
		if v == name {
			db.names = append(db.names[:i], db.names[i+1:]...)
			break
		}
	}
}

func (db *memoryDatabase) Size() int {
	return len(db.names)
}

func (db *memoryDatabase) GetNames(max int, skip int) BasketNamesPage {
	db.RLock()
	defer db.RUnlock()

	size := len(db.names)
	last := skip + max

	namesPage := BasketNamesPage{
		Count:   size,
		HasMore: last < size}

	if skip < size {
		if last > size {
			last = size
		}

		namesPage.Names = db.names[skip:last]
	}

	return namesPage
}

// NewMemoryDatabase creates an instance of in-memory Baskets Database
func NewMemoryDatabase() BasketsDatabase {
	return &memoryDatabase{baskets: make(map[string]*memoryBasket), names: make([]string, 0)}
}
<commit_msg>fixed nil pointer issue introduced by switching to interfaces<commit_after>package main

import (
	"fmt"
	"net/http"
	"sync"
)

/// Basket interface ///

type memoryBasket struct {
	sync.RWMutex
	token      string
	config     BasketConfig
	requests   []*RequestData
	totalCount int
}

func (basket *memoryBasket) applyLimit() {
	// Keep requests up to specified capacity
	if len(basket.requests) > basket.config.Capacity {
		basket.requests = basket.requests[:basket.config.Capacity]
	}
}

func (basket *memoryBasket) Config() BasketConfig {
	return basket.config
}

func (basket *memoryBasket) Update(config BasketConfig) {
	basket.Lock()
	defer basket.Unlock()

	basket.config = config
	basket.applyLimit()
}

func (basket *memoryBasket) Authorize(token string) bool {
	return token == basket.token
}

func (basket *memoryBasket) Add(req *http.Request) *RequestData {
	basket.Lock()
	defer basket.Unlock()

	data := ToRequestData(req)
	// insert in front of collection
	basket.requests = append([]*RequestData{data}, basket.requests...)

	// keep total number of all collected requests
	basket.totalCount++
	// apply limits according to basket capacity
	basket.applyLimit()

	return data
}

func (basket *memoryBasket) Clear() {
	basket.Lock()
	defer basket.Unlock()

	// reset collected requests and total counter
	basket.requests = make([]*RequestData, 0, basket.config.Capacity)
	basket.totalCount = 0
}

func (basket *memoryBasket) Size() int {
	return len(basket.requests)
}

func (basket *memoryBasket) GetRequests(max int, skip int) RequestsPage {
	basket.RLock()
	defer basket.RUnlock()

	size := basket.Size()
	last := skip + max

	requestsPage := RequestsPage{
		Count:      size,
		TotalCount: basket.totalCount,
		HasMore:    last < size}

	if skip < size {
		if last > size {
			last = size
		}
		requestsPage.Requests = basket.requests[skip:last]
	}

	return requestsPage
}

/// BasketsDatabase interface ///

type memoryDatabase struct {
	sync.RWMutex
	baskets map[string]*memoryBasket
	names   []string
}

func (db *memoryDatabase) Create(name string, config BasketConfig) (BasketAuth, error) {
	db.Lock()
	defer db.Unlock()

	auth := BasketAuth{}

	_, exists := db.baskets[name]
	if exists {
		return auth, fmt.Errorf("Basket with name '%s' already exists", name)
	}

	token, err := GenerateToken()
	if err != nil {
		return auth, fmt.Errorf("Failed to generate token: %s", err.Error())
	}

	basket := new(memoryBasket)
	basket.token = token
	basket.config = config
	basket.requests = make([]*RequestData, 0, config.Capacity)
	basket.totalCount = 0

	db.baskets[name] = basket
	db.names = append(db.names, name)
	// Uncomment if sorting is expected
	// sort.Strings(db.names)

	auth.Token = token

	return auth, nil
}

func (db *memoryDatabase) Get(name string) Basket {
	basket, exists := db.baskets[name]
	if exists {
		return basket
	} else {
		return nil
	}
}

func (db *memoryDatabase) Delete(name string) {
	db.Lock()
	defer db.Unlock()

	delete(db.baskets, name)
	for i, v := range db.names {
		if v == name {
			db.names = append(db.names[:i], db.names[i+1:]...)
			break
		}
	}
}

func (db *memoryDatabase) Size() int {
	return len(db.names)
}

func (db *memoryDatabase) GetNames(max int, skip int) BasketNamesPage {
	db.RLock()
	defer db.RUnlock()

	size := len(db.names)
	last := skip + max

	namesPage := BasketNamesPage{
		Count:   size,
		HasMore: last < size}

	if skip < size {
		if last > size {
			last = size
		}

		namesPage.Names = db.names[skip:last]
	}

	return namesPage
}

// NewMemoryDatabase creates an instance of in-memory Baskets Database
func NewMemoryDatabase() BasketsDatabase {
	return &memoryDatabase{baskets: make(map[string]*memoryBasket), names: make([]string, 0)}
}
<|endoftext|>


<commit_before>package main

import (
    "encoding/json"
    "fmt"
)

func handleEvent(eventName string, messageContents string, player *Player) {
  switch {
    case eventName == "updateBodyPosition":
      evt_updatePlayerBodyPosition(messageContents, player)
      break
    case eventName == "updateHeadPosition":
      evt_updatePlayerHeadPosition(messageContents, player)
      break
    case eventName == "recvMessage":
      evt_sendMessage(messageContents, player)
      break
    default:
      break
  }
}

//updateBodyPosition:{"x": 1.0, "y": 2.0, "z": 3.0, "r": 4.0}
func evt_updatePlayerBodyPosition(message string, player *Player) {
  byt := []byte(message)
  var dat map[string]interface{}
  if err := json.Unmarshal(byt, &dat); err != nil {
    panic(err)
  }
  x := float32(dat["x"].(float64))
  y := float32(dat["y"].(float64))
  z := float32(dat["z"].(float64))
  r := float32(dat["r"].(float64))
  player.updateBodyPosition(x, y, z, r)
  player.room.broadcast <- []byte(message)
}

func evt_updatePlayerHeadPosition(message string, player *Player) {
  byt := []byte(message)
  var dat map[string]interface{}
  if err := json.Unmarshal(byt, &dat); err != nil {
    panic(err)
  }
  x := float32(dat["x"].(float64))
  y := float32(dat["y"].(float64))
  z := float32(dat["z"].(float64))
  w := float32(dat["w"].(float64))
  player.updateHeadPosition(x, y, z, w)
  player.room.broadcast <- []byte(message)
}

func evt_sendMessage(message string, player *Player) {
  player.room.broadcast <- []byte(message)
}
<commit_msg>Added event names in the outgoing messages.<commit_after>package main

import (
    "encoding/json"
    //"fmt"
)

func handleEvent(eventName string, messageContents string, player *Player) {
  switch {
    case eventName == "ubp": //updateBodyPosition
      evt_updatePlayerBodyPosition(messageContents, player)
      break
    case eventName == "uhp": //updateHeadPosition
      evt_updatePlayerHeadPosition(messageContents, player)
      break
    case eventName == "sm": //sendMessage
      evt_sendMessage(messageContents, player)
      break
    default:
      break
  }
}

//ubp:{"x": 1.0, "y": 2.0, "z": 3.0, "r": 4.0}
func evt_updatePlayerBodyPosition(message string, player *Player) {
  byt := []byte(message)
  var dat map[string]interface{}
  if err := json.Unmarshal(byt, &dat); err != nil {
    panic(err)
  }
  x := float32(dat["x"].(float64))
  y := float32(dat["y"].(float64))
  z := float32(dat["z"].(float64))
  r := float32(dat["r"].(float64))
  player.updateBodyPosition(x, y, z, r)
  player.room.broadcast <- []byte("ubp:" + message)
}

//uhp:{"x": 1.0, "y": 2.0, "z": 3.0, "w": 4.0}
func evt_updatePlayerHeadPosition(message string, player *Player) {
  byt := []byte(message)
  var dat map[string]interface{}
  if err := json.Unmarshal(byt, &dat); err != nil {
    panic(err)
  }
  x := float32(dat["x"].(float64))
  y := float32(dat["y"].(float64))
  z := float32(dat["z"].(float64))
  w := float32(dat["w"].(float64))
  player.updateHeadPosition(x, y, z, w)
  player.room.broadcast <- []byte("uhp:" + message)
}

//sm:test
func evt_sendMessage(message string, player *Player) {
  player.room.broadcast <- []byte("sm:" + message)
}
<|endoftext|>


<commit_before>package bench

import (
	//"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	//"os"
	"math/rand"
	//"sync"
	"time"
)

const (
	MongoDbHosts = "localhost:27017"
	Database     = "journaldb"
	Collection   = "journal"
)

var users = []string{"user1", "user2"}

func Bench(threads int) {
	mongoDbDialInfo := &mgo.DialInfo{
		Addrs:    []string{MongoDbHosts},
		Timeout:  5 * time.Second,
		Database: Database,
	}

	mongoSession, err := mgo.DialWithInfo(mongoDbDialInfo)
	if err != nil {
		panic(err)
	}
	mongoSession.SetMode(mgo.Monotonic, true)
	//var waitGroup sync.WaitGroup
	//      waitGroup.Add(10)
	//t := make(chan *time.Duration)
	ch := make(chan time.Duration)
	for query := 0; query < 100; query++ {
		go RunQuery(query, mongoSession, ch)
	}
	//defer session.Close()

	//mongoSession = session.DB("journaldb").C("journal")
	//      err = mongoSession.Insert(&Person{"Ale", "+55 53 8116 9639"},
	//              &Person{"Cla", "+55 53 8402 8510"})
	//      if err != nil {
	//              log.Fatal(err)
	//      }

	//      var m bson.M

	//      before := time.Now()
	//      err = mongoSession.Find(nil).One(&m)
	//      if err != nil {
	//              log.Fatal(err)
	//      }
	//      elapsed := time.Since(before)
	//      enc := json.NewEncoder(os.Stdout)
	//      enc.SetIndent("", "  ")
	//      if err := enc.Encode(m); err != nil {
	//              panic(err)
	//      }

	//      fmt.Println(elapsed)
	//waitGroup.Wait()
	var x []time.Duration
	for i := 0; i < threads; i++ {
		//var dur []time.Duration
		x = append(x, <-ch)
		//fmt.Println(dur)
	}

	var total time.Duration
	var n, slowest time.Duration
	for _, value := range x {
		total += value
		if value > n {
			n = value
			slowest = n
		}
	}
	fmt.Println("Average: ", total.Seconds()/float64(len(x)), "s")
	fmt.Println("Slowest: ", slowest)
}

func RunQuery(query int, mongoSession *mgo.Session, ch chan time.Duration) {
	//defer waitGroup.Done()
	sessionCopy := mongoSession.Copy()
	rand.Seed(time.Now().UnixNano())
	u := rand.Int() % len(users)

	Collection := sessionCopy.DB("journaldb").C("journal")
	defer sessionCopy.Close()
	var m bson.M
	start := time.Now()
	var q [4]bson.M
	er := bson.UnmarshalJSON([]byte(`{"branchCode": 64}`), &q[0])
	er = bson.UnmarshalJSON([]byte(`{"branchCode": 230}`), &q[1])
	er = bson.UnmarshalJSON([]byte(`{"userName":"`+users[u]+`"}`), &q[2])
	er = bson.UnmarshalJSON([]byte(`{"createDate":{$gte:ISODate("2017-05-22T05:48:15.721Z"),$lt:ISODate("2017-05-25T05:48:15.721Z")}}`), &q[3])

	if er != nil {
		panic("wtf")
	}

	n := rand.Int() % len(q)

	err := Collection.Find(q[n]).One(&m)
	dur := time.Since(start)
	if err != nil {
		log.Println("Find:", err)
	}
	fmt.Println("Query in thread ", query, " Completed. Elapsed Time: ", dur, "and query was: ", q[n])
	ch <- dur

}
<commit_msg>Fixed Threads<commit_after>package bench

import (
	//"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"log"
	//"os"
	"math/rand"
	//"sync"
	"time"
)

const (
	MongoDbHosts = "localhost:27017"
	Database     = "journaldb"
	Collection   = "journal"
)

var users = []string{"user1", "user2"}

func Bench(threads int) {
	mongoDbDialInfo := &mgo.DialInfo{
		Addrs:    []string{MongoDbHosts},
		Timeout:  5 * time.Second,
		Database: Database,
	}

	mongoSession, err := mgo.DialWithInfo(mongoDbDialInfo)
	if err != nil {
		panic(err)
	}
	mongoSession.SetMode(mgo.Monotonic, true)

	ch := make(chan time.Duration)
	for query := 0; query < threads; query++ {
		go RunQuery(query, mongoSession, ch)
	}

	var x []time.Duration
	for i := 0; i < threads; i++ {

		x = append(x, <-ch)

	}

	var total time.Duration
	var n, slowest time.Duration
	for _, value := range x {
		total += value
		if value > n {
			n = value
			slowest = n
		}
	}
	fmt.Println("Average: ", total.Seconds()/float64(len(x)), "s")
	fmt.Println("Slowest: ", slowest)
}

func RunQuery(query int, mongoSession *mgo.Session, ch chan time.Duration) {
	//defer waitGroup.Done()
	sessionCopy := mongoSession.Copy()
	rand.Seed(time.Now().UnixNano())
	u := rand.Int() % len(users)

	Collection := sessionCopy.DB("journaldb").C("journal")
	defer sessionCopy.Close()
	var m bson.M
	start := time.Now()
	var q [4]bson.M
	er := bson.UnmarshalJSON([]byte(`{"branchCode": 64}`), &q[0])
	er = bson.UnmarshalJSON([]byte(`{"branchCode": 230}`), &q[1])
	er = bson.UnmarshalJSON([]byte(`{"userName":"`+users[u]+`"}`), &q[2])
	er = bson.UnmarshalJSON([]byte(`{"createDate":{$gte:ISODate("2017-05-22T05:48:15.721Z"),$lt:ISODate("2017-05-25T05:48:15.721Z")}}`), &q[3])

	if er != nil {
		panic("wtf")
	}

	n := rand.Int() % len(q)

	err := Collection.Find(q[n]).One(&m)
	dur := time.Since(start)
	if err != nil {
		log.Println("Find:", err)
	}
	fmt.Println("Query in thread ", query, " Completed. Elapsed Time: ", dur, "and query was: ", q[n])
	ch <- dur

}
<|endoftext|>


<commit_before>package main

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"gopkg.in/mgo.v2/bson"
	"log"
	"net/http"
	"strings"
	"time"
)

const secretString = "putyoursecretstringhere"

func token(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "POST" {
		err = errors.New("Token endpoint only accepts POST requests!")
		return
	}

	var ud = struct {
		UserName string `json:"userName"`
		Password string `json:"password"`
	}{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&ud)

	userInfo, err := validateUserInDb(ud.UserName, ud.Password)

	if err != nil {
		w.WriteHeader(http.StatusUnauthorized)
		log.Printf("Authorization failed for user '%s' : %s", ud.UserName, err)
		return
	}

	token, id, err := generateToken(userInfo)

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		log.Printf("Could not generate token for user '%s': %s", ud.UserName, err)
		return
	}

	http.SetCookie(w, &http.Cookie{
		Secure:   true,
		HttpOnly: true,
		Name:     "token",
		Value:    string(token),
		MaxAge:   3600,
	})

	mac := hmac.New(sha256.New, []byte(secretString))
	mac.Write([]byte(id))

	http.SetCookie(w, &http.Cookie{
		Secure:   true,
		HttpOnly: false,
		Name:     "Csrf-token",
		Value:    hex.EncodeToString(mac.Sum(nil)),
		MaxAge:   3600,
	})

	w.WriteHeader(http.StatusOK)
	return
}

func generateToken(userInfo *User) ([]byte, string, error) {
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims["exp"] = time.Now().Add(1 * time.Hour).Unix()
	token.Claims["iat"] = time.Now().Unix()

	id := make([]byte, 32)
	_, err := rand.Read(id)

	if nil != err {
		return nil, "", err
	}

	clientId := hex.EncodeToString(id)

	token.Claims["jti"] = clientId

	token.Claims["userInfo"] = map[string]interface{}{
		"userName": userInfo.UserName,
		"email":    userInfo.Email,
		"realName": userInfo.RealName,
		"roles":    strings.Join(userInfo.Roles, ","),
	}

	tokenString, err := token.SignedString([]byte(secretString))

	return []byte(tokenString), clientId, err
}

func userInfo(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	return json.NewEncoder(w).Encode(*data)
}

func allUsers(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	users, err := allUsersInDb()

	if err != nil {
		return
	}

	numOfUsers := len(users)
	userData := make([]middlewareData, numOfUsers)

	for idx, user := range users {
		userData[idx].Email = user.Email
		userData[idx].RealName = user.RealName
		userData[idx].UserName = user.UserName
		userData[idx].Roles = user.Roles
		userData[idx].Id = user.Id.Hex()
	}

	return json.NewEncoder(w).Encode(userData)
}

func deleteUser(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	var ud = struct {
		UserId string `json:"userId"`
	}{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&ud)

	return deleteUserFromDb(ud.UserId)
}

func updateUser(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	userData := middlewareData{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&userData)

	updatedUserData := User{
		Id:       bson.ObjectIdHex(userData.Id),
		Email:    userData.Email,
		UserName: userData.UserName,
		RealName: userData.RealName,
		Roles:    userData.Roles,
	}

	return updateUserInDb(&updatedUserData)
}
<commit_msg>Just checked if the endpoints are used as intended ...<commit_after>package main

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"gopkg.in/mgo.v2/bson"
	"log"
	"net/http"
	"strings"
	"time"
)

const secretString = "putyoursecretstringhere"

func token(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "POST" {
		err = errors.New("Token endpoint only accepts POST requests!")
		return
	}

	var ud = struct {
		UserName string `json:"userName"`
		Password string `json:"password"`
	}{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&ud)

	userInfo, err := validateUserInDb(ud.UserName, ud.Password)

	if err != nil {
		w.WriteHeader(http.StatusUnauthorized)
		log.Printf("Authorization failed for user '%s' : %s", ud.UserName, err)
		return
	}

	token, id, err := generateToken(userInfo)

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		log.Printf("Could not generate token for user '%s': %s", ud.UserName, err)
		return
	}

	http.SetCookie(w, &http.Cookie{
		Secure:   true,
		HttpOnly: true,
		Name:     "token",
		Value:    string(token),
		MaxAge:   3600,
	})

	mac := hmac.New(sha256.New, []byte(secretString))
	mac.Write([]byte(id))

	http.SetCookie(w, &http.Cookie{
		Secure:   true,
		HttpOnly: false,
		Name:     "Csrf-token",
		Value:    hex.EncodeToString(mac.Sum(nil)),
		MaxAge:   3600,
	})

	w.WriteHeader(http.StatusOK)
	return
}

func generateToken(userInfo *User) ([]byte, string, error) {
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims["exp"] = time.Now().Add(1 * time.Hour).Unix()
	token.Claims["iat"] = time.Now().Unix()

	id := make([]byte, 32)
	_, err := rand.Read(id)

	if nil != err {
		return nil, "", err
	}

	clientId := hex.EncodeToString(id)

	token.Claims["jti"] = clientId

	token.Claims["userInfo"] = map[string]interface{}{
		"userName": userInfo.UserName,
		"email":    userInfo.Email,
		"realName": userInfo.RealName,
		"roles":    strings.Join(userInfo.Roles, ","),
	}

	tokenString, err := token.SignedString([]byte(secretString))

	return []byte(tokenString), clientId, err
}

func userInfo(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "GET" {
		return errors.New("User info endpoint only accepts GET requests!")
	}

	return json.NewEncoder(w).Encode(*data)
}

func allUsers(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "GET" {
		return errors.New("All users endpoint only accepts GET requests!")
	}

	users, err := allUsersInDb()

	if err != nil {
		return
	}

	numOfUsers := len(users)
	userData := make([]middlewareData, numOfUsers)

	for idx, user := range users {
		userData[idx].Email = user.Email
		userData[idx].RealName = user.RealName
		userData[idx].UserName = user.UserName
		userData[idx].Roles = user.Roles
		userData[idx].Id = user.Id.Hex()
	}

	return json.NewEncoder(w).Encode(userData)
}

func deleteUser(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "POST" {
		return errors.New("Delete user endpoint only accepts POST requests!")
	}

	var ud = struct {
		UserId string `json:"userId"`
	}{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&ud)

	return deleteUserFromDb(ud.UserId)
}

func updateUser(data *middlewareData, w http.ResponseWriter, req *http.Request) (err error) {
	if req.Method != "POST" {
		return errors.New("Update user endpoint only accepts POST requests!")
	}

	userData := middlewareData{}

	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&userData)

	updatedUserData := User{
		Id:       bson.ObjectIdHex(userData.Id),
		Email:    userData.Email,
		UserName: userData.UserName,
		RealName: userData.RealName,
		Roles:    userData.Roles,
	}

	return updateUserInDb(&updatedUserData)
}
<|endoftext|>