<commit_before>/*
Package dogo provides an client to the DigitalOcean V2 API.

Current endpoints include:

        droplets
        images
        keys
        sizes
        regions
        domains
        actions

Each client requires a DigitalOcean token. Tokens can either be read, write or both read/write; so make sure you have the correct token permissions.

If you export the token as follows:

        $ export $DIGITALOCEAN_TOKEN="token"

For example using the droplet client will go as follows:

        package main

	import (
		"github.com/domluna/dogo"
	)

	func main() {

                // If the token is the empty string("") then it'll attempt
                // to fill the value under env var $DIGITALOCEAN_TOKEN
		client := dogo.NewClient("") // $DIGITALOCEAN_TOKEN

		// get all droplets
		droplets, err := client.ListDroplets()
		if err != nil {
			// deal with error
		}
		// do stuff with droplets
	}
*/
package dogo
<commit_msg>fix formatting<commit_after>/*
Package dogo provides an client to the DigitalOcean V2 API.

Current endpoints include:

        droplets
        images
        keys
        sizes
        regions
        domains
        actions

Each client requires a DigitalOcean token. Tokens can either be read, write or both read/write; so make sure you have the correct token permissions.

If you export the token as follows:

        $ export $DIGITALOCEAN_TOKEN="token"

For example using the droplet client will go as follows:

package main

import (
	"github.com/domluna/dogo"
)

func main() {

        // If the token is the empty string("") then it'll attempt
        // to fill the value under env var $DIGITALOCEAN_TOKEN
	client := dogo.NewClient("") // $DIGITALOCEAN_TOKEN

	// get all droplets
	droplets, err := client.ListDroplets()
	if err != nil {
		// deal with error
	}
	// do stuff with droplets
}
*/
package dogo
<|endoftext|>


<commit_before>//go:generate make all

package main

func main() {
}
<commit_msg>go gen command<commit_after>//go:generate -command make all

package main

func main() {
}
<|endoftext|>


<commit_before>package sysinit

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/docker/docker/daemon/execdriver"
	_ "github.com/docker/docker/daemon/execdriver/lxc"
	_ "github.com/docker/docker/daemon/execdriver/native"
)

func executeProgram(args *execdriver.InitArgs) error {
	dockerInitFct, err := execdriver.GetInitFunc(args.Driver)
	if err != nil {
		panic(err)
	}
	return dockerInitFct(args)
}

// Sys Init code
// This code is run INSIDE the container and is responsible for setting
// up the environment before running the actual process
func SysInit() {
	if len(os.Args) <= 1 {
		fmt.Println("You should not invoke dockerinit manually")
		os.Exit(1)
	}

	var (
		// Get cmdline arguments
		user       = flag.String("u", "", "username or uid")
		gateway    = flag.String("g", "", "gateway address")
		ip         = flag.String("i", "", "ip address")
		workDir    = flag.String("w", "", "workdir")
		privileged = flag.Bool("privileged", false, "privileged mode")
		mtu        = flag.Int("mtu", 1500, "interface mtu")
		driver     = flag.String("driver", "", "exec driver")
		pipe       = flag.Int("pipe", 0, "sync pipe fd")
		console    = flag.String("console", "", "console (pty slave) path")
		root       = flag.String("root", ".", "root path for configuration files")
		capAdd     = flag.String("cap-add", "", "capabilities to add")
		capDrop    = flag.String("cap-drop", "", "capabilities to drop")
	)
	flag.Parse()

	args := &execdriver.InitArgs{
		User:       *user,
		Gateway:    *gateway,
		Ip:         *ip,
		WorkDir:    *workDir,
		Privileged: *privileged,
		Args:       flag.Args(),
		Mtu:        *mtu,
		Driver:     *driver,
		Console:    *console,
		Pipe:       *pipe,
		Root:       *root,
		CapAdd:     *capAdd,
		CapDrop:    *capDrop,
	}

	if err := executeProgram(args); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Ensure thread is locked in sysinit for docker<commit_after>package sysinit

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/docker/docker/daemon/execdriver"
	_ "github.com/docker/docker/daemon/execdriver/lxc"
	_ "github.com/docker/docker/daemon/execdriver/native"
)

func executeProgram(args *execdriver.InitArgs) error {
	dockerInitFct, err := execdriver.GetInitFunc(args.Driver)
	if err != nil {
		panic(err)
	}
	return dockerInitFct(args)
}

// Sys Init code
// This code is run INSIDE the container and is responsible for setting
// up the environment before running the actual process
func SysInit() {
	// The very first thing that we should do is lock the thread so that other
	// system level options will work and not have issues, i.e. setns
	runtime.LockOSThread()

	if len(os.Args) <= 1 {
		fmt.Println("You should not invoke dockerinit manually")
		os.Exit(1)
	}

	var (
		// Get cmdline arguments
		user       = flag.String("u", "", "username or uid")
		gateway    = flag.String("g", "", "gateway address")
		ip         = flag.String("i", "", "ip address")
		workDir    = flag.String("w", "", "workdir")
		privileged = flag.Bool("privileged", false, "privileged mode")
		mtu        = flag.Int("mtu", 1500, "interface mtu")
		driver     = flag.String("driver", "", "exec driver")
		pipe       = flag.Int("pipe", 0, "sync pipe fd")
		console    = flag.String("console", "", "console (pty slave) path")
		root       = flag.String("root", ".", "root path for configuration files")
		capAdd     = flag.String("cap-add", "", "capabilities to add")
		capDrop    = flag.String("cap-drop", "", "capabilities to drop")
	)
	flag.Parse()

	args := &execdriver.InitArgs{
		User:       *user,
		Gateway:    *gateway,
		Ip:         *ip,
		WorkDir:    *workDir,
		Privileged: *privileged,
		Args:       flag.Args(),
		Mtu:        *mtu,
		Driver:     *driver,
		Console:    *console,
		Pipe:       *pipe,
		Root:       *root,
		CapAdd:     *capAdd,
		CapDrop:    *capDrop,
	}

	if err := executeProgram(args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha1"
	"crypto/tls"
	"encoding/hex"
	"errors"
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/nfnt/resize"
	"github.com/vmihailenco/redis"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"syscall"
	"time"
)

// The URL for the default avatar
const DefaultAvatarUrl = "//linuxfr.org/images/default-avatar.png"

// The maximal size for an image is 5MB
const MaxSize = 5 * (1 << 20)

// Force the height of the avatar, width is computed to preserve ratio
const AvatarHeight = 64

// Don't try ro refresh the cache more than once per hour
const CacheRefreshInterval = 3600

// HTTP headers struct
type Headers struct {
	contentType  string
	lastModified string
	cacheControl string
}

// Behaviour is a way to customize handlers
type Behaviour struct {
	// Manipulate the image before sending it (resize for example)
	Manipulate func(body []byte) []byte
	// NotFound is called when we can't find a valid image at the original location
	NotFound func(http.ResponseWriter, *http.Request)
}

// The behaviour for normal images
var ImgBehaviour = Behaviour{
	func(body []byte) []byte {
		return body
	},
	func(w http.ResponseWriter, r *http.Request) {
		http.NotFound(w, r)
	},
}

// The behaviour for avatars
var AvatarBehaviour = Behaviour{
	func(body []byte) []byte {
		img, format, err := image.Decode(bytes.NewReader(body))
		if err != nil {
			return body
		}
		m := resize.Resize(0, AvatarHeight, img, resize.Lanczos3Lut)
		var buf bytes.Buffer
		switch format {
		case "png":
			png.Encode(&buf, m)
		case "jpeg":
			jpeg.Encode(&buf, m, nil)
		}
		if buf.Len() == 0 {
			return body
		}
		return buf.Bytes()
	},
	func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Location", DefaultAvatarUrl)
		w.WriteHeader(http.StatusFound)
	},
}

// The directory for caching files
var directory string

// The connection to redis
var connection *redis.Client

// Check if an URL is valid and not temporary in error
func urlStatus(uri string) error {
	hexists := connection.HExists("img/"+uri, "created_at")
	if err := hexists.Err(); err != nil {
		return err
	}
	if ok := hexists.Val(); !ok {
		return errors.New("Invalid URL")
	}

	hget := connection.HGet("img/"+uri, "status")
	if err := hget.Err(); err == nil {
		if status := hget.Val(); status == "Blocked" {
			return errors.New("Invalid URL")
		}
	}

	get := connection.Get("img/err/" + uri)
	if err := get.Err(); err == nil {
		str := get.Val()
		return errors.New(str)
	}

	return nil
}

// Generate a key for cache from a string
func generateKeyForCache(s string) string {
	h := sha1.New()
	io.WriteString(h, s)
	key := h.Sum(nil)

	// Use 3 levels of hasing to avoid having too many files in the same directory
	return fmt.Sprintf("%s/%x/%x/%x/%x", directory, key[0:1], key[1:2], key[2:3], key[3:])
}

// Generate a key for cache from a string
func generateChecksumForCache(body []byte) string {
	h := sha1.New()
	h.Write(body)
	return fmt.Sprintf("%x", h.Sum(nil))
}

// Retrieve mtime of the cached file
func getModTime(uri string) (modTime string, err error) {
	filename := generateKeyForCache(uri)
	stat, err := os.Stat(filename)
	if err != nil {
		return
	}
	modTime = stat.ModTime().Format(time.RFC1123)
	return
}

// Tell the cache that the metadata we have for that URL is still valid
func resetCacheTimer(uri string) {
	mtime, err := getModTime(uri)
	if err != nil {
		log.Printf("Couldn't Get mtime while resetting cache timer for %s: %s\n", uri, err)
		return
	}
	connection.Set("img/updated/"+uri, mtime)
	connection.Expire("img/updated/"+uri, CacheRefreshInterval)
}

// Fetch image from cache
func fetchImageFromCache(uri string, behaviour Behaviour) (headers Headers, body []byte, ok bool) {
	ok = false

	hget := connection.HGet("img/"+uri, "type")
	if err := hget.Err(); err != nil {
		return
	}
	contentType := hget.Val()

	filename := generateKeyForCache(uri)
	lastModified, err := getModTime(uri)
	if err != nil {
		return
	}

	headers.contentType = contentType
	headers.lastModified = lastModified

	body, err = ioutil.ReadFile(filename)
	ok = err == nil

	exists := connection.Exists("img/updated/" + uri)
	if err := exists.Err(); err == nil {
		if present := exists.Val(); !present {
			go fetchImageFromServer(uri, behaviour)
		}
	}

	return
}

// Save the body and the content-type header in cache
func saveImageInCache(uri string, headers Headers, body []byte) {
	go func() {
		checksum := generateChecksumForCache(body)
		hget := connection.HGet("img/"+uri, "checksum")
		if err := hget.Err(); err == nil {
			if was := hget.Val(); checksum == was {
				resetCacheTimer(uri)
				return
			}
		}

		filename := generateKeyForCache(uri)
		dirname := path.Dir(filename)
		err := os.MkdirAll(dirname, 0755)
		if err != nil {
			return
		}

		// Save the body on disk
		err = ioutil.WriteFile(filename, body, 0644)
		if err != nil {
			log.Printf("Error while writing %s\n", filename)
			return
		}

		// And other infos in redis
		connection.HSet("img/"+uri, "type", headers.contentType)
		connection.HSet("img/"+uri, "checksum", checksum)
		resetCacheTimer(uri)
	}()
}

// Save the error in redis for 10 minutes
func saveErrorInCache(uri string, err error) {
	go func() {
		connection.Set("img/err/"+uri, err.Error())
		connection.Expire("img/err/"+uri, CacheRefreshInterval)
	}()
}

// Fetch the image from the distant server
func fetchImageFromServer(uri string, behaviour Behaviour) (headers Headers, body []byte, err error) {
	// Accepts any certificate in HTTPS
	cfg := &tls.Config{InsecureSkipVerify: true}
	tr := &http.Transport{TLSClientConfig: cfg}
	client := &http.Client{Transport: tr}
	res, err := client.Get(uri)
	if err != nil {
		log.Printf("Error on client.Get %s: %s\n", uri, err)
		return
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		log.Printf("Status code of %s is: %d\n", uri, res.StatusCode)
		err = errors.New("Unexpected status code")
		saveErrorInCache(uri, err)
		return
	}
	if res.ContentLength > MaxSize {
		log.Printf("Exceeded max size for %s: %d\n", uri, res.ContentLength)
		err = errors.New("Exceeded max size")
		saveErrorInCache(uri, err)
		return
	}
	contentType := res.Header.Get("Content-Type")
	if len(contentType) < 5 || contentType[0:5] != "image" {
		log.Printf("%s has an invalid content-type: %s\n", uri, contentType)
		err = errors.New("Invalid content-type")
		saveErrorInCache(uri, err)
		return
	}
	log.Printf("Fetch %s (%s)\n", uri, contentType)

	body, err = ioutil.ReadAll(res.Body)
	if err != nil {
		log.Printf("Error on ioutil.ReadAll for %s: %s\n", uri, err)
		return
	}

	body = behaviour.Manipulate(body)

	headers.contentType = contentType
	headers.lastModified = time.Now().Format(time.RFC1123)
	if urlStatus(uri) == nil {
		saveImageInCache(uri, headers, body)
	}
	return
}

// Fetch image from cache if available, or from the server
func fetchImage(uri string, behaviour Behaviour) (headers Headers, body []byte, err error) {
	err = urlStatus(uri)
	if err != nil {
		return
	}

	headers, body, ok := fetchImageFromCache(uri, behaviour)
	if !ok {
		headers, body, err = fetchImageFromServer(uri, behaviour)
	}
	headers.cacheControl = fmt.Sprintf("public, max-age=%d", CacheRefreshInterval)

	return
}

// Receive an HTTP request, fetch the image and respond with it
func Image(w http.ResponseWriter, r *http.Request, behaviour Behaviour) {
	encoded_url := r.URL.Query().Get(":encoded_url")
	chars, err := hex.DecodeString(encoded_url)
	if err != nil {
		log.Printf("Invalid URL %s\n", encoded_url)
		http.Error(w, "Invalid parameters", 400)
		return
	}
	uri := string(chars)

	headers, body, err := fetchImage(uri, behaviour)
	if err != nil {
		behaviour.NotFound(w, r)
		return
	}
	if headers.lastModified == r.Header.Get("If-Modified-Since") {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Add("Content-Type", headers.contentType)
	w.Header().Add("Last-Modified", headers.lastModified)
	w.Header().Add("Cache-Control", headers.cacheControl)
	w.Write(body)
}

// Receive an HTTP request for an image and respond with it
func Img(w http.ResponseWriter, r *http.Request) {
	Image(w, r, ImgBehaviour)
}

// Receive an HTTP request for an avatar and respond with it
func Avatar(w http.ResponseWriter, r *http.Request) {
	Image(w, r, AvatarBehaviour)
}

// Returns 200 OK if the server is running (for monitoring)
func Status(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Parse the command-line
	var addr string
	var logs string
	var conn string
	flag.StringVar(&addr, "a", "127.0.0.1:8000", "Bind to this address:port")
	flag.StringVar(&logs, "l", "-", "Use this file for logs")
	flag.StringVar(&conn, "r", "localhost:6379/0", "The redis database to use for caching meta")
	flag.StringVar(&directory, "d", "cache", "The directory for the caching files")
	flag.Parse()

	// Logging
	if logs != "-" {
		f, err := os.OpenFile(logs, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			log.Fatal("OpenFile: ", err)
		}
		syscall.Dup2(int(f.Fd()), int(os.Stdout.Fd()))
		syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
	}

	// Redis
	parts := strings.Split(conn, "/")
	host := parts[0]
	db := 0
	if len(parts) >= 2 {
		db, _ = strconv.Atoi(parts[1])
	}
	fmt.Printf("Connection %s  %d\n", host, db)
	connection = redis.NewTCPClient(host, "", int64(db))
	defer connection.Close()

	// Routing
	m := pat.New()
	m.Get("/status", http.HandlerFunc(Status))
	m.Get("/img/:encoded_url/:filename", http.HandlerFunc(Img))
	m.Get("/img/:encoded_url", http.HandlerFunc(Img))
	m.Get("/avatars/:encoded_url/:filename", http.HandlerFunc(Avatar))
	m.Get("/avatars/:encoded_url", http.HandlerFunc(Avatar))
	http.Handle("/", m)

	// Start the HTTP server
	log.Printf("Listening on http://%s/\n", addr)
	server := &http.Server{
		Addr:         addr,
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	}
	err := server.ListenAndServe()
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Nicify saveImageInCache<commit_after>package main

import (
	"bytes"
	"crypto/sha1"
	"crypto/tls"
	"encoding/hex"
	"errors"
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/nfnt/resize"
	"github.com/vmihailenco/redis"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"syscall"
	"time"
)

// The URL for the default avatar
const DefaultAvatarUrl = "//linuxfr.org/images/default-avatar.png"

// The maximal size for an image is 5MB
const MaxSize = 5 * (1 << 20)

// Force the height of the avatar, width is computed to preserve ratio
const AvatarHeight = 64

// Don't try ro refresh the cache more than once per hour
const CacheRefreshInterval = 3600

// HTTP headers struct
type Headers struct {
	contentType  string
	lastModified string
	cacheControl string
}

// Behaviour is a way to customize handlers
type Behaviour struct {
	// Manipulate the image before sending it (resize for example)
	Manipulate func(body []byte) []byte
	// NotFound is called when we can't find a valid image at the original location
	NotFound func(http.ResponseWriter, *http.Request)
}

// The behaviour for normal images
var ImgBehaviour = Behaviour{
	func(body []byte) []byte {
		return body
	},
	func(w http.ResponseWriter, r *http.Request) {
		http.NotFound(w, r)
	},
}

// The behaviour for avatars
var AvatarBehaviour = Behaviour{
	func(body []byte) []byte {
		img, format, err := image.Decode(bytes.NewReader(body))
		if err != nil {
			return body
		}
		m := resize.Resize(0, AvatarHeight, img, resize.Lanczos3Lut)
		var buf bytes.Buffer
		switch format {
		case "png":
			png.Encode(&buf, m)
		case "jpeg":
			jpeg.Encode(&buf, m, nil)
		}
		if buf.Len() == 0 {
			return body
		}
		return buf.Bytes()
	},
	func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Location", DefaultAvatarUrl)
		w.WriteHeader(http.StatusFound)
	},
}

// The directory for caching files
var directory string

// The connection to redis
var connection *redis.Client

// Check if an URL is valid and not temporary in error
func urlStatus(uri string) error {
	hexists := connection.HExists("img/"+uri, "created_at")
	if err := hexists.Err(); err != nil {
		return err
	}
	if ok := hexists.Val(); !ok {
		return errors.New("Invalid URL")
	}

	hget := connection.HGet("img/"+uri, "status")
	if err := hget.Err(); err == nil {
		if status := hget.Val(); status == "Blocked" {
			return errors.New("Invalid URL")
		}
	}

	get := connection.Get("img/err/" + uri)
	if err := get.Err(); err == nil {
		str := get.Val()
		return errors.New(str)
	}

	return nil
}

// Generate a key for cache from a string
func generateKeyForCache(s string) string {
	h := sha1.New()
	io.WriteString(h, s)
	key := h.Sum(nil)

	// Use 3 levels of hasing to avoid having too many files in the same directory
	return fmt.Sprintf("%s/%x/%x/%x/%x", directory, key[0:1], key[1:2], key[2:3], key[3:])
}

// Generate a key for cache from a string
func generateChecksumForCache(body []byte) string {
	h := sha1.New()
	h.Write(body)
	return fmt.Sprintf("%x", h.Sum(nil))
}

// Retrieve mtime of the cached file
func getModTime(uri string) (modTime string, err error) {
	filename := generateKeyForCache(uri)
	stat, err := os.Stat(filename)
	if err != nil {
		return
	}
	modTime = stat.ModTime().Format(time.RFC1123)
	return
}

// Tell the cache that the metadata we have for that URL is still valid
func resetCacheTimer(uri string) {
	mtime, err := getModTime(uri)
	if err != nil {
		log.Printf("Couldn't Get mtime while resetting cache timer for %s: %s\n", uri, err)
		return
	}
	connection.Set("img/updated/"+uri, mtime)
	connection.Expire("img/updated/"+uri, CacheRefreshInterval)
}

// Fetch image from cache
func fetchImageFromCache(uri string, behaviour Behaviour) (headers Headers, body []byte, ok bool) {
	ok = false

	hget := connection.HGet("img/"+uri, "type")
	if err := hget.Err(); err != nil {
		return
	}
	contentType := hget.Val()

	filename := generateKeyForCache(uri)
	lastModified, err := getModTime(uri)
	if err != nil {
		return
	}

	headers.contentType = contentType
	headers.lastModified = lastModified

	body, err = ioutil.ReadFile(filename)
	ok = err == nil

	exists := connection.Exists("img/updated/" + uri)
	if err := exists.Err(); err == nil {
		if present := exists.Val(); !present {
			go fetchImageFromServer(uri, behaviour)
		}
	}

	return
}

// Save the body and the content-type header in cache
func saveImageInCache(uri string, headers Headers, body []byte) {
	checksum := generateChecksumForCache(body)
	hget := connection.HGet("img/"+uri, "checksum")
	if err := hget.Err(); err == nil {
		if was := hget.Val(); checksum == was {
			resetCacheTimer(uri)
			return
		}
	}

	filename := generateKeyForCache(uri)
	dirname := path.Dir(filename)
	err := os.MkdirAll(dirname, 0755)
	if err != nil {
		return
	}

	// Save the body on disk
	err = ioutil.WriteFile(filename, body, 0644)
	if err != nil {
		log.Printf("Error while writing %s\n", filename)
		return
	}

	// And other infos in redis
	connection.HSet("img/"+uri, "type", headers.contentType)
	connection.HSet("img/"+uri, "checksum", checksum)
	resetCacheTimer(uri)
}

// Save the error in redis for 10 minutes
func saveErrorInCache(uri string, err error) {
	go func() {
		connection.Set("img/err/"+uri, err.Error())
		connection.Expire("img/err/"+uri, CacheRefreshInterval)
	}()
}

// Fetch the image from the distant server
func fetchImageFromServer(uri string, behaviour Behaviour) (headers Headers, body []byte, err error) {
	// Accepts any certificate in HTTPS
	cfg := &tls.Config{InsecureSkipVerify: true}
	tr := &http.Transport{TLSClientConfig: cfg}
	client := &http.Client{Transport: tr}
	res, err := client.Get(uri)
	if err != nil {
		log.Printf("Error on client.Get %s: %s\n", uri, err)
		return
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		log.Printf("Status code of %s is: %d\n", uri, res.StatusCode)
		err = errors.New("Unexpected status code")
		saveErrorInCache(uri, err)
		return
	}
	if res.ContentLength > MaxSize {
		log.Printf("Exceeded max size for %s: %d\n", uri, res.ContentLength)
		err = errors.New("Exceeded max size")
		saveErrorInCache(uri, err)
		return
	}
	contentType := res.Header.Get("Content-Type")
	if len(contentType) < 5 || contentType[0:5] != "image" {
		log.Printf("%s has an invalid content-type: %s\n", uri, contentType)
		err = errors.New("Invalid content-type")
		saveErrorInCache(uri, err)
		return
	}
	log.Printf("Fetch %s (%s)\n", uri, contentType)

	body, err = ioutil.ReadAll(res.Body)
	if err != nil {
		log.Printf("Error on ioutil.ReadAll for %s: %s\n", uri, err)
		return
	}

	body = behaviour.Manipulate(body)

	headers.contentType = contentType
	headers.lastModified = time.Now().Format(time.RFC1123)
	if urlStatus(uri) == nil {
		go saveImageInCache(uri, headers, body)
	}
	return
}

// Fetch image from cache if available, or from the server
func fetchImage(uri string, behaviour Behaviour) (headers Headers, body []byte, err error) {
	err = urlStatus(uri)
	if err != nil {
		return
	}

	headers, body, ok := fetchImageFromCache(uri, behaviour)
	if !ok {
		headers, body, err = fetchImageFromServer(uri, behaviour)
	}
	headers.cacheControl = fmt.Sprintf("public, max-age=%d", CacheRefreshInterval)

	return
}

// Receive an HTTP request, fetch the image and respond with it
func Image(w http.ResponseWriter, r *http.Request, behaviour Behaviour) {
	encoded_url := r.URL.Query().Get(":encoded_url")
	chars, err := hex.DecodeString(encoded_url)
	if err != nil {
		log.Printf("Invalid URL %s\n", encoded_url)
		http.Error(w, "Invalid parameters", 400)
		return
	}
	uri := string(chars)

	headers, body, err := fetchImage(uri, behaviour)
	if err != nil {
		behaviour.NotFound(w, r)
		return
	}
	if headers.lastModified == r.Header.Get("If-Modified-Since") {
		w.WriteHeader(http.StatusNotModified)
		return
	}
	w.Header().Add("Content-Type", headers.contentType)
	w.Header().Add("Last-Modified", headers.lastModified)
	w.Header().Add("Cache-Control", headers.cacheControl)
	w.Write(body)
}

// Receive an HTTP request for an image and respond with it
func Img(w http.ResponseWriter, r *http.Request) {
	Image(w, r, ImgBehaviour)
}

// Receive an HTTP request for an avatar and respond with it
func Avatar(w http.ResponseWriter, r *http.Request) {
	Image(w, r, AvatarBehaviour)
}

// Returns 200 OK if the server is running (for monitoring)
func Status(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Parse the command-line
	var addr string
	var logs string
	var conn string
	flag.StringVar(&addr, "a", "127.0.0.1:8000", "Bind to this address:port")
	flag.StringVar(&logs, "l", "-", "Use this file for logs")
	flag.StringVar(&conn, "r", "localhost:6379/0", "The redis database to use for caching meta")
	flag.StringVar(&directory, "d", "cache", "The directory for the caching files")
	flag.Parse()

	// Logging
	if logs != "-" {
		f, err := os.OpenFile(logs, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			log.Fatal("OpenFile: ", err)
		}
		syscall.Dup2(int(f.Fd()), int(os.Stdout.Fd()))
		syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
	}

	// Redis
	parts := strings.Split(conn, "/")
	host := parts[0]
	db := 0
	if len(parts) >= 2 {
		db, _ = strconv.Atoi(parts[1])
	}
	fmt.Printf("Connection %s  %d\n", host, db)
	connection = redis.NewTCPClient(host, "", int64(db))
	defer connection.Close()

	// Routing
	m := pat.New()
	m.Get("/status", http.HandlerFunc(Status))
	m.Get("/img/:encoded_url/:filename", http.HandlerFunc(Img))
	m.Get("/img/:encoded_url", http.HandlerFunc(Img))
	m.Get("/avatars/:encoded_url/:filename", http.HandlerFunc(Avatar))
	m.Get("/avatars/:encoded_url", http.HandlerFunc(Avatar))
	http.Handle("/", m)

	// Start the HTTP server
	log.Printf("Listening on http://%s/\n", addr)
	server := &http.Server{
		Addr:         addr,
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	}
	err := server.ListenAndServe()
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package scamp

import (
	"bytes"
	"encoding/json"
)

type MessageChan chan *Message

type Message struct {
	Action   string
	Envelope envelopeFormat
	// TODO: how do RequestId's fit in again? NOTE: from (SCAMP repo) -"Set to 18 random base64 bytes"
	RequestId        int
	Version          int64
	MessageType      messageType
	packets          []*Packet
	bytesWritten     uint64
	Ticket           string
	IdentifyingToken string
	Error            string
	ErrorCode        string
}

// Notes from scamp repo:
// action	    request	  The full action name, e.g. Customer.Order.create
// envelope	  request	  String identifying the envelope format, e.g. json
// error	    reply	    Humanreadable error if present
// error_code	reply	    Error code if present
// message_id	both	    String used to correlate requests to responses in the event of reordering. RECOMMENDED 18 random bytes base64-encoded.
// station	  request	  A station ticket, see Ticket format. Optional
// ticket	    request	  An authorization ticket, see Ticket format. Optional
// type	      both	    request or reply
// version	  request	  Action version number

func NewMessage() (msg *Message) {
	msg = new(Message)
	return
}

func NewRequestMessage() (msg *Message) {
	msg = new(Message)
	msg.SetMessageType(1)
	return
}

func NewResponseMessage() (msg *Message) {
	msg = new(Message)
	msg.SetMessageType(2)
	return
}

func (msg *Message) SetAction(action string) {
	msg.Action = action
}

func (msg *Message) SetEnvelope(env envelopeFormat) {
	msg.Envelope = env
}

func (msg *Message) SetVersion(version int64) {
	msg.Version = version
}

func (msg *Message) SetMessageType(mtype messageType) {
	msg.MessageType = mtype
}

func (msg *Message) SetRequestId(requestId int) {
	msg.RequestId = requestId
}

func (msg *Message) SetTicket(ticket string) {
	msg.Ticket = ticket
}

func (msg *Message) SetIdentifyingToken(token string) {
	msg.IdentifyingToken = token
}

func (msg *Message) SetError(err string) {
	msg.Error = err
}

func (msg *Message) SetErrorCode(errCode string) {
	msg.ErrorCode = errCode
}

func (msg *Message) GetError() (err string) {
	return msg.Error
}

func (msg *Message) GetErrorCode() (errCode string) {
	return msg.ErrorCode
}

func (msg *Message) GetTicket() (ticket string) {
	return msg.Ticket
}

func (msg *Message) GetIdentifyingToken() (token string) {
	return msg.IdentifyingToken
}

func (msg *Message) Write(blob []byte) (n int, err error) {
	// TODO: should this be a sync add?
	msg.bytesWritten += uint64(len(blob))

	msg.packets = append(msg.packets, &Packet{packetType: DATA, body: blob})
	return len(blob), nil
}

var MSG_CHUNK_SIZE = 256 * 1024

func (msg *Message) WriteJson(data interface{}) (n int, err error) {
	var buf bytes.Buffer
	err = json.NewEncoder(&buf).Encode(data)
	if err != nil {
		return
	}

	msg.bytesWritten += uint64(len(buf.Bytes()))

	// Trace.Printf("WriteJson data size: %d", len(buf.Bytes()))

	if len(buf.Bytes()) > MSG_CHUNK_SIZE {
		slice := buf.Bytes()[:]
		for {
			// Trace.Printf("slice size: %d", len(slice))

			if len(slice) < MSG_CHUNK_SIZE {
				msg.packets = append(msg.packets, &Packet{packetType: DATA, body: slice})
				break
			} else {
				chunk := make([]byte, MSG_CHUNK_SIZE)
				copy(chunk, slice[0:MSG_CHUNK_SIZE])
				slice = slice[MSG_CHUNK_SIZE:]
				msg.packets = append(msg.packets, &Packet{packetType: DATA, body: chunk})
			}
		}

	} else {
		msg.packets = append(msg.packets, &Packet{packetType: DATA, body: buf.Bytes()})
	}

	return
}

func (msg *Message) BytesWritten() uint64 {
	return msg.bytesWritten
}

func (msg *Message) toPackets(msgNo uint64) []*Packet {
	headerHeader := PacketHeader{
		Action:           msg.Action,
		Envelope:         msg.Envelope,
		Version:          msg.Version,
		RequestId:        msg.RequestId, // TODO: nope, can't do this
		MessageType:      msg.MessageType,
		Ticket:           msg.GetTicket(),
		IdentifyingToken: msg.GetIdentifyingToken(),
	}

	headerPacket := Packet{
		packetHeader: headerHeader,
		packetType:   HEADER,
		msgNo:        msgNo,
	}

	eofPacket := Packet{
		packetType: EOF,
		msgNo:      msgNo,
	}

	packets := make([]*Packet, 1)
	packets[0] = &headerPacket

	for _, dataPacket := range msg.packets {
		dataPacket.msgNo = msgNo
		packets = append(packets, dataPacket)
	}

	packets = append(packets, &eofPacket)

	return packets
}

func (msg *Message) Bytes() []byte {
	buf := new(bytes.Buffer)
	// Info.Printf("packet count: %d", len(msg.packets))
	// for _,pkt := range msg.packets {
	//   Info.Printf("packet len: %d", len(pkt.body))
	// }
	for _, pkt := range msg.packets {
		buf.Write(pkt.body)
	}

	return buf.Bytes()
}
<commit_msg>Support for Error + ErrorCode<commit_after>package scamp

import (
	"bytes"
	"encoding/json"
)

type MessageChan chan *Message

type Message struct {
	Action   string
	Envelope envelopeFormat
	// TODO: how do RequestId's fit in again? NOTE: from (SCAMP repo) -"Set to 18 random base64 bytes"
	RequestId        int
	Version          int64
	MessageType      messageType
	packets          []*Packet
	bytesWritten     uint64
	Ticket           string
	IdentifyingToken string
	Error            string
	ErrorCode        string
}

// Notes from scamp repo:
// action	    request	  The full action name, e.g. Customer.Order.create
// envelope	  request	  String identifying the envelope format, e.g. json
// error	    reply	    Humanreadable error if present
// error_code	reply	    Error code if present
// message_id	both	    String used to correlate requests to responses in the event of reordering. RECOMMENDED 18 random bytes base64-encoded.
// station	  request	  A station ticket, see Ticket format. Optional
// ticket	    request	  An authorization ticket, see Ticket format. Optional
// type	      both	    request or reply
// version	  request	  Action version number

func NewMessage() (msg *Message) {
	msg = new(Message)
	return
}

func NewRequestMessage() (msg *Message) {
	msg = new(Message)
	msg.SetMessageType(1)
	return
}

func NewResponseMessage() (msg *Message) {
	msg = new(Message)
	msg.SetMessageType(2)
	return
}

func (msg *Message) SetAction(action string) {
	msg.Action = action
}

func (msg *Message) SetEnvelope(env envelopeFormat) {
	msg.Envelope = env
}

func (msg *Message) SetVersion(version int64) {
	msg.Version = version
}

func (msg *Message) SetMessageType(mtype messageType) {
	msg.MessageType = mtype
}

func (msg *Message) SetRequestId(requestId int) {
	msg.RequestId = requestId
}

func (msg *Message) SetTicket(ticket string) {
	msg.Ticket = ticket
}

func (msg *Message) SetIdentifyingToken(token string) {
	msg.IdentifyingToken = token
}

func (msg *Message) SetError(err string) {
	msg.Error = err
}

func (msg *Message) SetErrorCode(errCode string) {
	msg.ErrorCode = errCode
}

func (msg *Message) GetError() (err string) {
	return msg.Error
}

func (msg *Message) GetErrorCode() (errCode string) {
	return msg.ErrorCode
}

func (msg *Message) GetTicket() (ticket string) {
	return msg.Ticket
}

func (msg *Message) GetIdentifyingToken() (token string) {
	return msg.IdentifyingToken
}

func (msg *Message) Write(blob []byte) (n int, err error) {
	// TODO: should this be a sync add?
	msg.bytesWritten += uint64(len(blob))

	msg.packets = append(msg.packets, &Packet{packetType: DATA, body: blob})
	return len(blob), nil
}

var MSG_CHUNK_SIZE = 256 * 1024

func (msg *Message) WriteJson(data interface{}) (n int, err error) {
	var buf bytes.Buffer
	err = json.NewEncoder(&buf).Encode(data)
	if err != nil {
		return
	}

	msg.bytesWritten += uint64(len(buf.Bytes()))

	// Trace.Printf("WriteJson data size: %d", len(buf.Bytes()))

	if len(buf.Bytes()) > MSG_CHUNK_SIZE {
		slice := buf.Bytes()[:]
		for {
			// Trace.Printf("slice size: %d", len(slice))

			if len(slice) < MSG_CHUNK_SIZE {
				msg.packets = append(msg.packets, &Packet{packetType: DATA, body: slice})
				break
			} else {
				chunk := make([]byte, MSG_CHUNK_SIZE)
				copy(chunk, slice[0:MSG_CHUNK_SIZE])
				slice = slice[MSG_CHUNK_SIZE:]
				msg.packets = append(msg.packets, &Packet{packetType: DATA, body: chunk})
			}
		}

	} else {
		msg.packets = append(msg.packets, &Packet{packetType: DATA, body: buf.Bytes()})
	}

	return
}

func (msg *Message) BytesWritten() uint64 {
	return msg.bytesWritten
}

func (msg *Message) toPackets(msgNo uint64) []*Packet {
	headerHeader := PacketHeader{
		Action:           msg.Action,
		Envelope:         msg.Envelope,
		Version:          msg.Version,
		RequestId:        msg.RequestId, // TODO: nope, can't do this
		MessageType:      msg.MessageType,
		Error:            msg.Error,
		ErrorCode:        msg.Error,
		Ticket:           msg.GetTicket(),
		IdentifyingToken: msg.GetIdentifyingToken(),
	}

	headerPacket := Packet{
		packetHeader: headerHeader,
		packetType:   HEADER,
		msgNo:        msgNo,
	}

	eofPacket := Packet{
		packetType: EOF,
		msgNo:      msgNo,
	}

	packets := make([]*Packet, 1)
	packets[0] = &headerPacket

	for _, dataPacket := range msg.packets {
		dataPacket.msgNo = msgNo
		packets = append(packets, dataPacket)
	}

	packets = append(packets, &eofPacket)

	return packets
}

func (msg *Message) Bytes() []byte {
	buf := new(bytes.Buffer)
	// Info.Printf("packet count: %d", len(msg.packets))
	// for _,pkt := range msg.packets {
	//   Info.Printf("packet len: %d", len(pkt.body))
	// }
	for _, pkt := range msg.packets {
		buf.Write(pkt.body)
	}

	return buf.Bytes()
}
<|endoftext|>


<commit_before>package systemd

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

	"github.com/coreos/fleet/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus"

	"github.com/coreos/fleet/log"
	"github.com/coreos/fleet/pkg"
	"github.com/coreos/fleet/unit"
)

const (
	DefaultUnitsDirectory = "/run/fleet/units/"
)

type systemdUnitManager struct {
	systemd  *dbus.Conn
	UnitsDir string

	hashes map[string]unit.Hash
	mutex  sync.RWMutex
}

func NewSystemdUnitManager(uDir string) (*systemdUnitManager, error) {
	systemd, err := dbus.New()
	if err != nil {
		return nil, err
	}

	if err := os.MkdirAll(uDir, os.FileMode(0755)); err != nil {
		return nil, err
	}

	mgr := systemdUnitManager{
		systemd:  systemd,
		UnitsDir: uDir,
		hashes:   make(map[string]unit.Hash),
		mutex:    sync.RWMutex{},
	}
	return &mgr, nil
}

// Load writes the given Unit to disk, subscribing to relevant dbus
// events, caching the Unit's Hash, and, if necessary, instructing the systemd
// daemon to reload.
func (m *systemdUnitManager) Load(name string, u unit.UnitFile) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	err := m.writeUnit(name, u.String())
	if err != nil {
		return err
	}
	m.hashes[name] = u.Hash()
	return m.daemonReload()
}

// Unload removes the indicated unit from the filesystem, deletes its
// associated Hash from the cache, clears its unit status in systemd, and
// performs a systemd daemon-reload
func (m *systemdUnitManager) Unload(name string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	delete(m.hashes, name)
	m.removeUnit(name)
	m.daemonReload()
}

// TriggerStart asynchronously starts the unit identified by the given name.
// This function does not block for the underlying unit to actually start.
func (m *systemdUnitManager) TriggerStart(name string) {
	jobID, err := m.systemd.StartUnit(name, "replace", nil)
	if err == nil {
		log.Infof("Triggered systemd unit %s start: job=%d", name, jobID)
	} else {
		log.Errorf("Failed to trigger systemd unit %s start: %v", name, err)
	}
}

// TriggerStop asynchronously starts the unit identified by the given name.
// This function does not block for the underlying unit to actually stop.
func (m *systemdUnitManager) TriggerStop(name string) {
	jobID, err := m.systemd.StopUnit(name, "replace", nil)
	if err == nil {
		log.Infof("Triggered systemd unit %s stop: job=%d", name, jobID)
	} else {
		log.Errorf("Failed to trigger systemd unit %s stop: %v", name, err)
	}
}

// GetUnitState generates a UnitState object representing the
// current state of a Unit
func (m *systemdUnitManager) GetUnitState(name string) (*unit.UnitState, error) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	us, err := m.getUnitState(name)
	if err != nil {
		return nil, err
	}
	if h, ok := m.hashes[name]; ok {
		us.UnitHash = h.String()
	}
	return us, nil
}

func (m *systemdUnitManager) getUnitState(name string) (*unit.UnitState, error) {
	info, err := m.systemd.GetUnitProperties(name)
	if err != nil {
		return nil, err
	}
	us := unit.UnitState{
		LoadState:   info["LoadState"].(string),
		ActiveState: info["ActiveState"].(string),
		SubState:    info["SubState"].(string),
	}
	return &us, nil
}

func (m *systemdUnitManager) readUnit(name string) (string, error) {
	path := m.getUnitFilePath(name)
	contents, err := ioutil.ReadFile(path)
	if err == nil {
		return string(contents), nil
	}
	return "", fmt.Errorf("no unit file at local path %s", path)
}

func (m *systemdUnitManager) unitRequiresDaemonReload(name string) bool {
	prop, err := m.systemd.GetUnitProperty(name, "NeedDaemonReload")
	if prop == nil || err != nil {
		return false
	}

	return prop.Value.Value().(bool)
}

func (m *systemdUnitManager) daemonReload() error {
	log.Infof("Instructing systemd to reload units")
	return m.systemd.Reload()
}

// Units enumerates all files recognized as valid systemd units in
// this manager's units directory.
func (m *systemdUnitManager) Units() (units []string, err error) {
	fis, err := ioutil.ReadDir(m.UnitsDir)
	if err != nil {
		return
	}

	for _, fi := range fis {
		name := fi.Name()
		if !unit.RecognizedUnitType(name) {
			log.Warningf("Found unrecognized file in %s, ignoring", path.Join(m.UnitsDir, name))
			continue
		}
		units = append(units, name)
	}
	return
}

func (m *systemdUnitManager) GetUnitStates(filter pkg.Set) (map[string]*unit.UnitState, error) {
	// Unfortunately we need to lock for the entire operation to ensure we
	// have a consistent view of the hashes. Otherwise, Load/Unload
	// operations could mutate the hashes before we've retrieved the state
	// for every unit in the filter, since they won't necessarily all be
	// present in the initial ListUnits() call.
	m.mutex.Lock()
	defer m.mutex.Unlock()
	dbusStatuses, err := m.systemd.ListUnits()

	if err != nil {
		return nil, err
	}

	states := make(map[string]*unit.UnitState)
	for _, dus := range dbusStatuses {
		if !filter.Contains(dus.Name) {
			continue
		}

		us := &unit.UnitState{
			LoadState:   dus.LoadState,
			ActiveState: dus.ActiveState,
			SubState:    dus.SubState,
		}
		if h, ok := m.hashes[dus.Name]; ok {
			us.UnitHash = h.String()
		}
		states[dus.Name] = us
	}

	// grab data on subscribed units that didn't show up in ListUnits, most
	// likely due to being inactive
	for _, name := range filter.Values() {
		if _, ok := states[name]; ok {
			continue
		}

		us, err := m.getUnitState(name)
		if err != nil {
			return nil, err
		}
		if h, ok := m.hashes[name]; ok {
			us.UnitHash = h.String()
		}
		states[name] = us
	}

	return states, nil
}

func (m *systemdUnitManager) writeUnit(name string, contents string) error {
	bContents := []byte(contents)
	log.Infof("Writing systemd unit %s (%db)", name, len(bContents))

	ufPath := m.getUnitFilePath(name)
	err := ioutil.WriteFile(ufPath, bContents, os.FileMode(0644))
	if err != nil {
		return err
	}

	_, err = m.systemd.LinkUnitFiles([]string{ufPath}, true, true)
	return err
}

func (m *systemdUnitManager) removeUnit(name string) {
	log.Infof("Removing systemd unit %s", name)

	m.systemd.DisableUnitFiles([]string{name}, true)
	m.systemd.ResetFailedUnit(name)

	ufPath := m.getUnitFilePath(name)
	os.Remove(ufPath)
}

func (m *systemdUnitManager) getUnitFilePath(name string) string {
	return path.Join(m.UnitsDir, name)
}
<commit_msg>systemd: only reload if necessary<commit_after>package systemd

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

	"github.com/coreos/fleet/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus"

	"github.com/coreos/fleet/log"
	"github.com/coreos/fleet/pkg"
	"github.com/coreos/fleet/unit"
)

const (
	DefaultUnitsDirectory = "/run/fleet/units/"
)

type systemdUnitManager struct {
	systemd  *dbus.Conn
	UnitsDir string

	hashes map[string]unit.Hash
	mutex  sync.RWMutex
}

func NewSystemdUnitManager(uDir string) (*systemdUnitManager, error) {
	systemd, err := dbus.New()
	if err != nil {
		return nil, err
	}

	if err := os.MkdirAll(uDir, os.FileMode(0755)); err != nil {
		return nil, err
	}

	mgr := systemdUnitManager{
		systemd:  systemd,
		UnitsDir: uDir,
		hashes:   make(map[string]unit.Hash),
		mutex:    sync.RWMutex{},
	}
	return &mgr, nil
}

// Load writes the given Unit to disk, subscribing to relevant dbus
// events, caching the Unit's Hash, and, if necessary, instructing the systemd
// daemon to reload.
func (m *systemdUnitManager) Load(name string, u unit.UnitFile) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	err := m.writeUnit(name, u.String())
	if err != nil {
		return err
	}
	m.hashes[name] = u.Hash()
	if m.unitRequiresDaemonReload(name) {
		return m.daemonReload()
	}
	return nil
}

// Unload removes the indicated unit from the filesystem, deletes its
// associated Hash from the cache, clears its unit status in systemd, and
// performs a systemd daemon-reload
func (m *systemdUnitManager) Unload(name string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	delete(m.hashes, name)
	m.removeUnit(name)
	if m.unitRequiresDaemonReload(name) {
		m.daemonReload()
	}
}

// TriggerStart asynchronously starts the unit identified by the given name.
// This function does not block for the underlying unit to actually start.
func (m *systemdUnitManager) TriggerStart(name string) {
	jobID, err := m.systemd.StartUnit(name, "replace", nil)
	if err == nil {
		log.Infof("Triggered systemd unit %s start: job=%d", name, jobID)
	} else {
		log.Errorf("Failed to trigger systemd unit %s start: %v", name, err)
	}
}

// TriggerStop asynchronously starts the unit identified by the given name.
// This function does not block for the underlying unit to actually stop.
func (m *systemdUnitManager) TriggerStop(name string) {
	jobID, err := m.systemd.StopUnit(name, "replace", nil)
	if err == nil {
		log.Infof("Triggered systemd unit %s stop: job=%d", name, jobID)
	} else {
		log.Errorf("Failed to trigger systemd unit %s stop: %v", name, err)
	}
}

// GetUnitState generates a UnitState object representing the
// current state of a Unit
func (m *systemdUnitManager) GetUnitState(name string) (*unit.UnitState, error) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	us, err := m.getUnitState(name)
	if err != nil {
		return nil, err
	}
	if h, ok := m.hashes[name]; ok {
		us.UnitHash = h.String()
	}
	return us, nil
}

func (m *systemdUnitManager) getUnitState(name string) (*unit.UnitState, error) {
	info, err := m.systemd.GetUnitProperties(name)
	if err != nil {
		return nil, err
	}
	us := unit.UnitState{
		LoadState:   info["LoadState"].(string),
		ActiveState: info["ActiveState"].(string),
		SubState:    info["SubState"].(string),
	}
	return &us, nil
}

func (m *systemdUnitManager) readUnit(name string) (string, error) {
	path := m.getUnitFilePath(name)
	contents, err := ioutil.ReadFile(path)
	if err == nil {
		return string(contents), nil
	}
	return "", fmt.Errorf("no unit file at local path %s", path)
}

func (m *systemdUnitManager) unitRequiresDaemonReload(name string) bool {
	prop, err := m.systemd.GetUnitProperty(name, "NeedDaemonReload")
	if prop == nil || err != nil {
		return false
	}

	return prop.Value.Value().(bool)
}

func (m *systemdUnitManager) daemonReload() error {
	log.Infof("Instructing systemd to reload units")
	return m.systemd.Reload()
}

// Units enumerates all files recognized as valid systemd units in
// this manager's units directory.
func (m *systemdUnitManager) Units() (units []string, err error) {
	fis, err := ioutil.ReadDir(m.UnitsDir)
	if err != nil {
		return
	}

	for _, fi := range fis {
		name := fi.Name()
		if !unit.RecognizedUnitType(name) {
			log.Warningf("Found unrecognized file in %s, ignoring", path.Join(m.UnitsDir, name))
			continue
		}
		units = append(units, name)
	}
	return
}

func (m *systemdUnitManager) GetUnitStates(filter pkg.Set) (map[string]*unit.UnitState, error) {
	// Unfortunately we need to lock for the entire operation to ensure we
	// have a consistent view of the hashes. Otherwise, Load/Unload
	// operations could mutate the hashes before we've retrieved the state
	// for every unit in the filter, since they won't necessarily all be
	// present in the initial ListUnits() call.
	m.mutex.Lock()
	defer m.mutex.Unlock()
	dbusStatuses, err := m.systemd.ListUnits()

	if err != nil {
		return nil, err
	}

	states := make(map[string]*unit.UnitState)
	for _, dus := range dbusStatuses {
		if !filter.Contains(dus.Name) {
			continue
		}

		us := &unit.UnitState{
			LoadState:   dus.LoadState,
			ActiveState: dus.ActiveState,
			SubState:    dus.SubState,
		}
		if h, ok := m.hashes[dus.Name]; ok {
			us.UnitHash = h.String()
		}
		states[dus.Name] = us
	}

	// grab data on subscribed units that didn't show up in ListUnits, most
	// likely due to being inactive
	for _, name := range filter.Values() {
		if _, ok := states[name]; ok {
			continue
		}

		us, err := m.getUnitState(name)
		if err != nil {
			return nil, err
		}
		if h, ok := m.hashes[name]; ok {
			us.UnitHash = h.String()
		}
		states[name] = us
	}

	return states, nil
}

func (m *systemdUnitManager) writeUnit(name string, contents string) error {
	bContents := []byte(contents)
	log.Infof("Writing systemd unit %s (%db)", name, len(bContents))

	ufPath := m.getUnitFilePath(name)
	err := ioutil.WriteFile(ufPath, bContents, os.FileMode(0644))
	if err != nil {
		return err
	}

	_, err = m.systemd.LinkUnitFiles([]string{ufPath}, true, true)
	return err
}

func (m *systemdUnitManager) removeUnit(name string) {
	log.Infof("Removing systemd unit %s", name)

	m.systemd.DisableUnitFiles([]string{name}, true)
	m.systemd.ResetFailedUnit(name)

	ufPath := m.getUnitFilePath(name)
	os.Remove(ufPath)
}

func (m *systemdUnitManager) getUnitFilePath(name string) string {
	return path.Join(m.UnitsDir, name)
}
<|endoftext|>


<commit_before>package systray

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"syscall"
	"unsafe"
)

var (
	iconFiles = make([]*os.File, 0)
	dllDir    = path.Join(os.Getenv("APPDATA"), "systray")
	dllFile   = path.Join(dllDir, "systray.dll")

	mod                      = syscall.NewLazyDLL(dllFile)
	_nativeLoop              = mod.NewProc("nativeLoop")
	_quit                    = mod.NewProc("quit")
	_setIcon                 = mod.NewProc("setIcon")
	_setTitle                = mod.NewProc("setTitle")
	_setTooltip              = mod.NewProc("setTooltip")
	_add_or_update_menu_item = mod.NewProc("add_or_update_menu_item")
)

func init() {
	// Write DLL to file
	b, err := Asset("systray.dll")
	if err != nil {
		panic(fmt.Errorf("Unable to read systray.dll: %v", err))
	}

	err = os.MkdirAll(dllDir, 0755)
	if err != nil {
		panic(fmt.Errorf("Unable to create directory %v to hold systray.dll: %v", dllDir, err))
	}

	err = ioutil.WriteFile(dllFile, b, 0644)
	if err != nil {
		panic(fmt.Errorf("Unable to save systray.dll to %v: %v", dllFile, err))
	}
}

func nativeLoop() {
	_nativeLoop.Call(
		syscall.NewCallback(systray_ready),
		syscall.NewCallback(systray_menu_item_selected))
}

func quit() {
	_quit.Call()
	for _, f := range iconFiles {
		err := os.Remove(f.Name())
		if err != nil {
			log.Debugf("Unable to delete temporary icon file %v: %v", f.Name(), err)
		}
	}
}

// SetIcon sets the systray icon.
// iconBytes should be the content of .ico for windows and .ico/.jpg/.png
// for other platforms.
func SetIcon(iconBytes []byte) {
	f, err := ioutil.TempFile("", "systray_temp_icon")
	if err != nil {
		log.Errorf("Unable to create temp icon: %v", err)
		return
	}
	defer f.Close()
	_, err = f.Write(iconBytes)
	if err != nil {
		log.Errorf("Unable to write icon to temp file %v: %v", f.Name(), f)
		return
	}
	f.Close()
	name, err := strPtr(f.Name())
	if err != nil {
		log.Errorf("Unable to convert name to string pointer: %v", err)
		return
	}
	_setIcon.Call(name)
}

// SetTitle sets the systray title, only available on Mac.
func SetTitle(title string) {
	// do nothing
}

// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon,
// only available on Mac and Windows.
func SetTooltip(tooltip string) {
	t, err := strPtr(tooltip)
	if err != nil {
		log.Errorf("Unable to convert tooltip to string pointer: %v", err)
		return
	}
	_setTooltip.Call(t)
}

func addOrUpdateMenuItem(item *MenuItem) {
	var disabled = 0
	if item.disabled {
		disabled = 1
	}
	var checked = 0
	if item.checked {
		checked = 1
	}
	title, err := strPtr(item.title)
	if err != nil {
		log.Errorf("Unable to convert title to string pointer: %v", err)
		return
	}
	tooltip, err := strPtr(item.tooltip)
	if err != nil {
		log.Errorf("Unable to convert tooltip to string pointer: %v", err)
		return
	}
	_add_or_update_menu_item.Call(
		uintptr(item.id),
		title,
		tooltip,
		uintptr(disabled),
		uintptr(checked),
	)
}

func strPtr(s string) (uintptr, error) {
	bp, err := syscall.BytePtrFromString(s)
	if err != nil {
		return 0, err
	}
	return uintptr(unsafe.Pointer(bp)), nil
}

func systray_ready() uintptr {
	systrayReady()
	return 0
}

func systray_menu_item_selected(id uintptr) uintptr {
	systrayMenuItemSelected(int32(id))
	return 0
}
<commit_msg>Added comment about closing file before loading it<commit_after>package systray

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"syscall"
	"unsafe"
)

var (
	iconFiles = make([]*os.File, 0)
	dllDir    = path.Join(os.Getenv("APPDATA"), "systray")
	dllFile   = path.Join(dllDir, "systray.dll")

	mod                      = syscall.NewLazyDLL(dllFile)
	_nativeLoop              = mod.NewProc("nativeLoop")
	_quit                    = mod.NewProc("quit")
	_setIcon                 = mod.NewProc("setIcon")
	_setTitle                = mod.NewProc("setTitle")
	_setTooltip              = mod.NewProc("setTooltip")
	_add_or_update_menu_item = mod.NewProc("add_or_update_menu_item")
)

func init() {
	// Write DLL to file
	b, err := Asset("systray.dll")
	if err != nil {
		panic(fmt.Errorf("Unable to read systray.dll: %v", err))
	}

	err = os.MkdirAll(dllDir, 0755)
	if err != nil {
		panic(fmt.Errorf("Unable to create directory %v to hold systray.dll: %v", dllDir, err))
	}

	err = ioutil.WriteFile(dllFile, b, 0644)
	if err != nil {
		panic(fmt.Errorf("Unable to save systray.dll to %v: %v", dllFile, err))
	}
}

func nativeLoop() {
	_nativeLoop.Call(
		syscall.NewCallback(systray_ready),
		syscall.NewCallback(systray_menu_item_selected))
}

func quit() {
	_quit.Call()
	for _, f := range iconFiles {
		err := os.Remove(f.Name())
		if err != nil {
			log.Debugf("Unable to delete temporary icon file %v: %v", f.Name(), err)
		}
	}
}

// SetIcon sets the systray icon.
// iconBytes should be the content of .ico for windows and .ico/.jpg/.png
// for other platforms.
func SetIcon(iconBytes []byte) {
	f, err := ioutil.TempFile("", "systray_temp_icon")
	if err != nil {
		log.Errorf("Unable to create temp icon: %v", err)
		return
	}
	defer f.Close()
	_, err = f.Write(iconBytes)
	if err != nil {
		log.Errorf("Unable to write icon to temp file %v: %v", f.Name(), f)
		return
	}
	// Need to close file before we load it to make sure contents is flushed.
	f.Close()
	name, err := strPtr(f.Name())
	if err != nil {
		log.Errorf("Unable to convert name to string pointer: %v", err)
		return
	}
	_setIcon.Call(name)
}

// SetTitle sets the systray title, only available on Mac.
func SetTitle(title string) {
	// do nothing
}

// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon,
// only available on Mac and Windows.
func SetTooltip(tooltip string) {
	t, err := strPtr(tooltip)
	if err != nil {
		log.Errorf("Unable to convert tooltip to string pointer: %v", err)
		return
	}
	_setTooltip.Call(t)
}

func addOrUpdateMenuItem(item *MenuItem) {
	var disabled = 0
	if item.disabled {
		disabled = 1
	}
	var checked = 0
	if item.checked {
		checked = 1
	}
	title, err := strPtr(item.title)
	if err != nil {
		log.Errorf("Unable to convert title to string pointer: %v", err)
		return
	}
	tooltip, err := strPtr(item.tooltip)
	if err != nil {
		log.Errorf("Unable to convert tooltip to string pointer: %v", err)
		return
	}
	_add_or_update_menu_item.Call(
		uintptr(item.id),
		title,
		tooltip,
		uintptr(disabled),
		uintptr(checked),
	)
}

func strPtr(s string) (uintptr, error) {
	bp, err := syscall.BytePtrFromString(s)
	if err != nil {
		return 0, err
	}
	return uintptr(unsafe.Pointer(bp)), nil
}

func systray_ready() uintptr {
	systrayReady()
	return 0
}

func systray_menu_item_selected(id uintptr) uintptr {
	systrayMenuItemSelected(int32(id))
	return 0
}
<|endoftext|>


<commit_before>package app

import (
  "github.com/urfave/cli"
  "net/http"
  "net/url"
  "errors"
  "time"
  "math"
  "net"
  "fmt"
  "os"
)

func ProbeCommand() cli.Command {

  return cli.Command{
    Name:  "probe",
    Usage: "Probe a TCP/HTTP(S) endpoint to determine if it is healthy",
    ArgsUsage: "<endpoint>",
    Action: probe,
    Flags: []cli.Flag{
      cli.DurationFlag{
        Name: "timeout, t",
        Usage: "Connection timeout in seconds",
        Value: 5 * time.Second,
      },
      cli.BoolFlag{
        Name:  "loop",
        Usage: "Continuously probe endpoint until it is healthy",
      },
      cli.Float64Flag{
        Name:  "backoff, b",
        Usage: "(Loop) Rate at which to back off from retries, must be >= 1",
        Value: 1.0,
      },
      cli.DurationFlag{
        Name:  "min, m",
        Usage: "(Loop) Minimum time to wait before retrying",
        Value: 1 * time.Second,
      },
      cli.DurationFlag{
        Name:  "max, x",
        Usage: "(Loop) Maximum time to wait before retrying",
        Value: 120 * time.Second,
      },
    },
  }
}

func probe(c *cli.Context) error {
  if c.Args().First() == "" {
    cli.ShowCommandHelp(c, "probe")
    os.Exit(1)
  }

  if c.Bool("loop") {
    min := c.Duration("min")
    max := c.Duration("max")
    backoff := c.Float64("backoff")
    loops := 0
    delay := min

    for err := healthCheck(c); err != nil; err = healthCheck(c) {
      fmt.Println(err)
      time.Sleep(delay)
      loops += 1

      if delay < max {
        delay = time.Duration(float64(min) * math.Pow(backoff, float64(loops)))
      }
      if delay > max {
        delay = max
      }
    }
    fmt.Println("OK")

  } else {
    if err := healthCheck(c); err != nil {
      fmt.Println(err)
      os.Exit(1)
    }
    fmt.Println("OK")
  }
  return nil
}

func healthCheck(c *cli.Context) error {
  endpoint := c.Args().First()
  timeout := c.Duration("timeout")

  url, err := url.Parse(endpoint)
  if err != nil {
    return err
  }

  switch url.Scheme {
  case "tcp":
    var conn net.Conn
    if conn, err = net.DialTimeout(url.Scheme, url.Host, timeout); err != nil {
      return err
    }
    conn.Close()
  case "http", "https":
    client := &http.Client{
      Timeout: timeout,
    }
    var resp *http.Response
    resp, err = client.Get(endpoint)

    switch {
    case err != nil:
      return err
    case resp.StatusCode >= 200 && resp.StatusCode <= 299:
      return nil
    default:
      return errors.New(fmt.Sprintf("HTTP %d\n", resp.StatusCode))
    }
  default:
    return errors.New(fmt.Sprintf("Unsupported URL scheme: %s\n", url.Scheme))
  }
  return nil
}
<commit_msg>break out of health probe loop after 'num' probes (#18)<commit_after>package app

import (
  "github.com/urfave/cli"
  "net/http"
  "net/url"
  "errors"
  "time"
  "math"
  "net"
  "fmt"
  "os"
)

func ProbeCommand() cli.Command {

  return cli.Command{
    Name:  "probe",
    Usage: "Probe a TCP/HTTP(S) endpoint to determine if it is healthy",
    ArgsUsage: "<endpoint>",
    Action: probe,
    Flags: []cli.Flag{
      cli.DurationFlag{
        Name: "timeout, t",
        Usage: "Connection timeout in seconds",
        Value: 5 * time.Second,
      },
      cli.BoolFlag{
        Name:  "loop",
        Usage: "Continuously probe endpoint until it is healthy",
      },
      cli.Float64Flag{
        Name:  "backoff, b",
        Usage: "(Loop) Rate at which to back off from retries, must be >= 1",
        Value: 1.0,
      },
      cli.DurationFlag{
        Name:  "min, m",
        Usage: "(Loop) Minimum time to wait before retrying",
        Value: 1 * time.Second,
      },
      cli.DurationFlag{
        Name:  "max, x",
        Usage: "(Loop) Maximum time to wait before retrying",
        Value: 120 * time.Second,
      },
      cli.IntFlag{
        Name:  "num, n",
        Usage: "(Loop) Maximum number of requests to perform before declaring unhealthy. 0 for infinite",
        Value: 0,
      },
    },
  }
}

func probe(c *cli.Context) error {
  if c.Args().First() == "" {
    cli.ShowCommandHelp(c, "probe")
    os.Exit(1)
  }

  if c.Bool("loop") {
    min := c.Duration("min")
    max := c.Duration("max")
    backoff := c.Float64("backoff")
    num := c.Int("num")
    loops := 0
    delay := min

    for err := healthCheck(c); err != nil; err = healthCheck(c) {
      fmt.Println(err)
      loops += 1
      if num != 0 && loops == num {
        os.Exit(1)
      }
      time.Sleep(delay)

      if delay < max {
        delay = time.Duration(float64(min) * math.Pow(backoff, float64(loops)))
      }
      if delay > max {
        delay = max
      }
    }
    fmt.Println("OK")

  } else {
    if err := healthCheck(c); err != nil {
      fmt.Println(err)
      os.Exit(1)
    }
    fmt.Println("OK")
  }
  return nil
}

func healthCheck(c *cli.Context) error {
  endpoint := c.Args().First()
  timeout := c.Duration("timeout")

  url, err := url.Parse(endpoint)
  if err != nil {
    return err
  }

  switch url.Scheme {
  case "tcp":
    var conn net.Conn
    if conn, err = net.DialTimeout(url.Scheme, url.Host, timeout); err != nil {
      return err
    }
    conn.Close()
  case "http", "https":
    client := &http.Client{
      Timeout: timeout,
    }
    var resp *http.Response
    resp, err = client.Get(endpoint)

    switch {
    case err != nil:
      return err
    case resp.StatusCode >= 200 && resp.StatusCode <= 299:
      return nil
    default:
      return errors.New(fmt.Sprintf("HTTP %d\n", resp.StatusCode))
    }
  default:
    return errors.New(fmt.Sprintf("Unsupported URL scheme: %s\n", url.Scheme))
  }
  return nil
}
<|endoftext|>


<commit_before>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type ATC struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewATC(actual interface{}, instance interface{}) (newInstance ATC) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			assertTrueResult := func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			}

			var nilValue interface{}
			var successfulAssertionTestCases = []ATC{
				NewATC(float64(1.1), nilValue),
				NewATC(int(1), nilValue),
				NewATC("1", nilValue),
				NewATC("a", nilValue),
				NewATC(float64(5), float64(1)),
				NewATC(int(5), float64(1)),
				NewATC("2.2", float64(1)),
				NewATC(int(5), int(1)),
				NewATC("5", int(1)),
			}

			for _, successCase := range successfulAssertionTestCases {
				actualValue := successCase.Actual
				instanceValue := successCase.Instance
				testName := fmt.Sprintf("ACTUAL > INSTANCE when Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
				if successCase.ActualStringNumber {
					testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER", testName)
				}
				if successCase.InstanceStringNumber {
					testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER", testName)
				}
				FIt(testName, func() {
					assertTrueResult(actualValue, instanceValue)
				})
			}

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<commit_msg>Succeeds when Actual is string and Instance is string<commit_after>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type ATC struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewATC(actual interface{}, instance interface{}) (newInstance ATC) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			assertTrueResult := func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			}

			var nilValue interface{}
			var successfulAssertionTestCases = []ATC{
				NewATC(float64(1.1), nilValue),
				NewATC(int(1), nilValue),
				NewATC("1", nilValue),
				NewATC("a", nilValue),
				NewATC(float64(5), float64(1)),
				NewATC(int(5), float64(1)),
				NewATC("2.2", float64(1)),
				NewATC(int(5), int(1)),
				NewATC("5", int(1)),
				NewATC("abc", "a"),
			}

			for _, successCase := range successfulAssertionTestCases {
				actualValue := successCase.Actual
				instanceValue := successCase.Instance
				testName := fmt.Sprintf("ACTUAL > INSTANCE when Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
				if successCase.ActualStringNumber {
					testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER", testName)
				}
				if successCase.InstanceStringNumber {
					testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER", testName)
				}
				FIt(testName, func() {
					assertTrueResult(actualValue, instanceValue)
				})
			}

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<|endoftext|>


<commit_before>
package main

import "bytes"

type Nal struct {

	streamType		uint32
	units			[]byte

}

func (n *Nal) read(bytes []byte) {

	//var H264_VIDEO uint32 = 0x1b

	if n.streamType == 0x1b {
		n.readVideo(bytes)
	} else {
	    n.readAudio(bytes)
	}

}

func (n *Nal) readVideo(byteArr []byte) {

	//Looking for this sequence in byteArr
	sep := []byte{0, 0, 0, 1}

	//item is a [][]byte and to append to units we need byte type
	for _, item := range bytes.Split(byteArr, sep) {

		if len(item) > 0 {

			//get each byte from item and append it to units
			for i := 0; i <= len(item) ; i++ {
				n.units = append(n.units, item[i])
			}//end if

		}//end if
	}//end for
}//end func

func (n *Nal) readAudio(bytes []byte) {

	n.units = append(n.units, bytes...)

}<commit_msg>updated some inline comments<commit_after>
package main

import "bytes"

type Nal struct {

	streamType		uint32
	units			[]byte

}

func (n *Nal) read(bytes []byte) {

	//var H264_VIDEO uint32 = 0x1b

	if n.streamType == 0x1b {
		n.readVideo(bytes)
	} else {
	    n.readAudio(bytes)
	}

}

func (n *Nal) readVideo(byteArr []byte) {

	//Looking for this sequence in byteArr
	sep := []byte{0, 0, 0, 1}

	//item is a [][]byte and to append to units we need byte type
	for _, item := range bytes.Split(byteArr, sep) {

		if len(item) > 0 {

			//get each byte from item and append it to units
			for i := 0; i <= len(item) ; i++ {
				n.units = append(n.units, item[i])
			}//end for

		}//end if
	}//end for
}//end func

func (n *Nal) readAudio(bytes []byte) {

	n.units = append(n.units, bytes...)

}<|endoftext|>


<commit_before>package scheduler

import (
	"fmt"

	"github.com/hashicorp/nomad/nomad/structs"
)

// Rank is used to provide a score and various ranking metadata
// along with a node when iterating. This state can be modified as
// various rank methods are applied.
type RankedNode struct {
	Node  *structs.Node
	Score float64

	// Allocs is used to cache the proposed allocations on the
	// node. This can be shared between iterators that require it.
	Proposed []*structs.Allocation
}

func (r *RankedNode) GoString() string {
	return fmt.Sprintf("<Node: %s Score: %0.3f>", r.Node.ID, r.Score)
}

// RankFeasibleIterator is used to iteratively yield nodes along
// with ranking metadata. The iterators may manage some state for
// performance optimizations.
type RankIterator interface {
	// Next yields a ranked option or nil if exhausted
	Next() *RankedNode

	// Reset is invoked when an allocation has been placed
	// to reset any stale state.
	Reset()
}

// FeasibleRankIterator is used to consume from a FeasibleIterator
// and return an unranked node with base ranking.
type FeasibleRankIterator struct {
	ctx    Context
	source FeasibleIterator
}

// NewFeasibleRankIterator is used to return a new FeasibleRankIterator
// from a FeasibleIterator source.
func NewFeasibleRankIterator(ctx Context, source FeasibleIterator) *FeasibleRankIterator {
	iter := &FeasibleRankIterator{
		ctx:    ctx,
		source: source,
	}
	return iter
}

func (iter *FeasibleRankIterator) Next() *RankedNode {
	option := iter.source.Next()
	if option == nil {
		return nil
	}
	ranked := &RankedNode{
		Node: option,
	}
	return ranked
}

func (iter *FeasibleRankIterator) Reset() {
	iter.source.Reset()
}

// StaticRankIterator is a RankIterator that returns a static set of results.
// This is largely only useful for testing.
type StaticRankIterator struct {
	ctx    Context
	nodes  []*RankedNode
	offset int
	seen   int
}

// NewStaticRankIterator returns a new static rank iterator over the given nodes
func NewStaticRankIterator(ctx Context, nodes []*RankedNode) *StaticRankIterator {
	iter := &StaticRankIterator{
		ctx:   ctx,
		nodes: nodes,
	}
	return iter
}

func (iter *StaticRankIterator) Next() *RankedNode {
	// Check if exhausted
	n := len(iter.nodes)
	if iter.offset == n || iter.seen == n {
		if iter.seen != n {
			iter.offset = 0
		} else {
			return nil
		}
	}

	// Return the next offset
	offset := iter.offset
	iter.offset += 1
	iter.seen += 1
	return iter.nodes[offset]
}

func (iter *StaticRankIterator) Reset() {
	iter.seen = 0
}

// BinPackIterator is a RankIterator that scores potential options
// based on a bin-packing algorithm.
type BinPackIterator struct {
	ctx       Context
	source    RankIterator
	resources *structs.Resources
	evict     bool
	priority  int
}

// NewBinPackIterator returns a BinPackIterator which tries to fit the given
// resources, potentially evicting other tasks based on a given priority.
func NewBinPackIterator(ctx Context, source RankIterator, resources *structs.Resources, evict bool, priority int) *BinPackIterator {
	iter := &BinPackIterator{
		ctx:       ctx,
		source:    source,
		resources: resources,
		evict:     evict,
		priority:  priority,
	}
	return iter
}

func (iter *BinPackIterator) SetResources(r *structs.Resources) {
	iter.resources = r
}

func (iter *BinPackIterator) SetPriority(p int) {
	iter.priority = p
}

func (iter *BinPackIterator) Next() *RankedNode {
	for {
		// Get the next potential option
		option := iter.source.Next()
		if option == nil {
			return nil
		}
		nodeID := option.Node.ID

		// Get the proposed allocations
		var proposed []*structs.Allocation
		if option.Proposed != nil {
			proposed = option.Proposed
		} else {
			p, err := iter.ctx.ProposedAllocs(nodeID)
			if err != nil {
				iter.ctx.Logger().Printf("[ERR] sched.binpack: failed to get proposed allocations for '%s': %v",
					nodeID, err)
				continue
			}
			proposed = p
			option.Proposed = p
		}

		// Add the resources we are trying to fit
		proposed = append(proposed, &structs.Allocation{Resources: iter.resources})

		// Check if these allocations fit, if they do not, simply skip this node
		fit, util, _ := structs.AllocsFit(option.Node, proposed)
		if !fit {
			iter.ctx.Metrics().ExhaustedNode(option.Node)
			continue
		}

		// XXX: For now we completely ignore evictions. We should use that flag
		// to determine if its possible to evict other lower priority allocations
		// to make room. This explodes the search space, so it must be done
		// carefully.

		// Score the fit normally otherwise
		fitness := structs.ScoreFit(option.Node, util)
		option.Score += fitness
		iter.ctx.Metrics().ScoreNode(option.Node, "binpack", fitness)
		return option
	}
}

func (iter *BinPackIterator) Reset() {
	iter.source.Reset()
}

// JobAntiAffinityIterator is used to apply an anti-affinity to allocating
// along side other allocations from this job. This is used to help distribute
// load across the cluster.
type JobAntiAffinityIterator struct {
	ctx     Context
	source  RankIterator
	penalty float64
	jobID   string
}

// NewJobAntiAffinityIterator is used to create a JobAntiAffinityIterator that
// applies the given penalty for co-placement with allocs from this job.
func NewJobAntiAffinityIterator(ctx Context, source RankIterator, penalty float64, jobID string) *JobAntiAffinityIterator {
	iter := &JobAntiAffinityIterator{
		ctx:     ctx,
		source:  source,
		penalty: penalty,
		jobID:   jobID,
	}
	return iter
}

func (iter *JobAntiAffinityIterator) SetJob(jobID string) {
	iter.jobID = jobID
}

func (iter *JobAntiAffinityIterator) Next() *RankedNode {
	for {
		option := iter.source.Next()
		if option == nil {
			return nil
		}
		nodeID := option.Node.ID

		// Get the proposed allocations
		var proposed []*structs.Allocation
		if option.Proposed != nil {
			proposed = option.Proposed
		} else {
			p, err := iter.ctx.ProposedAllocs(nodeID)
			if err != nil {
				iter.ctx.Logger().Printf("[ERR] sched.job-anti-affinity: failed to get proposed allocations for '%s': %v",
					nodeID, err)
				continue
			}
			proposed = p
			option.Proposed = p
		}

		// Determine the number of collisions
		collisions := 0
		for _, alloc := range proposed {
			if alloc.JobID == iter.jobID {
				collisions += 1
			}
		}

		// Apply a penalty if there are collisions
		if collisions > 0 {
			scorePenalty := float64(collisions) * iter.penalty
			option.Score -= scorePenalty
			iter.ctx.Metrics().ScoreNode(option.Node, "job-anti-affinity", scorePenalty)
		}
		return option
	}
}

func (iter *JobAntiAffinityIterator) Reset() {
	iter.source.Reset()
}
<commit_msg>scheduler: refactor shared logic<commit_after>package scheduler

import (
	"fmt"

	"github.com/hashicorp/nomad/nomad/structs"
)

// Rank is used to provide a score and various ranking metadata
// along with a node when iterating. This state can be modified as
// various rank methods are applied.
type RankedNode struct {
	Node  *structs.Node
	Score float64

	// Allocs is used to cache the proposed allocations on the
	// node. This can be shared between iterators that require it.
	Proposed []*structs.Allocation
}

func (r *RankedNode) GoString() string {
	return fmt.Sprintf("<Node: %s Score: %0.3f>", r.Node.ID, r.Score)
}

func (r *RankedNode) ProposedAllocs(ctx Context) ([]*structs.Allocation, error) {
	if r.Proposed != nil {
		return r.Proposed, nil
	}

	p, err := ctx.ProposedAllocs(r.Node.ID)
	if err != nil {
		return nil, err
	}
	r.Proposed = p
	return p, nil
}

// RankFeasibleIterator is used to iteratively yield nodes along
// with ranking metadata. The iterators may manage some state for
// performance optimizations.
type RankIterator interface {
	// Next yields a ranked option or nil if exhausted
	Next() *RankedNode

	// Reset is invoked when an allocation has been placed
	// to reset any stale state.
	Reset()
}

// FeasibleRankIterator is used to consume from a FeasibleIterator
// and return an unranked node with base ranking.
type FeasibleRankIterator struct {
	ctx    Context
	source FeasibleIterator
}

// NewFeasibleRankIterator is used to return a new FeasibleRankIterator
// from a FeasibleIterator source.
func NewFeasibleRankIterator(ctx Context, source FeasibleIterator) *FeasibleRankIterator {
	iter := &FeasibleRankIterator{
		ctx:    ctx,
		source: source,
	}
	return iter
}

func (iter *FeasibleRankIterator) Next() *RankedNode {
	option := iter.source.Next()
	if option == nil {
		return nil
	}
	ranked := &RankedNode{
		Node: option,
	}
	return ranked
}

func (iter *FeasibleRankIterator) Reset() {
	iter.source.Reset()
}

// StaticRankIterator is a RankIterator that returns a static set of results.
// This is largely only useful for testing.
type StaticRankIterator struct {
	ctx    Context
	nodes  []*RankedNode
	offset int
	seen   int
}

// NewStaticRankIterator returns a new static rank iterator over the given nodes
func NewStaticRankIterator(ctx Context, nodes []*RankedNode) *StaticRankIterator {
	iter := &StaticRankIterator{
		ctx:   ctx,
		nodes: nodes,
	}
	return iter
}

func (iter *StaticRankIterator) Next() *RankedNode {
	// Check if exhausted
	n := len(iter.nodes)
	if iter.offset == n || iter.seen == n {
		if iter.seen != n {
			iter.offset = 0
		} else {
			return nil
		}
	}

	// Return the next offset
	offset := iter.offset
	iter.offset += 1
	iter.seen += 1
	return iter.nodes[offset]
}

func (iter *StaticRankIterator) Reset() {
	iter.seen = 0
}

// BinPackIterator is a RankIterator that scores potential options
// based on a bin-packing algorithm.
type BinPackIterator struct {
	ctx       Context
	source    RankIterator
	resources *structs.Resources
	evict     bool
	priority  int
}

// NewBinPackIterator returns a BinPackIterator which tries to fit the given
// resources, potentially evicting other tasks based on a given priority.
func NewBinPackIterator(ctx Context, source RankIterator, resources *structs.Resources, evict bool, priority int) *BinPackIterator {
	iter := &BinPackIterator{
		ctx:       ctx,
		source:    source,
		resources: resources,
		evict:     evict,
		priority:  priority,
	}
	return iter
}

func (iter *BinPackIterator) SetResources(r *structs.Resources) {
	iter.resources = r
}

func (iter *BinPackIterator) SetPriority(p int) {
	iter.priority = p
}

func (iter *BinPackIterator) Next() *RankedNode {
	for {
		// Get the next potential option
		option := iter.source.Next()
		if option == nil {
			return nil
		}

		// Get the proposed allocations
		proposed, err := option.ProposedAllocs(iter.ctx)
		if err != nil {
			iter.ctx.Logger().Printf(
				"[ERR] sched.binpack: failed to get proposed allocations: %v",
				err)
			continue
		}

		// Add the resources we are trying to fit
		proposed = append(proposed, &structs.Allocation{Resources: iter.resources})

		// Check if these allocations fit, if they do not, simply skip this node
		fit, util, _ := structs.AllocsFit(option.Node, proposed)
		if !fit {
			iter.ctx.Metrics().ExhaustedNode(option.Node)
			continue
		}

		// XXX: For now we completely ignore evictions. We should use that flag
		// to determine if its possible to evict other lower priority allocations
		// to make room. This explodes the search space, so it must be done
		// carefully.

		// Score the fit normally otherwise
		fitness := structs.ScoreFit(option.Node, util)
		option.Score += fitness
		iter.ctx.Metrics().ScoreNode(option.Node, "binpack", fitness)
		return option
	}
}

func (iter *BinPackIterator) Reset() {
	iter.source.Reset()
}

// JobAntiAffinityIterator is used to apply an anti-affinity to allocating
// along side other allocations from this job. This is used to help distribute
// load across the cluster.
type JobAntiAffinityIterator struct {
	ctx     Context
	source  RankIterator
	penalty float64
	jobID   string
}

// NewJobAntiAffinityIterator is used to create a JobAntiAffinityIterator that
// applies the given penalty for co-placement with allocs from this job.
func NewJobAntiAffinityIterator(ctx Context, source RankIterator, penalty float64, jobID string) *JobAntiAffinityIterator {
	iter := &JobAntiAffinityIterator{
		ctx:     ctx,
		source:  source,
		penalty: penalty,
		jobID:   jobID,
	}
	return iter
}

func (iter *JobAntiAffinityIterator) SetJob(jobID string) {
	iter.jobID = jobID
}

func (iter *JobAntiAffinityIterator) Next() *RankedNode {
	for {
		option := iter.source.Next()
		if option == nil {
			return nil
		}

		// Get the proposed allocations
		proposed, err := option.ProposedAllocs(iter.ctx)
		if err != nil {
			iter.ctx.Logger().Printf(
				"[ERR] sched.job-anti-aff: failed to get proposed allocations: %v",
				err)
			continue
		}

		// Determine the number of collisions
		collisions := 0
		for _, alloc := range proposed {
			if alloc.JobID == iter.jobID {
				collisions += 1
			}
		}

		// Apply a penalty if there are collisions
		if collisions > 0 {
			scorePenalty := float64(collisions) * iter.penalty
			option.Score -= scorePenalty
			iter.ctx.Metrics().ScoreNode(option.Node, "job-anti-affinity", scorePenalty)
		}
		return option
	}
}

func (iter *JobAntiAffinityIterator) Reset() {
	iter.source.Reset()
}
<|endoftext|>