<commit_before>// Copyright © 2017 Aaron Donovan <amdonov@gmail.com>
//
// 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 idp

import (
	"crypto/sha1"
	"encoding/base64"
	"errors"
	"net"
	"net/http"
	"time"

	"github.com/amdonov/lite-idp/model"
	"github.com/amdonov/lite-idp/saml"
	"github.com/google/uuid"
)

func (i *IDP) respond(authRequest *model.AuthnRequest, user *model.User,
	w http.ResponseWriter, r *http.Request) error {
	switch authRequest.ProtocolBinding {
	case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact":
		return i.sendArtifactResponse(authRequest, user, w, r)
	case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST":
		return i.sendPostResponse(authRequest, user, w, r)
	default:
		return errors.New("unsupported protocol binding")
	}
}

func (i *IDP) makeResponse(authRequest *model.AuthnRequest, user *model.User) *saml.Response {
	now := time.Now()
	fiveFromNow := now.Add(5 * time.Minute)
	s := &saml.Response{
		StatusResponseType: saml.StatusResponseType{
			Version:      "2.0",
			ID:           saml.NewID(),
			IssueInstant: now,
			Status: &saml.Status{
				StatusCode: saml.StatusCode{
					Value: "urn:oasis:names:tc:SAML:2.0:status:Success",
				},
			},
			InResponseTo: authRequest.ID,
			Issuer: &saml.Issuer{
				Value: i.entityID,
			},
		},
		Assertion: &saml.Assertion{
			ID:           saml.NewID(),
			IssueInstant: now,
			Issuer: &saml.Issuer{
				Value: i.entityID,
			},
			Version: "2.0",
			Subject: &saml.Subject{
				NameID: &saml.NameID{
					Format:          user.Format,
					NameQualifier:   i.entityID,
					SPNameQualifier: authRequest.Issuer,
					Value:           user.Name,
				},
				SubjectConfirmation: &saml.SubjectConfirmation{
					Method: "urn:oasis:names:tc:SAML:2.0:cm:bearer",
					SubjectConfirmationData: &saml.SubjectConfirmationData{
						Address:      net.ParseIP(user.IP),
						InResponseTo: authRequest.ID,
						Recipient:    authRequest.AssertionConsumerServiceURL,
						NotOnOrAfter: fiveFromNow,
					},
				},
			},
			AuthnStatement: &saml.AuthnStatement{
				AuthnInstant: now,
				SessionIndex: saml.NewID(),
				SubjectLocality: &saml.SubjectLocality{
					DNSName: i.serverName,
				},
				AuthnContext: &saml.AuthnContext{
					AuthnContextClassRef: user.Context,
				},
			},
			AttributeStatement: user.AttributeStatement(),
			Conditions: &saml.Conditions{
				NotOnOrAfter: fiveFromNow,
				NotBefore:    now,
				AudienceRestriction: &saml.AudienceRestriction{
					Audience: authRequest.Issuer,
				},
			},
		},
	}
	return s
}

func getArtifact(entityId string) string {
	// The artifact isn't just a random session id. It's a base64-encoded byte array
	// that's 44 bytes in length. The first two bytes must be 04 for SAML 2. The second
	// two bytes are the index of the artifact resolution endpoint in the IdP metadata. Something like 02
	// The next 20 bytes are the sha1 hash of the IdP's entity ID
	// The last 20 bytes are unique to the request
	artifact := make([]byte, 44)
	// Use SAML 2
	artifact[1] = byte(4)
	// Index 1
	artifact[3] = byte(1)
	// Hash of entity ID
	source := sha1.Sum([]byte(entityId))
	for i := 4; i < 24; i++ {
		artifact[i] = source[i-4]
	}
	// Message ID
	message := sha1.Sum([]byte(uuid.New().String()))
	for i := 24; i < 44; i++ {
		artifact[i] = message[i-24]
	}
	return base64.StdEncoding.EncodeToString(artifact)
}
<commit_msg>Added Issuer Format attribute<commit_after>// Copyright © 2017 Aaron Donovan <amdonov@gmail.com>
//
// 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 idp

import (
	"crypto/sha1"
	"encoding/base64"
	"errors"
	"net"
	"net/http"
	"time"

	"github.com/amdonov/lite-idp/model"
	"github.com/amdonov/lite-idp/saml"
	"github.com/google/uuid"
)

func (i *IDP) respond(authRequest *model.AuthnRequest, user *model.User,
	w http.ResponseWriter, r *http.Request) error {
	switch authRequest.ProtocolBinding {
	case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact":
		return i.sendArtifactResponse(authRequest, user, w, r)
	case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST":
		return i.sendPostResponse(authRequest, user, w, r)
	default:
		return errors.New("unsupported protocol binding")
	}
}

func (i *IDP) makeResponse(authRequest *model.AuthnRequest, user *model.User) *saml.Response {
	now := time.Now()
	fiveFromNow := now.Add(5 * time.Minute)
	s := &saml.Response{
		StatusResponseType: saml.StatusResponseType{
			Version:      "2.0",
			ID:           saml.NewID(),
			IssueInstant: now,
			Status: &saml.Status{
				StatusCode: saml.StatusCode{
					Value: "urn:oasis:names:tc:SAML:2.0:status:Success",
				},
			},
			InResponseTo: authRequest.ID,
			Issuer:       saml.NewIssuer(i.entityID),
		},
		Assertion: &saml.Assertion{
			ID:           saml.NewID(),
			IssueInstant: now,
			Issuer:       saml.NewIssuer(i.entityID),
			Version:      "2.0",
			Subject: &saml.Subject{
				NameID: &saml.NameID{
					Format:          user.Format,
					NameQualifier:   i.entityID,
					SPNameQualifier: authRequest.Issuer,
					Value:           user.Name,
				},
				SubjectConfirmation: &saml.SubjectConfirmation{
					Method: "urn:oasis:names:tc:SAML:2.0:cm:bearer",
					SubjectConfirmationData: &saml.SubjectConfirmationData{
						Address:      net.ParseIP(user.IP),
						InResponseTo: authRequest.ID,
						Recipient:    authRequest.AssertionConsumerServiceURL,
						NotOnOrAfter: fiveFromNow,
					},
				},
			},
			AuthnStatement: &saml.AuthnStatement{
				AuthnInstant: now,
				SessionIndex: saml.NewID(),
				SubjectLocality: &saml.SubjectLocality{
					DNSName: i.serverName,
				},
				AuthnContext: &saml.AuthnContext{
					AuthnContextClassRef: user.Context,
				},
			},
			AttributeStatement: user.AttributeStatement(),
			Conditions: &saml.Conditions{
				NotOnOrAfter: fiveFromNow,
				NotBefore:    now,
				AudienceRestriction: &saml.AudienceRestriction{
					Audience: authRequest.Issuer,
				},
			},
		},
	}
	return s
}

func getArtifact(entityId string) string {
	// The artifact isn't just a random session id. It's a base64-encoded byte array
	// that's 44 bytes in length. The first two bytes must be 04 for SAML 2. The second
	// two bytes are the index of the artifact resolution endpoint in the IdP metadata. Something like 02
	// The next 20 bytes are the sha1 hash of the IdP's entity ID
	// The last 20 bytes are unique to the request
	artifact := make([]byte, 44)
	// Use SAML 2
	artifact[1] = byte(4)
	// Index 1
	artifact[3] = byte(1)
	// Hash of entity ID
	source := sha1.Sum([]byte(entityId))
	for i := 4; i < 24; i++ {
		artifact[i] = source[i-4]
	}
	// Message ID
	message := sha1.Sum([]byte(uuid.New().String()))
	for i := 24; i < 44; i++ {
		artifact[i] = message[i-24]
	}
	return base64.StdEncoding.EncodeToString(artifact)
}
<|endoftext|>


<commit_before>package gorill

import "testing"

func TestNewline(t *testing.T) {
	t.Run("empty", func(t *testing.T) {
		if got, want := newline(""), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("single character", func(t *testing.T) {
		if got, want := newline("a"), "a\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("single newline", func(t *testing.T) {
		if got, want := newline("\n"), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("multiple newline", func(t *testing.T) {
		if got, want := newline("\n\n"), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("string plus single newline", func(t *testing.T) {
		if got, want := newline("abc\n"), "abc\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("string plus multiple newlines", func(t *testing.T) {
		if got, want := newline("abc\n\n"), "abc\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
}
<commit_msg>embedded newlines not affected<commit_after>package gorill

import "testing"

func TestNewline(t *testing.T) {
	t.Run("empty", func(t *testing.T) {
		if got, want := newline(""), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("single character", func(t *testing.T) {
		if got, want := newline("a"), "a\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("single newline", func(t *testing.T) {
		if got, want := newline("\n"), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("multiple newline", func(t *testing.T) {
		if got, want := newline("\n\n"), "\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("string plus single newline", func(t *testing.T) {
		if got, want := newline("abc\n"), "abc\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("string plus multiple newlines", func(t *testing.T) {
		if got, want := newline("abc\n\n"), "abc\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
	t.Run("string with multiple embedded newlines", func(t *testing.T) {
		if got, want := newline("abc\n\ndef\n\n"), "abc\n\ndef\n"; got != want {
			t.Errorf("GOT: %q; WANT: %q", got, want)
		}
	})
}
<|endoftext|>


<commit_before>// Package encoding converts arbitrary objects into byte slices, and vis
// versa. It also contains helper functions for reading and writing length-
// prefixed data. See doc/Encoding.md for the full encoding specification.
package encoding

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
)

const (
	maxDecodeLen = 12e6 // 12 MB
	maxSliceLen  = 5e6  // 5 MB
)

var (
	errBadPointer = errors.New("cannot decode into invalid pointer")
)

type (
	// GenericMarshaler marshals objects into byte slices and unmarshals byte
	// slices into objects.
	GenericMarshaler interface {
		Marshal(interface{}) []byte
		Unmarshal([]byte, interface{}) error
	}

	// A SiaMarshaler can encode and write itself to a stream.
	SiaMarshaler interface {
		MarshalSia(io.Writer) error
	}

	// A SiaUnmarshaler can read and decode itself from a stream.
	SiaUnmarshaler interface {
		UnmarshalSia(io.Reader) error
	}

	// StdGenericMarshaler is an implementation of GenericMarshaler that uses
	// the encoding.Marshal and encoding.Unmarshal functions to perform
	// its marshaling/unmarshaling.
	StdGenericMarshaler struct{}

	// An Encoder writes objects to an output stream.
	Encoder struct {
		w io.Writer
	}
)

// Encode writes the encoding of v to the stream. For encoding details, see
// the package docstring.
func (e *Encoder) Encode(v interface{}) error {
	return e.encode(reflect.ValueOf(v))
}

// EncodeAll encodes a variable number of arguments.
func (e *Encoder) EncodeAll(vs ...interface{}) error {
	for _, v := range vs {
		if err := e.Encode(v); err != nil {
			return err
		}
	}
	return nil
}

// write catches instances where short writes do not return an error.
func (e *Encoder) write(p []byte) error {
	n, err := e.w.Write(p)
	if n != len(p) && err == nil {
		return io.ErrShortWrite
	}
	return err
}

// Encode writes the encoding of val to the stream. For encoding details, see
// the package docstring.
func (e *Encoder) encode(val reflect.Value) error {
	// check for MarshalSia interface first
	if m, ok := val.Interface().(SiaMarshaler); ok {
		return m.MarshalSia(e.w)
	}

	switch val.Kind() {
	case reflect.Ptr:
		// write either a 1 or 0
		if err := e.Encode(!val.IsNil()); err != nil {
			return err
		}
		if !val.IsNil() {
			return e.encode(val.Elem())
		}
	case reflect.Bool:
		if val.Bool() {
			return e.write([]byte{1})
		} else {
			return e.write([]byte{0})
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return e.write(EncInt64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return e.write(EncUint64(val.Uint()))
	case reflect.String:
		return WritePrefix(e.w, []byte(val.String()))
	case reflect.Slice:
		// slices are variable length, so prepend the length and then fallthrough to array logic
		if err := e.write(EncUint64(uint64(val.Len()))); err != nil {
			return err
		}
		if val.Len() == 0 {
			return nil
		}
		fallthrough
	case reflect.Array:
		// special case for byte arrays
		if val.Type().Elem().Kind() == reflect.Uint8 {
			// if the array is addressable, we can optimize a bit here
			if val.CanAddr() {
				return e.write(val.Slice(0, val.Len()).Bytes())
			}
			// otherwise we have to copy into a newly allocated slice
			slice := reflect.MakeSlice(reflect.SliceOf(val.Type().Elem()), val.Len(), val.Len())
			reflect.Copy(slice, val)
			return e.write(slice.Bytes())
		}
		// normal slices/arrays are encoded by sequentially encoding their elements
		for i := 0; i < val.Len(); i++ {
			if err := e.encode(val.Index(i)); err != nil {
				return err
			}
		}
		return nil
	case reflect.Struct:
		for i := 0; i < val.NumField(); i++ {
			if err := e.encode(val.Field(i)); err != nil {
				return err
			}
		}
		return nil
	}

	// Marshalling should never fail. If it panics, you're doing something wrong,
	// like trying to encode a map or an unexported struct field.
	panic("could not marshal type " + val.Type().String())
}

// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
	return &Encoder{w}
}

// Marshal returns the encoding of v. For encoding details, see the package
// docstring.
func Marshal(v interface{}) []byte {
	b := new(bytes.Buffer)
	NewEncoder(b).Encode(v) // no error possible when using a bytes.Buffer
	return b.Bytes()
}

// MarshalAll encodes all of its inputs and returns their concatenation.
func MarshalAll(vs ...interface{}) []byte {
	b := new(bytes.Buffer)
	enc := NewEncoder(b)
	// can't encode with EncodeAll (type information is lost)
	for _, v := range vs {
		enc.Encode(v)
	}
	return b.Bytes()
}

// WriteFile writes v to a file. The file will be created if it does not exist.
func WriteFile(filename string, v interface{}) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = NewEncoder(file).Encode(v)
	if err != nil {
		return errors.New("error while writing " + filename + ": " + err.Error())
	}
	return nil
}

// A Decoder reads and decodes values from an input stream.
type Decoder struct {
	r io.Reader
	n int
}

// Read implements the io.Reader interface. It also keeps track of the total
// number of bytes decoded, and panics if that number exceeds a global
// maximum.
func (d *Decoder) Read(p []byte) (int, error) {
	n, err := d.r.Read(p)
	// enforce an absolute maximum size limit
	if d.n += n; d.n > maxDecodeLen {
		panic("encoded type exceeds size limit")
	}
	return n, err
}

// Decode reads the next encoded value from its input stream and stores it in
// v, which must be a pointer. The decoding rules are the inverse of those
// specified in the package docstring.
func (d *Decoder) Decode(v interface{}) (err error) {
	// v must be a pointer
	pval := reflect.ValueOf(v)
	if pval.Kind() != reflect.Ptr || pval.IsNil() {
		return errBadPointer
	}

	// catch decoding panics and convert them to errors
	// note that this allows us to skip boundary checks during decoding
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("could not decode type %s: %v", pval.Elem().Type().String(), r)
		}
	}()

	// reset the read count
	d.n = 0

	d.decode(pval.Elem())
	return
}

// DecodeAll decodes a variable number of arguments.
func (d *Decoder) DecodeAll(vs ...interface{}) error {
	for _, v := range vs {
		if err := d.Decode(v); err != nil {
			return err
		}
	}
	return nil
}

// readN reads n bytes and panics if the read fails.
func (d *Decoder) readN(n int) []byte {
	b := make([]byte, n)
	_, err := io.ReadFull(d, b)
	if err != nil {
		panic(err)
	}
	return b
}

// readPrefix reads a length-prefixed byte slice and panics if the read fails.
func (d *Decoder) readPrefix() []byte {
	b, err := ReadPrefix(d, maxSliceLen)
	if err != nil {
		panic(err)
	}
	return b
}

// decode reads the next encoded value from its input stream and stores it in
// val. The decoding rules are the inverse of those specified in the package
// docstring.
func (d *Decoder) decode(val reflect.Value) {
	// check for UnmarshalSia interface first
	if val.CanAddr() {
		if u, ok := val.Addr().Interface().(SiaUnmarshaler); ok {
			err := u.UnmarshalSia(d)
			if err != nil {
				panic(err)
			}
			return
		}
	}

	switch val.Kind() {
	case reflect.Ptr:
		var valid bool
		d.decode(reflect.ValueOf(&valid).Elem())
		// nil pointer, nothing to decode
		if !valid {
			return
		}
		// make sure we aren't decoding into nil
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}
		d.decode(val.Elem())
	case reflect.Bool:
		b := d.readN(1)
		if b[0] > 1 {
			panic("boolean value was not 0 or 1")
		}
		val.SetBool(b[0] == 1)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val.SetInt(DecInt64(d.readN(8)))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val.SetUint(DecUint64(d.readN(8)))
	case reflect.String:
		val.SetString(string(d.readPrefix()))
	case reflect.Slice:
		// slices are variable length, but otherwise the same as arrays.
		// just have to allocate them first, then we can fallthrough to the array logic.
		sliceLen := DecUint64(d.readN(8))
		// sanity-check the sliceLen, otherwise you can crash a peer by making
		// them allocate a massive slice
		if sliceLen > 1<<31-1 || sliceLen*uint64(val.Type().Elem().Size()) > maxSliceLen {
			panic("slice is too large")
		} else if sliceLen == 0 {
			return
		}
		val.Set(reflect.MakeSlice(val.Type(), int(sliceLen), int(sliceLen)))
		fallthrough
	case reflect.Array:
		// special case for byte arrays (e.g. hashes)
		if val.Type().Elem().Kind() == reflect.Uint8 {
			// convert val to a slice and read into it directly
			b := val.Slice(0, val.Len())
			_, err := io.ReadFull(d, b.Bytes())
			if err != nil {
				panic(err)
			}
			return
		}
		// arrays are unmarshalled by sequentially unmarshalling their elements
		for i := 0; i < val.Len(); i++ {
			d.decode(val.Index(i))
		}
		return
	case reflect.Struct:
		for i := 0; i < val.NumField(); i++ {
			d.decode(val.Field(i))
		}
		return
	default:
		panic("unknown type")
	}
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r, 0}
}

// Unmarshal decodes the encoded value b and stores it in v, which must be a
// pointer. The decoding rules are the inverse of those specified in the
// package docstring for marshaling.
func Unmarshal(b []byte, v interface{}) error {
	r := bytes.NewReader(b)
	return NewDecoder(r).Decode(v)
}

// UnmarshalAll decodes the encoded values in b and stores them in vs, which
// must be pointers.
func UnmarshalAll(b []byte, vs ...interface{}) error {
	dec := NewDecoder(bytes.NewReader(b))
	// can't use DecodeAll (type information is lost)
	for _, v := range vs {
		if err := dec.Decode(v); err != nil {
			return err
		}
	}
	return nil
}

// ReadFile reads the contents of a file and decodes them into v.
func ReadFile(filename string, v interface{}) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = NewDecoder(file).Decode(v)
	if err != nil {
		return errors.New("error while reading " + filename + ": " + err.Error())
	}
	return nil
}

// Marshal returns the encoding of v. For encoding details, see the package
// docstring.
func (m StdGenericMarshaler) Marshal(v interface{}) []byte {
	return Marshal(v)
}

// Unmarshal decodes the encoded value b and stores it in v, which must be a
// pointer. The decoding rules are the inverse of those specified in the
// package docstring for marshaling.
func (m StdGenericMarshaler) Unmarshal(b []byte, v interface{}) error {
	return Unmarshal(b, v)
}
<commit_msg>fix Go 1.6 reflection behavior<commit_after>// Package encoding converts arbitrary objects into byte slices, and vis
// versa. It also contains helper functions for reading and writing length-
// prefixed data. See doc/Encoding.md for the full encoding specification.
package encoding

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"reflect"
)

const (
	maxDecodeLen = 12e6 // 12 MB
	maxSliceLen  = 5e6  // 5 MB
)

var (
	errBadPointer = errors.New("cannot decode into invalid pointer")
)

type (
	// GenericMarshaler marshals objects into byte slices and unmarshals byte
	// slices into objects.
	GenericMarshaler interface {
		Marshal(interface{}) []byte
		Unmarshal([]byte, interface{}) error
	}

	// A SiaMarshaler can encode and write itself to a stream.
	SiaMarshaler interface {
		MarshalSia(io.Writer) error
	}

	// A SiaUnmarshaler can read and decode itself from a stream.
	SiaUnmarshaler interface {
		UnmarshalSia(io.Reader) error
	}

	// StdGenericMarshaler is an implementation of GenericMarshaler that uses
	// the encoding.Marshal and encoding.Unmarshal functions to perform
	// its marshaling/unmarshaling.
	StdGenericMarshaler struct{}

	// An Encoder writes objects to an output stream.
	Encoder struct {
		w io.Writer
	}
)

// Encode writes the encoding of v to the stream. For encoding details, see
// the package docstring.
func (e *Encoder) Encode(v interface{}) error {
	return e.encode(reflect.ValueOf(v))
}

// EncodeAll encodes a variable number of arguments.
func (e *Encoder) EncodeAll(vs ...interface{}) error {
	for _, v := range vs {
		if err := e.Encode(v); err != nil {
			return err
		}
	}
	return nil
}

// write catches instances where short writes do not return an error.
func (e *Encoder) write(p []byte) error {
	n, err := e.w.Write(p)
	if n != len(p) && err == nil {
		return io.ErrShortWrite
	}
	return err
}

// Encode writes the encoding of val to the stream. For encoding details, see
// the package docstring.
func (e *Encoder) encode(val reflect.Value) error {
	// check for MarshalSia interface first
	if val.CanInterface() {
		if m, ok := val.Interface().(SiaMarshaler); ok {
			return m.MarshalSia(e.w)
		}
	}

	switch val.Kind() {
	case reflect.Ptr:
		// write either a 1 or 0
		if err := e.Encode(!val.IsNil()); err != nil {
			return err
		}
		if !val.IsNil() {
			return e.encode(val.Elem())
		}
	case reflect.Bool:
		if val.Bool() {
			return e.write([]byte{1})
		} else {
			return e.write([]byte{0})
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return e.write(EncInt64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return e.write(EncUint64(val.Uint()))
	case reflect.String:
		return WritePrefix(e.w, []byte(val.String()))
	case reflect.Slice:
		// slices are variable length, so prepend the length and then fallthrough to array logic
		if err := e.write(EncUint64(uint64(val.Len()))); err != nil {
			return err
		}
		if val.Len() == 0 {
			return nil
		}
		fallthrough
	case reflect.Array:
		// special case for byte arrays
		if val.Type().Elem().Kind() == reflect.Uint8 {
			// if the array is addressable, we can optimize a bit here
			if val.CanAddr() {
				return e.write(val.Slice(0, val.Len()).Bytes())
			}
			// otherwise we have to copy into a newly allocated slice
			slice := reflect.MakeSlice(reflect.SliceOf(val.Type().Elem()), val.Len(), val.Len())
			reflect.Copy(slice, val)
			return e.write(slice.Bytes())
		}
		// normal slices/arrays are encoded by sequentially encoding their elements
		for i := 0; i < val.Len(); i++ {
			if err := e.encode(val.Index(i)); err != nil {
				return err
			}
		}
		return nil
	case reflect.Struct:
		for i := 0; i < val.NumField(); i++ {
			if err := e.encode(val.Field(i)); err != nil {
				return err
			}
		}
		return nil
	}

	// Marshalling should never fail. If it panics, you're doing something wrong,
	// like trying to encode a map or an unexported struct field.
	panic("could not marshal type " + val.Type().String())
}

// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
	return &Encoder{w}
}

// Marshal returns the encoding of v. For encoding details, see the package
// docstring.
func Marshal(v interface{}) []byte {
	b := new(bytes.Buffer)
	NewEncoder(b).Encode(v) // no error possible when using a bytes.Buffer
	return b.Bytes()
}

// MarshalAll encodes all of its inputs and returns their concatenation.
func MarshalAll(vs ...interface{}) []byte {
	b := new(bytes.Buffer)
	enc := NewEncoder(b)
	// can't encode with EncodeAll (type information is lost)
	for _, v := range vs {
		enc.Encode(v)
	}
	return b.Bytes()
}

// WriteFile writes v to a file. The file will be created if it does not exist.
func WriteFile(filename string, v interface{}) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = NewEncoder(file).Encode(v)
	if err != nil {
		return errors.New("error while writing " + filename + ": " + err.Error())
	}
	return nil
}

// A Decoder reads and decodes values from an input stream.
type Decoder struct {
	r io.Reader
	n int
}

// Read implements the io.Reader interface. It also keeps track of the total
// number of bytes decoded, and panics if that number exceeds a global
// maximum.
func (d *Decoder) Read(p []byte) (int, error) {
	n, err := d.r.Read(p)
	// enforce an absolute maximum size limit
	if d.n += n; d.n > maxDecodeLen {
		panic("encoded type exceeds size limit")
	}
	return n, err
}

// Decode reads the next encoded value from its input stream and stores it in
// v, which must be a pointer. The decoding rules are the inverse of those
// specified in the package docstring.
func (d *Decoder) Decode(v interface{}) (err error) {
	// v must be a pointer
	pval := reflect.ValueOf(v)
	if pval.Kind() != reflect.Ptr || pval.IsNil() {
		return errBadPointer
	}

	// catch decoding panics and convert them to errors
	// note that this allows us to skip boundary checks during decoding
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("could not decode type %s: %v", pval.Elem().Type().String(), r)
		}
	}()

	// reset the read count
	d.n = 0

	d.decode(pval.Elem())
	return
}

// DecodeAll decodes a variable number of arguments.
func (d *Decoder) DecodeAll(vs ...interface{}) error {
	for _, v := range vs {
		if err := d.Decode(v); err != nil {
			return err
		}
	}
	return nil
}

// readN reads n bytes and panics if the read fails.
func (d *Decoder) readN(n int) []byte {
	b := make([]byte, n)
	_, err := io.ReadFull(d, b)
	if err != nil {
		panic(err)
	}
	return b
}

// readPrefix reads a length-prefixed byte slice and panics if the read fails.
func (d *Decoder) readPrefix() []byte {
	b, err := ReadPrefix(d, maxSliceLen)
	if err != nil {
		panic(err)
	}
	return b
}

// decode reads the next encoded value from its input stream and stores it in
// val. The decoding rules are the inverse of those specified in the package
// docstring.
func (d *Decoder) decode(val reflect.Value) {
	// check for UnmarshalSia interface first
	if val.CanAddr() && val.Addr().CanInterface() {
		if u, ok := val.Addr().Interface().(SiaUnmarshaler); ok {
			err := u.UnmarshalSia(d)
			if err != nil {
				panic(err)
			}
			return
		}
	}

	switch val.Kind() {
	case reflect.Ptr:
		var valid bool
		d.decode(reflect.ValueOf(&valid).Elem())
		// nil pointer, nothing to decode
		if !valid {
			return
		}
		// make sure we aren't decoding into nil
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}
		d.decode(val.Elem())
	case reflect.Bool:
		b := d.readN(1)
		if b[0] > 1 {
			panic("boolean value was not 0 or 1")
		}
		val.SetBool(b[0] == 1)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val.SetInt(DecInt64(d.readN(8)))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		val.SetUint(DecUint64(d.readN(8)))
	case reflect.String:
		val.SetString(string(d.readPrefix()))
	case reflect.Slice:
		// slices are variable length, but otherwise the same as arrays.
		// just have to allocate them first, then we can fallthrough to the array logic.
		sliceLen := DecUint64(d.readN(8))
		// sanity-check the sliceLen, otherwise you can crash a peer by making
		// them allocate a massive slice
		if sliceLen > 1<<31-1 || sliceLen*uint64(val.Type().Elem().Size()) > maxSliceLen {
			panic("slice is too large")
		} else if sliceLen == 0 {
			return
		}
		val.Set(reflect.MakeSlice(val.Type(), int(sliceLen), int(sliceLen)))
		fallthrough
	case reflect.Array:
		// special case for byte arrays (e.g. hashes)
		if val.Type().Elem().Kind() == reflect.Uint8 {
			// convert val to a slice and read into it directly
			b := val.Slice(0, val.Len())
			_, err := io.ReadFull(d, b.Bytes())
			if err != nil {
				panic(err)
			}
			return
		}
		// arrays are unmarshalled by sequentially unmarshalling their elements
		for i := 0; i < val.Len(); i++ {
			d.decode(val.Index(i))
		}
		return
	case reflect.Struct:
		for i := 0; i < val.NumField(); i++ {
			d.decode(val.Field(i))
		}
		return
	default:
		panic("unknown type")
	}
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r, 0}
}

// Unmarshal decodes the encoded value b and stores it in v, which must be a
// pointer. The decoding rules are the inverse of those specified in the
// package docstring for marshaling.
func Unmarshal(b []byte, v interface{}) error {
	r := bytes.NewReader(b)
	return NewDecoder(r).Decode(v)
}

// UnmarshalAll decodes the encoded values in b and stores them in vs, which
// must be pointers.
func UnmarshalAll(b []byte, vs ...interface{}) error {
	dec := NewDecoder(bytes.NewReader(b))
	// can't use DecodeAll (type information is lost)
	for _, v := range vs {
		if err := dec.Decode(v); err != nil {
			return err
		}
	}
	return nil
}

// ReadFile reads the contents of a file and decodes them into v.
func ReadFile(filename string, v interface{}) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = NewDecoder(file).Decode(v)
	if err != nil {
		return errors.New("error while reading " + filename + ": " + err.Error())
	}
	return nil
}

// Marshal returns the encoding of v. For encoding details, see the package
// docstring.
func (m StdGenericMarshaler) Marshal(v interface{}) []byte {
	return Marshal(v)
}

// Unmarshal decodes the encoded value b and stores it in v, which must be a
// pointer. The decoding rules are the inverse of those specified in the
// package docstring for marshaling.
func (m StdGenericMarshaler) Unmarshal(b []byte, v interface{}) error {
	return Unmarshal(b, v)
}
<|endoftext|>


<commit_before>package image

import (
	"github.com/pkg/errors"

	"github.com/containers/image/types"
)

// memoryImage is a mostly-implementation of types.Image assembled from data
// created in memory, used primarily as a return value of types.Image.UpdatedImage
// as a way to carry various structured information in a type-safe and easy-to-use way.
// Note that this _only_ carries the immediate metadata; it is _not_ a stand-alone
// collection of all related information, e.g. there is no way to get layer blobs
// from a memoryImage.
type memoryImage struct {
	genericManifest
	serializedManifest []byte // A private cache for Manifest()
}

func memoryImageFromManifest(m genericManifest) types.Image {
	return &memoryImage{
		genericManifest:    m,
		serializedManifest: nil,
	}
}

// Reference returns the reference used to set up this source, _as specified by the user_
// (not as the image itself, or its underlying storage, claims).  This can be used e.g. to determine which public keys are trusted for this image.
func (i *memoryImage) Reference() types.ImageReference {
	// It would really be inappropriate to return the ImageReference of the image this was based on.
	return nil
}

// Close removes resources associated with an initialized UnparsedImage, if any.
func (i *memoryImage) Close() {
}

// Size returns the size of the image as stored, if known, or -1 if not.
func (i *memoryImage) Size() (int64, error) {
	s, err := i.serialize()
	if err != nil {
		return -1, err
	}
	return int64(len(s)), nil
}

// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
func (i *memoryImage) Manifest() ([]byte, string, error) {
	if i.serializedManifest == nil {
		m, err := i.genericManifest.serialize()
		if err != nil {
			return nil, "", err
		}
		i.serializedManifest = m
	}
	return i.serializedManifest, i.genericManifest.manifestMIMEType(), nil
}

// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need.
func (i *memoryImage) Signatures() ([][]byte, error) {
	// Modifying an image invalidates signatures; a caller asking the updated image for signatures
	// is probably confused.
	return nil, errors.New("Internal error: Image.Signatures() is not supported for images modified in memory")
}

// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration.
func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) {
	return inspectManifest(i.genericManifest)
}

// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
func (i *memoryImage) IsMultiImage() bool {
	return false
}
<commit_msg>Don't fake a bad answer from memoryImage.Size()<commit_after>package image

import (
	"github.com/pkg/errors"

	"github.com/containers/image/types"
)

// memoryImage is a mostly-implementation of types.Image assembled from data
// created in memory, used primarily as a return value of types.Image.UpdatedImage
// as a way to carry various structured information in a type-safe and easy-to-use way.
// Note that this _only_ carries the immediate metadata; it is _not_ a stand-alone
// collection of all related information, e.g. there is no way to get layer blobs
// from a memoryImage.
type memoryImage struct {
	genericManifest
	serializedManifest []byte // A private cache for Manifest()
}

func memoryImageFromManifest(m genericManifest) types.Image {
	return &memoryImage{
		genericManifest:    m,
		serializedManifest: nil,
	}
}

// Reference returns the reference used to set up this source, _as specified by the user_
// (not as the image itself, or its underlying storage, claims).  This can be used e.g. to determine which public keys are trusted for this image.
func (i *memoryImage) Reference() types.ImageReference {
	// It would really be inappropriate to return the ImageReference of the image this was based on.
	return nil
}

// Close removes resources associated with an initialized UnparsedImage, if any.
func (i *memoryImage) Close() {
}

// Size returns the size of the image as stored, if known, or -1 if not.
func (i *memoryImage) Size() (int64, error) {
	return -1, nil
}

// Manifest is like ImageSource.GetManifest, but the result is cached; it is OK to call this however often you need.
func (i *memoryImage) Manifest() ([]byte, string, error) {
	if i.serializedManifest == nil {
		m, err := i.genericManifest.serialize()
		if err != nil {
			return nil, "", err
		}
		i.serializedManifest = m
	}
	return i.serializedManifest, i.genericManifest.manifestMIMEType(), nil
}

// Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need.
func (i *memoryImage) Signatures() ([][]byte, error) {
	// Modifying an image invalidates signatures; a caller asking the updated image for signatures
	// is probably confused.
	return nil, errors.New("Internal error: Image.Signatures() is not supported for images modified in memory")
}

// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration.
func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) {
	return inspectManifest(i.genericManifest)
}

// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
func (i *memoryImage) IsMultiImage() bool {
	return false
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Nodetemple <hostmaster@nodetemple.com>

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

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

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

package main

import (
	"fmt"
	"strings"
	"os"
	"strconv"
	"text/tabwriter"

	"github.com/spf13/cobra"
	"github.com/nodetemple/nodetemple/common"
)

const (
	cliName        = "nodectl"
	cliDescription = "nodectl is a command-line interface for an orchestration of CoreOS and Kubernetes cluster"
)

var (
	tabOut        *tabwriter.Writer
	globalFlags   = struct {
		Debug       bool
		Help        bool
		Provider    string
	}{}

	cmdExitCode int

	cmdNodectl = &cobra.Command{
		Use:   fmt.Sprintf("%s [command]", cliName),
		Short: cliDescription,
	}
)

func init() {
	cmdNodectl.PersistentFlags().BoolVar(&globalFlags.Debug, "debug", envBool("debug", false), "Print out more debug information")
	cmdNodectl.PersistentFlags().StringVarP(&globalFlags.Provider, "provider", "p", envString("provider", common.DefaultProvider), "Provider to use when managing a cluster")

	tabOut = new(tabwriter.Writer)
	tabOut.Init(os.Stdout, 0, 8, 1, '\t', 0)

	cobra.EnablePrefixMatching = true
}

func main() {
	cmdNodectl.SetUsageFunc(usageFunc)
	cmdNodectl.SetUsageTemplate(`{{.UsageString}}`)

	cmdNodectl.SetHelpCommand(cmdHelp)
	cmdNodectl.SetHelpTemplate(`{{.UsageString}}`)

	cmdNodectl.Execute()
	os.Exit(cmdExitCode)
}

func stderr(format string, a ...interface{}) {
	out := fmt.Sprintf(format, a...)
	fmt.Fprintln(os.Stderr, strings.TrimSuffix(out, "\n"))
}

func stdout(format string, a ...interface{}) {
	out := fmt.Sprintf(format, a...)
	fmt.Fprintln(os.Stdout, strings.TrimSuffix(out, "\n"))
}

func runWrapper(cf func(cmd *cobra.Command, args []string) (exit int)) func(cmd *cobra.Command, args []string) {
	return func(cmd *cobra.Command, args []string) {
		cmdExitCode = cf(cmd, args)
	}
}

func envString(key, def string) string {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		return env
	}
	return def
}

func envBool(key string, def bool) bool {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		val, err := strconv.ParseBool(env)
		if err != nil {
			stderr("invalid value %q for %q (default: %t): %v", env, key, def, err)
			return def
		}
		return val
	}
	return def
}

func envInt(key string, def int) int {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		val, err := strconv.Atoi(env)
		if err != nil {
			stderr("invalid value %q for %q (default: %q): %v", env, key, def, err)
			return def
		}
		return val
	}
	return def
}
<commit_msg>Try to override help flag<commit_after>/*
Copyright 2015 Nodetemple <hostmaster@nodetemple.com>

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

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

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

package main

import (
	"fmt"
	"strings"
	"os"
	"strconv"
	"text/tabwriter"

	"github.com/spf13/cobra"
	"github.com/nodetemple/nodetemple/common"
)

const (
	cliName        = "nodectl"
	cliDescription = "nodectl is a command-line interface for an orchestration of CoreOS and Kubernetes cluster"
)

var (
	tabOut        *tabwriter.Writer
	globalFlags   = struct {
		Debug       bool
		Help        bool
		Provider    string
	}{}

	cmdExitCode int

	cmdNodectl = &cobra.Command{
		Use:   fmt.Sprintf("%s [command]", cliName),
		Short: cliDescription,
	}
)

func init() {
	cmdNodectl.PersistentFlags().BoolVarP(&cmdNodectl.helpFlagVal, "help", "h", false, "Help for "+cmdNodectl.Name())
	cmdNodectl.PersistentFlags().BoolVar(&globalFlags.Debug, "debug", envBool("debug", false), "Print out more debug information")
	cmdNodectl.PersistentFlags().StringVarP(&globalFlags.Provider, "provider", "p", envString("provider", common.DefaultProvider), "Provider to use when managing a cluster")

	tabOut = new(tabwriter.Writer)
	tabOut.Init(os.Stdout, 0, 8, 1, '\t', 0)

	cobra.EnablePrefixMatching = true
}

func main() {
	cmdNodectl.SetUsageFunc(usageFunc)
	cmdNodectl.SetUsageTemplate(`{{.UsageString}}`)

	cmdNodectl.SetHelpCommand(cmdHelp)
	cmdNodectl.SetHelpTemplate(`{{.UsageString}}`)

	cmdNodectl.Execute()
	os.Exit(cmdExitCode)
}

func stderr(format string, a ...interface{}) {
	out := fmt.Sprintf(format, a...)
	fmt.Fprintln(os.Stderr, strings.TrimSuffix(out, "\n"))
}

func stdout(format string, a ...interface{}) {
	out := fmt.Sprintf(format, a...)
	fmt.Fprintln(os.Stdout, strings.TrimSuffix(out, "\n"))
}

func runWrapper(cf func(cmd *cobra.Command, args []string) (exit int)) func(cmd *cobra.Command, args []string) {
	return func(cmd *cobra.Command, args []string) {
		cmdExitCode = cf(cmd, args)
	}
}

func envString(key, def string) string {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		return env
	}
	return def
}

func envBool(key string, def bool) bool {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		val, err := strconv.ParseBool(env)
		if err != nil {
			stderr("invalid value %q for %q (default: %t): %v", env, key, def, err)
			return def
		}
		return val
	}
	return def
}

func envInt(key string, def int) int {
	envKey := strings.ToUpper(cliName + "_" + strings.Replace(key, "-", "_", -1))

	if env := os.Getenv(envKey); env != "" {
		val, err := strconv.Atoi(env)
		if err != nil {
			stderr("invalid value %q for %q (default: %q): %v", env, key, def, err)
			return def
		}
		return val
	}
	return def
}
<|endoftext|>


<commit_before>package pitchfork

import (
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

/* Constants */
const PAGER_PERPAGE = 10

/* Templates */
var g_tmp *template.Template

var template_funcs = template.FuncMap{
	"pager_less_ok":   tmp_pager_less_ok,
	"pager_less":      tmp_pager_less,
	"pager_more_ok":   tmp_pager_more_ok,
	"pager_more":      tmp_pager_more,
	"user_home_link":  tmp_user_home_link,
	"user_image_link": tmp_user_image_link,
	"fmt_date":        tmp_fmt_date,
	"fmt_datemin":     tmp_fmt_datemin,
	"fmt_time":        tmp_fmt_time,
	"fmt_string":      tmp_fmt_string,
	"str_tolower":     tmp_str_tolower,
	"str_emboss":      tmp_str_emboss,
	"inc_file":        tmp_inc_file,
	"dumpvar":         tmp_dumpvar,
}

func Template_FuncAdd(name string, f interface{}) {
	template_funcs[name] = f
}

func Template_Get() *template.Template {
	return g_tmp
}

/* Template Functions - used from inside the templates */
func tmp_pager_less_ok(cur int) bool {
	return cur >= PAGER_PERPAGE
}

func tmp_pager_less(cur int) int {
	return cur - PAGER_PERPAGE
}

func tmp_pager_more_ok(cur int, max int) bool {
	return cur < (max - PAGER_PERPAGE)
}

func tmp_pager_more(cur int, max int) int {
	return cur + PAGER_PERPAGE
}

func tmp_user_home_link(ctx PfCtx, username string, fullname string) template.HTML {
	html := ""
	if Config.UserHomeLinks || ctx.IsSysAdmin() || username == ctx.TheUser().GetUserName() {
		html = "" + HE(fullname) + ""
	} else {
		html = HE(fullname)
	}

	return HEB(html)
}

func tmp_user_image_link(ctx PfCtx, username string, fullname string, extraclass string) template.HTML {
	link := false
	if Config.UserHomeLinks || ctx.IsSysAdmin() || username == ctx.TheUser().GetUserName() {
		link = true
	}

	html := ""

	if link {
		html += ""
		html += "<img src=\"/user/" + HE(username) + "/image.png\" "
	} else {
		html += ""

	if link {
		html += ""
	}

	return HEB(html)
}

func tmp_fmt_date(t time.Time) string {
	return t.Format(Config.DateFormat)
}

/* Minimum time display */
func tmp_fmt_datemin(a time.Time, b time.Time, skipstamp string) (s string) {
	if skipstamp == "now" {
		/* This causes the year to be skipped if it is the same */
		skipstamp = time.Now().Format("2006")
	}
	ssl := len(skipstamp)

	/* Show just the date */
	s = a.Format("2006-01-02")

	/* Shrink the date, skipping what is already a given? */
	if skipstamp != "" && ssl < len(s) && s[0:ssl] == skipstamp {
		/* 2006 ? */
		skip := 5

		/* 2006-01 ? */
		if ssl == 7 {
			skip = 8
		}

		s = s[skip:]
	}

	/* Same start & end, nothing more to show */
	if a == b {
		return
	}

	if b.Year() != a.Year() {
		/* Year change, show full end date */
		s += " - "
		s += b.Format("2006-01-02")
		return
	}

	if b.Month() != a.Month() {
		/* Month change, show Month + Day */
		s += " - "
		s += b.Format("01-02")
		return
	}

	/* Show only the day */
	s += "..."
	s += b.Format("02")

	return
}

func tmp_fmt_time(t time.Time) string {
	return Fmt_Time(t)
}

func tmp_fmt_string(obj interface{}) string {
	return ToString(obj)
}

func tmp_str_tolower(str string) string {
	return strings.ToLower(str)
}

func tmp_str_emboss(in string, em string) (o template.HTML) {
	inlen := len(in)
	inlow := strings.ToLower(in)

	emlen := len(em)
	emlow := strings.ToLower(em)

	for i := 0; i < inlen; {
		f := strings.Index(inlow[i:], emlow)
		if f == -1 {
			/* Remainder */
			o += HEB(HE(in[i:]))
			break
		}

		o += HEB(HE(in[i : i+f]))
		o += HEB("" + in[i+f:i+f+emlen] + "")
		i += f + emlen
	}
	return
}

func tmp_inc_file(fn string) template.HTML {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return HEB("Invalid File")
	}

	return HEB(string(b))
}

/*
 * Dump a variable from a template
 *
 * Useful for debugging so that one can check
 * the entire structure of a variable that is
 * passed in to a template
 */
func tmp_dumpvar(v interface{}) template.HTML {
	str := fmt.Sprintf("%#v", v)
	str = template.HTMLEscapeString(str)
	str = strings.Replace(str, "\n", "
", -1)
	return template.HTML("
" + str + "
")
}

func template_loader(root string, path string) error {
	/* Name is the 'short' name without the root of the template dir */
	if !strings.HasSuffix(path, ".tmpl") {
		return nil
	}

	/* We want just the name, not the whole path */
	name := path[len(root)+1:]

	/* Do we already have a version of this template? */
	if g_tmp.Lookup(name) != nil {
		Dbgf("Skipping overruled template %s", name)
		return nil
	}

	/* Load the file */
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	s := string(b)

	/* New Template */
	t := g_tmp.New(name)
	Dbgf("Loaded template %s", name)

	/* Add functions */
	t.Funcs(template_funcs)

	/* Parse the template */
	_, err = t.Parse(s)
	return err
}

func Template_Load() (err error) {
	g_tmp = template.New("Pitchfork Templates")

	/* Pre-load the templates from multiple roots */
	for _, root := range Config.File_roots {
		root = filepath.Join(root, "templates/")

		Dbgf("Probing root %s for templates", root)

		err = filepath.Walk(root, func(path string, fi os.FileInfo, _ error) error {
			/* fi can be nil when the dir is not found... */
			if fi == nil {
				return errors.New("Path " + path + " not found")
			} else if fi.IsDir() {
				return nil
			}

			return template_loader(root, path)
		})

		if err != nil {
			err = errors.New(err.Error() + " [root: " + root + "]")
			Dbgf("Template loading caused an error: %s", err.Error())
			break
		}

		Dbgf("Probing root %s for templates - done", root)
	}

	Dbg("Loading templates... done")

	return err
}

func HE(str string) string {
	return template.HTMLEscapeString(str)
}

func HEB(str string) template.HTML {
	return template.HTML(str)
}
<commit_msg>In case the user has no full name use the username<commit_after>package pitchfork

import (
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

/* Constants */
const PAGER_PERPAGE = 10

/* Templates */
var g_tmp *template.Template

var template_funcs = template.FuncMap{
	"pager_less_ok":   tmp_pager_less_ok,
	"pager_less":      tmp_pager_less,
	"pager_more_ok":   tmp_pager_more_ok,
	"pager_more":      tmp_pager_more,
	"user_home_link":  tmp_user_home_link,
	"user_image_link": tmp_user_image_link,
	"fmt_date":        tmp_fmt_date,
	"fmt_datemin":     tmp_fmt_datemin,
	"fmt_time":        tmp_fmt_time,
	"fmt_string":      tmp_fmt_string,
	"str_tolower":     tmp_str_tolower,
	"str_emboss":      tmp_str_emboss,
	"inc_file":        tmp_inc_file,
	"dumpvar":         tmp_dumpvar,
}

func Template_FuncAdd(name string, f interface{}) {
	template_funcs[name] = f
}

func Template_Get() *template.Template {
	return g_tmp
}

/* Template Functions - used from inside the templates */
func tmp_pager_less_ok(cur int) bool {
	return cur >= PAGER_PERPAGE
}

func tmp_pager_less(cur int) int {
	return cur - PAGER_PERPAGE
}

func tmp_pager_more_ok(cur int, max int) bool {
	return cur < (max - PAGER_PERPAGE)
}

func tmp_pager_more(cur int, max int) int {
	return cur + PAGER_PERPAGE
}

func tmp_user_home_link(ctx PfCtx, username string, fullname string) template.HTML {
	html := ""

	/* In case the user has no full name use the username */
	if fullname == "" {
		fullname = username
	}

	if Config.UserHomeLinks || ctx.IsSysAdmin() || username == ctx.TheUser().GetUserName() {
		html = "" + HE(fullname) + ""
	} else {
		html = HE(fullname)
	}

	return HEB(html)
}

func tmp_user_image_link(ctx PfCtx, username string, fullname string, extraclass string) template.HTML {
	link := false
	if Config.UserHomeLinks || ctx.IsSysAdmin() || username == ctx.TheUser().GetUserName() {
		link = true
	}

	html := ""

	if link {
		html += ""
		html += "<img src=\"/user/" + HE(username) + "/image.png\" "
	} else {
		html += ""

	if link {
		html += ""
	}

	return HEB(html)
}

func tmp_fmt_date(t time.Time) string {
	return t.Format(Config.DateFormat)
}

/* Minimum time display */
func tmp_fmt_datemin(a time.Time, b time.Time, skipstamp string) (s string) {
	if skipstamp == "now" {
		/* This causes the year to be skipped if it is the same */
		skipstamp = time.Now().Format("2006")
	}
	ssl := len(skipstamp)

	/* Show just the date */
	s = a.Format("2006-01-02")

	/* Shrink the date, skipping what is already a given? */
	if skipstamp != "" && ssl < len(s) && s[0:ssl] == skipstamp {
		/* 2006 ? */
		skip := 5

		/* 2006-01 ? */
		if ssl == 7 {
			skip = 8
		}

		s = s[skip:]
	}

	/* Same start & end, nothing more to show */
	if a == b {
		return
	}

	if b.Year() != a.Year() {
		/* Year change, show full end date */
		s += " - "
		s += b.Format("2006-01-02")
		return
	}

	if b.Month() != a.Month() {
		/* Month change, show Month + Day */
		s += " - "
		s += b.Format("01-02")
		return
	}

	/* Show only the day */
	s += "..."
	s += b.Format("02")

	return
}

func tmp_fmt_time(t time.Time) string {
	return Fmt_Time(t)
}

func tmp_fmt_string(obj interface{}) string {
	return ToString(obj)
}

func tmp_str_tolower(str string) string {
	return strings.ToLower(str)
}

func tmp_str_emboss(in string, em string) (o template.HTML) {
	inlen := len(in)
	inlow := strings.ToLower(in)

	emlen := len(em)
	emlow := strings.ToLower(em)

	for i := 0; i < inlen; {
		f := strings.Index(inlow[i:], emlow)
		if f == -1 {
			/* Remainder */
			o += HEB(HE(in[i:]))
			break
		}

		o += HEB(HE(in[i : i+f]))
		o += HEB("" + in[i+f:i+f+emlen] + "")
		i += f + emlen
	}
	return
}

func tmp_inc_file(fn string) template.HTML {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return HEB("Invalid File")
	}

	return HEB(string(b))
}

/*
 * Dump a variable from a template
 *
 * Useful for debugging so that one can check
 * the entire structure of a variable that is
 * passed in to a template
 */
func tmp_dumpvar(v interface{}) template.HTML {
	str := fmt.Sprintf("%#v", v)
	str = template.HTMLEscapeString(str)
	str = strings.Replace(str, "\n", "
", -1)
	return template.HTML("
" + str + "
")
}

func template_loader(root string, path string) error {
	/* Name is the 'short' name without the root of the template dir */
	if !strings.HasSuffix(path, ".tmpl") {
		return nil
	}

	/* We want just the name, not the whole path */
	name := path[len(root)+1:]

	/* Do we already have a version of this template? */
	if g_tmp.Lookup(name) != nil {
		Dbgf("Skipping overruled template %s", name)
		return nil
	}

	/* Load the file */
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	s := string(b)

	/* New Template */
	t := g_tmp.New(name)
	Dbgf("Loaded template %s", name)

	/* Add functions */
	t.Funcs(template_funcs)

	/* Parse the template */
	_, err = t.Parse(s)
	return err
}

func Template_Load() (err error) {
	g_tmp = template.New("Pitchfork Templates")

	/* Pre-load the templates from multiple roots */
	for _, root := range Config.File_roots {
		root = filepath.Join(root, "templates/")

		Dbgf("Probing root %s for templates", root)

		err = filepath.Walk(root, func(path string, fi os.FileInfo, _ error) error {
			/* fi can be nil when the dir is not found... */
			if fi == nil {
				return errors.New("Path " + path + " not found")
			} else if fi.IsDir() {
				return nil
			}

			return template_loader(root, path)
		})

		if err != nil {
			err = errors.New(err.Error() + " [root: " + root + "]")
			Dbgf("Template loading caused an error: %s", err.Error())
			break
		}

		Dbgf("Probing root %s for templates - done", root)
	}

	Dbg("Loading templates... done")

	return err
}

func HE(str string) string {
	return template.HTMLEscapeString(str)
}

func HEB(str string) template.HTML {
	return template.HTML(str)
}
<|endoftext|>


<commit_before>package amelia

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/subosito/twilio"
	"github.com/zachlatta/go-tomtom"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
)

type Notification struct {
	UserID           int64             `json:"userId"`
	StorylineUpdates []StorylineUpdate `json:"storylineUpdates"`
}

type StorylineUpdate struct {
	// TODO: Change to equivalent of enum
	Reason string `json:"reason"`
}

type Location struct {
	Lat float64 `json:"lat"`
	Lon float64 `json:"lon"`
}

type Place struct {
	Location Location `json:"location"`
}

type Segment struct {
	Place     Place       `json:"place"`
	StartTime RFC3339Time `json:"startTime"`
}

type DailySegments struct {
	Segments []Segment `json:"segments"`
}

func handleNotification(w http.ResponseWriter, r *http.Request) *appError {
	c := appengine.NewContext(r)

	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return &appError{err, "Error reading request body", http.StatusBadRequest}
	}

	var notification Notification
	err = json.Unmarshal(body, &notification)
	if err != nil {
		return &appError{err, "Error unmarshalling JSON", http.StatusBadRequest}
	}

	hasDataUpload := false
	for _, update := range notification.StorylineUpdates {
		if update.Reason == "DataUpload" {
			hasDataUpload = true
			break
		}
	}

	if hasDataUpload {
		// TODO: Ensure MovesUserId is unique in datastore
		q := datastore.NewQuery("User").Filter("AuthorizedWithMoves =", true).Filter("MovesUserId =", notification.UserID)

		var users []User
		keys, err := q.GetAll(c, &users)
		if err != nil {
			return &appError{err, "Could not get user from datastore",
				http.StatusInternalServerError}
		}

		if len(users) <= 0 {
			return &appError{err, "User not found", http.StatusNotFound}
		}

		user, key := users[0], keys[0]

		t := CreateTransport(c, user.MovesToken.NormToken())

		dailySegmentsList, err := GetLatestPlaces(t)
		if err != nil {
			return &appError{err, "Could not unmarshal request",
				http.StatusBadRequest}
		}

		return updateDailySegments(c, *dailySegmentsList, user, key)
	}

	return nil
}

func updateDailySegments(c appengine.Context,
	dailySegmentsList []DailySegments, user User,
	userKey *datastore.Key) *appError {
	f := urlfetch.Client(c)
	var phoneEntries []PhoneEntry
	_, err := datastore.NewQuery("PhoneEntry").Ancestor(userKey).GetAll(c, &phoneEntries)
	if err != nil {
		return &appError{err, "Error getting phones from datastore",
			http.StatusInternalServerError}
	}

	segmentsToProcess := make([]Segment, 0)

	// Find segments with StartTimes greater than the user's LastSegmentStartTime
	for _, dailySegments := range dailySegmentsList {
		for _, segment := range dailySegments.Segments {
			if user.LastSegmentStartTime.Time.Before(segment.StartTime.Time) {
				segmentsToProcess = append(segmentsToProcess, segment)
			}
		}
	}

	// If there aren't any, return
	if len(segmentsToProcess) <= 0 {
		return nil
	}

	for _, segment := range segmentsToProcess {
		client := tomtom.NewClient(tomtomKey, f)
		codes, err := client.Geocode.ReverseGeocode(segment.Place.Location.Lat, segment.Place.Location.Lon)
		if err != nil {
			return &appError{err, "Error reverse geocoding address",
				http.StatusInternalServerError}
		}

		// get address string and check if it changed
		var address string
		if len(codes) > 0 {
			address = codes[0].FormattedAddress
		} else {
			address = fmt.Sprintf("%f, %f", segment.Place.Location.Lat,
				segment.Place.Location.Lon)
		}

		// send texts
		for _, phone := range phoneEntries {
			appError := sendText(c, "I'm now at "+address+".", phone.Phone)
			if err != nil {
				return appError
			}
		}
	}

	lastSegment := segmentsToProcess[len(segmentsToProcess)-1]
	user.LastSegmentStartTime = lastSegment.StartTime

	_, err = datastore.Put(c, userKey, &user)
	if err != nil {
		return &appError{err, "Error saving user", http.StatusInternalServerError}
	}

	return nil
}

func sendText(a appengine.Context, message string, phone string) *appError {
	f := urlfetch.Client(a)
	c := twilio.NewClient(twilioSid, twilioAuthToken, f)

	var params twilio.MessageParams
	params.Body = message
	_, _, err := c.Messages.Send(twilioPhone, phone, params)
	if err != nil {
		return &appError{err, "Error sending text message",
			http.StatusInternalServerError}
	}

	return nil
}
<commit_msg>Use the place's name if available.<commit_after>package amelia

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/subosito/twilio"
	"github.com/zachlatta/go-tomtom"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
)

type Notification struct {
	UserID           int64             `json:"userId"`
	StorylineUpdates []StorylineUpdate `json:"storylineUpdates"`
}

type StorylineUpdate struct {
	// TODO: Change to equivalent of enum
	Reason string `json:"reason"`
}

type Location struct {
	Lat float64 `json:"lat"`
	Lon float64 `json:"lon"`
}

type Place struct {
	Location Location `json:"location"`
	Name     string   `json:"name"`
}

type Segment struct {
	Place     Place       `json:"place"`
	StartTime RFC3339Time `json:"startTime"`
}

type DailySegments struct {
	Segments []Segment `json:"segments"`
}

func handleNotification(w http.ResponseWriter, r *http.Request) *appError {
	c := appengine.NewContext(r)

	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return &appError{err, "Error reading request body", http.StatusBadRequest}
	}

	var notification Notification
	err = json.Unmarshal(body, &notification)
	if err != nil {
		return &appError{err, "Error unmarshalling JSON", http.StatusBadRequest}
	}

	hasDataUpload := false
	for _, update := range notification.StorylineUpdates {
		if update.Reason == "DataUpload" {
			hasDataUpload = true
			break
		}
	}

	if hasDataUpload {
		// TODO: Ensure MovesUserId is unique in datastore
		q := datastore.NewQuery("User").Filter("AuthorizedWithMoves =", true).Filter("MovesUserId =", notification.UserID)

		var users []User
		keys, err := q.GetAll(c, &users)
		if err != nil {
			return &appError{err, "Could not get user from datastore",
				http.StatusInternalServerError}
		}

		if len(users) <= 0 {
			return &appError{err, "User not found", http.StatusNotFound}
		}

		user, key := users[0], keys[0]

		t := CreateTransport(c, user.MovesToken.NormToken())

		dailySegmentsList, err := GetLatestPlaces(t)
		if err != nil {
			return &appError{err, "Could not unmarshal request",
				http.StatusBadRequest}
		}

		return updateDailySegments(c, *dailySegmentsList, user, key)
	}

	return nil
}

func updateDailySegments(c appengine.Context,
	dailySegmentsList []DailySegments, user User,
	userKey *datastore.Key) *appError {
	f := urlfetch.Client(c)
	var phoneEntries []PhoneEntry
	_, err := datastore.NewQuery("PhoneEntry").Ancestor(userKey).GetAll(c, &phoneEntries)
	if err != nil {
		return &appError{err, "Error getting phones from datastore",
			http.StatusInternalServerError}
	}

	segmentsToProcess := make([]Segment, 0)

	// Find segments with StartTimes greater than the user's LastSegmentStartTime
	for _, dailySegments := range dailySegmentsList {
		for _, segment := range dailySegments.Segments {
			if user.LastSegmentStartTime.Time.Before(segment.StartTime.Time) {
				segmentsToProcess = append(segmentsToProcess, segment)
			}
		}
	}

	// If there aren't any, return
	if len(segmentsToProcess) <= 0 {
		return nil
	}

	client := tomtom.NewClient(tomtomKey, f)

	for _, segment := range segmentsToProcess {
		var address string
		if segment.Place.Name != "" {
			address = segment.Place.Name
		} else {
			codes, err := client.Geocode.ReverseGeocode(segment.Place.Location.Lat, segment.Place.Location.Lon)
			if err != nil {
				return &appError{err, "Error reverse geocoding address",
					http.StatusInternalServerError}
			}

			if len(codes) > 0 {
				address = codes[0].FormattedAddress
			} else {
				address = fmt.Sprintf("%f, %f", segment.Place.Location.Lat,
					segment.Place.Location.Lon)
			}
		}

		// send texts
		for _, phone := range phoneEntries {
			appError := sendText(c, "I'm now at "+address+".", phone.Phone)
			if err != nil {
				return appError
			}
		}
	}

	lastSegment := segmentsToProcess[len(segmentsToProcess)-1]
	user.LastSegmentStartTime = lastSegment.StartTime

	_, err = datastore.Put(c, userKey, &user)
	if err != nil {
		return &appError{err, "Error saving user", http.StatusInternalServerError}
	}

	return nil
}

func sendText(a appengine.Context, message string, phone string) *appError {
	f := urlfetch.Client(a)
	c := twilio.NewClient(twilioSid, twilioAuthToken, f)

	var params twilio.MessageParams
	params.Body = message
	_, _, err := c.Messages.Send(twilioPhone, phone, params)
	if err != nil {
		return &appError{err, "Error sending text message",
			http.StatusInternalServerError}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"math/rand"

	pb "github.com/brotherlogic/gobuildmaster/proto"
	pbs "github.com/brotherlogic/gobuildslave/proto"
	"github.com/golang/protobuf/proto"

	pbd "github.com/brotherlogic/discovery/proto"
)

type checker interface {
	assess(server string) (*pbs.JobList, *pbs.Config)
	discover() *pbd.ServiceList
}

func getFleetStatus(c checker) (map[string]*pbs.JobList, map[string]*pbs.Config) {
	resJ := make(map[string]*pbs.JobList)
	resC := make(map[string]*pbs.Config)

	for _, service := range c.discover().Services {
		log.Printf("Found: %v", service)
		if service.Name == "gobuildslave" {
			log.Printf("HERE: %v", service)
			joblist, config := c.assess(service.Identifier)
			resJ[service.Identifier] = joblist
			resC[service.Identifier] = config

			sub := 0
			for i := range resJ[service.Identifier].Details {
				if !resJ[service.Identifier].Details[i-sub].Running {
					resJ[service.Identifier].Details = append(resJ[service.Identifier].Details[:(i-sub)], resJ[service.Identifier].Details[(i-sub)+1:]...)
					sub++
				}
			}
		}
	}

	log.Printf("RETURNING FLEET STATUS: %v -> %v", resJ, resJ["framethree"])
	return resJ, resC
}

// Find the first available server
func chooseServer(job *pbs.JobSpec, c checker) string {
	services := c.discover().Services
	for i := range rand.Perm(len(services)) {
		service := services[i]
		log.Printf("Trying %v", service)
		if service.Name == "gobuildslave" {
			jobs, sc := c.assess(service.Identifier)

			//Don't accept a server which is already running this job
			jobfine := true
			for _, j := range jobs.Details {
				log.Printf("%v and %v", job, j.Spec)
				if j.Spec.Name == job.Name {
					jobfine = false
				}
			}
			if jobfine {
				if sc.Disk > job.Disk {
					return service.Identifier
				}
			}
		}
	}
	return ""
}

func configDiff(cm, cs *pb.Config) *pb.Config {
	retConfig := &pb.Config{}

	log.Printf("COMPARE %v to %v", cm, cs)
	for _, entry := range cm.Intents {
		nIntent := &pb.Intent{}
		nIntent.Spec = entry.Spec
		nIntent.Count = entry.Count
		retConfig.Intents = append(retConfig.Intents, nIntent)
	}

	log.Printf("FIRST PASS: %v", retConfig)
	for _, entry := range cs.Intents {
		for _, pair := range retConfig.Intents {
			if entry.Spec.Name == pair.Spec.Name {
				log.Printf("FOUND: %v", pair)
				pair.Count -= entry.Count
				log.Printf("RESULT: %v", retConfig)
			}
		}
	}

	log.Printf("RETURNING: %v", retConfig)
	return retConfig
}

func loadConfig(f string) (*pb.Config, error) {
	toload := &pb.Config{}
	bytes, _ := ioutil.ReadFile(f)
	proto.UnmarshalText(string(bytes), toload)
	return toload, nil
}

func runJobs(c *pb.Config) []*pbs.JobSpec {
	var jobs []*pbs.JobSpec
	for _, j := range c.Intents {
		for i := 0; i < int(j.Count); i++ {
			jobs = append(jobs, j.Spec)
		}
	}

	return jobs
}
<commit_msg>Added condition that code isn't running<commit_after>package main

import (
	"io/ioutil"
	"log"
	"math/rand"

	pb "github.com/brotherlogic/gobuildmaster/proto"
	pbs "github.com/brotherlogic/gobuildslave/proto"
	"github.com/golang/protobuf/proto"

	pbd "github.com/brotherlogic/discovery/proto"
)

type checker interface {
	assess(server string) (*pbs.JobList, *pbs.Config)
	discover() *pbd.ServiceList
}

func getFleetStatus(c checker) (map[string]*pbs.JobList, map[string]*pbs.Config) {
	resJ := make(map[string]*pbs.JobList)
	resC := make(map[string]*pbs.Config)

	for _, service := range c.discover().Services {
		log.Printf("Found: %v", service)
		if service.Name == "gobuildslave" {
			log.Printf("HERE: %v", service)
			joblist, config := c.assess(service.Identifier)
			resJ[service.Identifier] = joblist
			resC[service.Identifier] = config

			sub := 0
			for i := range resJ[service.Identifier].Details {
				if !resJ[service.Identifier].Details[i-sub].Running {
					resJ[service.Identifier].Details = append(resJ[service.Identifier].Details[:(i-sub)], resJ[service.Identifier].Details[(i-sub)+1:]...)
					sub++
				}
			}
		}
	}

	log.Printf("RETURNING FLEET STATUS: %v -> %v", resJ, resJ["framethree"])
	return resJ, resC
}

// Find the first available server
func chooseServer(job *pbs.JobSpec, c checker) string {
	services := c.discover().Services
	for i := range rand.Perm(len(services)) {
		service := services[i]
		log.Printf("Trying %v", service)
		if service.Name == "gobuildslave" {
			jobs, sc := c.assess(service.Identifier)

			//Don't accept a server which is already running this job
			jobfine := true
			for _, j := range jobs.Details {
				log.Printf("%v and %v", job, j.Spec)
				if j.Spec.Name == job.Name && j.Running {
					jobfine = false
				}
			}
			if jobfine {
				if sc.Disk > job.Disk {
					return service.Identifier
				}
			}
		}
	}
	return ""
}

func configDiff(cm, cs *pb.Config) *pb.Config {
	retConfig := &pb.Config{}

	log.Printf("COMPARE %v to %v", cm, cs)
	for _, entry := range cm.Intents {
		nIntent := &pb.Intent{}
		nIntent.Spec = entry.Spec
		nIntent.Count = entry.Count
		retConfig.Intents = append(retConfig.Intents, nIntent)
	}

	log.Printf("FIRST PASS: %v", retConfig)
	for _, entry := range cs.Intents {
		for _, pair := range retConfig.Intents {
			if entry.Spec.Name == pair.Spec.Name {
				log.Printf("FOUND: %v", pair)
				pair.Count -= entry.Count
				log.Printf("RESULT: %v", retConfig)
			}
		}
	}

	log.Printf("RETURNING: %v", retConfig)
	return retConfig
}

func loadConfig(f string) (*pb.Config, error) {
	toload := &pb.Config{}
	bytes, _ := ioutil.ReadFile(f)
	proto.UnmarshalText(string(bytes), toload)
	return toload, nil
}

func runJobs(c *pb.Config) []*pbs.JobSpec {
	var jobs []*pbs.JobSpec
	for _, j := range c.Intents {
		for i := 0; i < int(j.Count); i++ {
			jobs = append(jobs, j.Spec)
		}
	}

	return jobs
}
<|endoftext|>


<commit_before>package server

import (
	"keyvalue/protobuf"

	"code.google.com/p/goprotobuf/proto"

	"bufio"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	// "net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

const LogDir string = "log/"
const MaxSetsPerSec uint = 1024

type set struct {
	Key   string
	Value string
}

type Server struct {
	Port           uint16
	listener       net.Listener
	store          map[string]string
	storeLock      *sync.RWMutex // Maps aren't thread safe, must lock on writes using a readers-writer lock
	pending        chan *set     // Pending sets are sent to channel to be added
	pendingPersist chan *set
}

func Init(port uint16) (int, *Server) {
	log.Println("Server starting")

	//Listen to the TCP port
	listener, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
	if err != nil {
		log.Printf("Port %u could not be opened: %v\n", port, err)
		return -1, nil
	}

	server := &Server{
		Port:           port,
		listener:       listener,
		store:          make(map[string]string),
		storeLock:      &sync.RWMutex{},
		pending:        make(chan *set, 64),
		pendingPersist: make(chan *set, MaxSetsPerSec),
	}

	os.MkdirAll(LogDir, 0777)

	server.recover()
	log.Println("Server fully recovered")

	go server.run()
	go server.set()

	go server.persistDelta()
	go server.persistBase()

	// go func() {
	// 	http.handlefunc("/", func(w http.responsewriter, r *http.request) {
	// 		fmt.fprintf(w, "%v", server.store)
	// 	})

	// 	log.fatal(http.listenandserve(":8080", nil))
	// }()

	log.Println("Server accepting requests")
	return 0, server
}

func (s *Server) recover() {
	entries, err := ioutil.ReadDir(LogDir)
	if err != nil {
		log.Printf("Error reading log directory, unable to recover: %v", err)
		return
	}

	names := make([]string, len(entries))
	for index, entry := range entries {
		names[index] = entry.Name()
	}
	sort.Strings(names)

	s.storeLock.Lock()
	defer s.storeLock.Unlock()

	// Find the most recent back backup
	var baseEpoch int64
	for i := len(names) - 1; i >= 0; i-- {
		name := names[i]
		if strings.LastIndex(name, "-base") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				epoch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil {
					baseEpoch = epoch
				}
			}

			data, err := ioutil.ReadFile(path.Join(LogDir, name))
			if err != nil {
				log.Printf("Error reading base log, unable to recover: %v", err)
				return
			}

			err = json.Unmarshal(data, &s.store)
			if err != nil {
				log.Printf("Error unmarshalling base log, unable to recover: %v", err)
				return
			}

			// Truncate the list of names so we don't have to iterate
			// through all of them for delta recovery
			if len(names) >= i+1 {
				names = names[i+1:]
			}

			break
		}
	}

	for _, name := range names {
		if strings.LastIndex(name, "-delta") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				epoch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil && epoch > baseEpoch {
					data, err := ioutil.ReadFile(path.Join(LogDir, fmt.Sprintf("%d-delta", epoch)))
					if err != nil {
						log.Printf("Error reading delta log, recovery could be paritally incorrect: %v", err)
						continue
					}

					var sets []set
					err = json.Unmarshal(data, &sets)
					if err != nil {
						log.Printf("Error reading delta log, recovery could be paritally incorrect: %v", err)
						continue
					}

					for _, set := range sets {
						s.store[set.Key] = set.Value
					}
				}
			}
		}
	}
}

func (s *Server) run() {
	for {
		if conn, err := s.listener.Accept(); err == nil {
			go func(s *Server, conn net.Conn) {
				defer conn.Close()
				log.Println("Connection established with client")
				for {
					data := make([]byte, 4)
					_, err := conn.Read(data)
					if err != nil {
						log.Printf("Error reading length: %v", err)
						return
					}
					length64, _ := binary.Uvarint(data)
					length := int(length64)

					data = make([]byte, length)
					for i := 0; i < length; {
						//Read the data waiting on the connection and put it in the data buffer
						n, err := conn.Read(data[i : length-i])
						i += n
						if err != nil {
							log.Printf("Error reading request: %v", err)
							return
						}
					}
					//Create an struct pointer of type protobuf.Request and protobuf.Response struct
					request := new(protobuf.Request)
					//Convert all the data retrieved into the ProtobufTest.TestMessage struct type
					err = proto.Unmarshal(data[:length], request)
					if err != nil {
						log.Printf("Error in Unmarshalling: %v\n", err)
						return
					}
					response := new(protobuf.Response)
					response.Id = request.Id
					if request.GetValue() == "" {
						result, value := s.Get(request.GetKey())
						response.Result = proto.Int32(int32(result))
						response.Value = proto.String(value)
					} else {
						result, value := s.Set(request.GetKey(), request.GetValue())
						response.Result = proto.Int32(int32(result))
						response.Value = proto.String(value)
					}

					data, err = proto.Marshal(response)
					if err != nil {
						log.Printf("Marshaling error: %v\n", err)
						continue
					}

					length = len(data)
					lengthBytes := make([]byte, 4)
					binary.LittleEndian.PutUint32(lengthBytes, uint32(length))
					_, err = conn.Write(lengthBytes)
					if err != nil {
						log.Printf("Error writing data: %v\n", err)
						return
					}
					_, err = conn.Write(data)
					if err != nil {
						log.Printf("Error writing data: %v\n", err)
						return
					}
				}
			}(s, conn)
		} else {
			continue
		}
	}
}

func (s *Server) set() {
	for set := range s.pending {
		s.storeLock.Lock()
		s.store[set.Key] = set.Value
		s.storeLock.Unlock()

		s.pendingPersist <- set
	}
}

func (s *Server) persistDelta() {
	ticker := time.NewTicker(time.Second)
	for t := range ticker.C {
		func(s *Server) {
			length := len(s.pendingPersist)
			if length == 0 {
				return
			}

			buffer := make([]*set, length)
			for i := 0; i < length; i++ {
				buffer[i] = <-s.pendingPersist
			}

			deltaPath := path.Join(LogDir, fmt.Sprintf("%d-delta", t.UnixNano()))
			f, err := os.Create(deltaPath)
			if err != nil {
				log.Printf("Could not create file %s, failed with error: %v\n", deltaPath, err)
				return
			}
			defer f.Close()

			w := bufio.NewWriter(f)
			defer w.Flush()

			data, err := json.Marshal(buffer)
			if err != nil {
				log.Printf("Could not marshall delta log, with error: %v\n", err)
			}
			w.Write(data)
			if err != nil {
				log.Printf("Could not write data failed, with error: %v\n", err)
			}
		}(s)
	}
}

func (s *Server) persistBase() {
	ticker := time.NewTicker(time.Minute)
	for t := range ticker.C {
		func(s *Server) {
			basePath := path.Join(LogDir, fmt.Sprintf("%d-base", t.UnixNano()))
			f, err := os.Create(basePath)
			if err != nil {
				log.Printf("Could not create file %s, failed with error: %v\n", basePath, err)
				return
			}
			defer f.Close()

			w := bufio.NewWriter(f)
			defer w.Flush()

			s.storeLock.RLock()
			data, err := json.Marshal(s.store)
			s.storeLock.RUnlock()
			if err != nil {
				log.Printf("Could not marshall delta log, with error: %v\n", err)
			}
			w.Write(data)
			if err != nil {
				log.Printf("Could not write data failed, with error: %v\n", err)
			}
			go deleteOldPersistence(t.UnixNano())
		}(s)
	}
}

func deleteOldPersistence(epoch int64) {
	entries, err := ioutil.ReadDir(LogDir)
	if err != nil {
		log.Printf("Error reading log directory: %v", err)
	}
	for _, entry := range entries {
		name := entry.Name()
		if strings.LastIndex(name, "-base") >= 0 || strings.LastIndex(name, "-delta") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				touch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil && touch < epoch {
					os.Remove(path.Join(LogDir, name))
				}
			}
		}
	}
}

func (s *Server) Get(key string) (int, string) {
	if s.store == nil {
		log.Printf("Server Store is not initialized\n")
		return -1, ""
	}

	s.storeLock.RLock()
	value, present := s.store[key]
	s.storeLock.RUnlock()
	if present {
		return 0, value
	}
	return 1, ""
}

func (s *Server) Set(key string, value string) (int, string) {
	status, oldValue := s.Get(key)

	s.pending <- &set{Key: key, Value: value}

	return status, oldValue
}

func (s *Server) Close() {
	s.listener.Close()
}
<commit_msg>Optimize for ignoring no delta updates<commit_after>package server

import (
	"keyvalue/protobuf"

	"code.google.com/p/goprotobuf/proto"

	"bufio"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	// "net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

const LogDir string = "log/"
const MaxSetsPerSec uint = 1024

type set struct {
	Key   string
	Value string
}

type Server struct {
	Port           uint16
	listener       net.Listener
	store          map[string]string
	storeLock      *sync.RWMutex // Maps aren't thread safe, must lock on writes using a readers-writer lock
	pending        chan *set     // Pending sets are sent to channel to be added
	pendingPersist chan *set
}

func Init(port uint16) (int, *Server) {
	log.Println("Server starting")

	//Listen to the TCP port
	listener, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
	if err != nil {
		log.Printf("Port %u could not be opened: %v\n", port, err)
		return -1, nil
	}

	server := &Server{
		Port:           port,
		listener:       listener,
		store:          make(map[string]string),
		storeLock:      &sync.RWMutex{},
		pending:        make(chan *set, 64),
		pendingPersist: make(chan *set, MaxSetsPerSec),
	}

	os.MkdirAll(LogDir, 0777)

	server.recover()
	log.Println("Server fully recovered")

	go server.run()
	go server.set()

	go server.persistDelta()
	go server.persistBase()

	// go func() {
	// 	http.handlefunc("/", func(w http.responsewriter, r *http.request) {
	// 		fmt.fprintf(w, "%v", server.store)
	// 	})

	// 	log.fatal(http.listenandserve(":8080", nil))
	// }()

	log.Println("Server accepting requests")
	return 0, server
}

func (s *Server) recover() {
	entries, err := ioutil.ReadDir(LogDir)
	if err != nil {
		log.Printf("Error reading log directory, unable to recover: %v", err)
		return
	}

	names := make([]string, len(entries))
	for index, entry := range entries {
		names[index] = entry.Name()
	}
	sort.Strings(names)

	s.storeLock.Lock()
	defer s.storeLock.Unlock()

	// Find the most recent back backup
	var baseEpoch int64
	for i := len(names) - 1; i >= 0; i-- {
		name := names[i]
		if strings.LastIndex(name, "-base") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				epoch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil {
					baseEpoch = epoch
				}
			}

			data, err := ioutil.ReadFile(path.Join(LogDir, name))
			if err != nil {
				log.Printf("Error reading base log, unable to recover: %v", err)
				return
			}

			err = json.Unmarshal(data, &s.store)
			if err != nil {
				log.Printf("Error unmarshalling base log, unable to recover: %v", err)
				return
			}

			// Truncate the list of names so we don't have to iterate
			// through all of them for delta recovery
			if len(names) > i+1 {
				names = names[i+1:]
			} else {
				// No further delta updates in the list
				return
			}

			break
		}
	}

	for _, name := range names {
		if strings.LastIndex(name, "-delta") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				epoch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil && epoch > baseEpoch {
					data, err := ioutil.ReadFile(path.Join(LogDir, fmt.Sprintf("%d-delta", epoch)))
					if err != nil {
						log.Printf("Error reading delta log, recovery could be paritally incorrect: %v", err)
						continue
					}

					var sets []set
					err = json.Unmarshal(data, &sets)
					if err != nil {
						log.Printf("Error reading delta log, recovery could be paritally incorrect: %v", err)
						continue
					}

					for _, set := range sets {
						s.store[set.Key] = set.Value
					}
				}
			}
		}
	}
}

func (s *Server) run() {
	for {
		if conn, err := s.listener.Accept(); err == nil {
			go func(s *Server, conn net.Conn) {
				defer conn.Close()
				log.Println("Connection established with client")
				for {
					data := make([]byte, 4)
					_, err := conn.Read(data)
					if err != nil {
						log.Printf("Error reading length: %v", err)
						return
					}
					length64, _ := binary.Uvarint(data)
					length := int(length64)

					data = make([]byte, length)
					for i := 0; i < length; {
						//Read the data waiting on the connection and put it in the data buffer
						n, err := conn.Read(data[i : length-i])
						i += n
						if err != nil {
							log.Printf("Error reading request: %v", err)
							return
						}
					}
					//Create an struct pointer of type protobuf.Request and protobuf.Response struct
					request := new(protobuf.Request)
					//Convert all the data retrieved into the ProtobufTest.TestMessage struct type
					err = proto.Unmarshal(data[:length], request)
					if err != nil {
						log.Printf("Error in Unmarshalling: %v\n", err)
						return
					}
					response := new(protobuf.Response)
					response.Id = request.Id
					if request.GetValue() == "" {
						result, value := s.Get(request.GetKey())
						response.Result = proto.Int32(int32(result))
						response.Value = proto.String(value)
					} else {
						result, value := s.Set(request.GetKey(), request.GetValue())
						response.Result = proto.Int32(int32(result))
						response.Value = proto.String(value)
					}

					data, err = proto.Marshal(response)
					if err != nil {
						log.Printf("Marshaling error: %v\n", err)
						continue
					}

					length = len(data)
					lengthBytes := make([]byte, 4)
					binary.LittleEndian.PutUint32(lengthBytes, uint32(length))
					_, err = conn.Write(lengthBytes)
					if err != nil {
						log.Printf("Error writing data: %v\n", err)
						return
					}
					_, err = conn.Write(data)
					if err != nil {
						log.Printf("Error writing data: %v\n", err)
						return
					}
				}
			}(s, conn)
		} else {
			continue
		}
	}
}

func (s *Server) set() {
	for set := range s.pending {
		s.storeLock.Lock()
		s.store[set.Key] = set.Value
		s.storeLock.Unlock()

		s.pendingPersist <- set
	}
}

func (s *Server) persistDelta() {
	ticker := time.NewTicker(time.Second)
	for t := range ticker.C {
		func(s *Server) {
			length := len(s.pendingPersist)
			if length == 0 {
				return
			}

			buffer := make([]*set, length)
			for i := 0; i < length; i++ {
				buffer[i] = <-s.pendingPersist
			}

			deltaPath := path.Join(LogDir, fmt.Sprintf("%d-delta", t.UnixNano()))
			f, err := os.Create(deltaPath)
			if err != nil {
				log.Printf("Could not create file %s, failed with error: %v\n", deltaPath, err)
				return
			}
			defer f.Close()

			w := bufio.NewWriter(f)
			defer w.Flush()

			data, err := json.Marshal(buffer)
			if err != nil {
				log.Printf("Could not marshall delta log, with error: %v\n", err)
			}
			w.Write(data)
			if err != nil {
				log.Printf("Could not write data failed, with error: %v\n", err)
			}
		}(s)
	}
}

func (s *Server) persistBase() {
	ticker := time.NewTicker(time.Minute)
	for t := range ticker.C {
		func(s *Server) {
			basePath := path.Join(LogDir, fmt.Sprintf("%d-base", t.UnixNano()))
			f, err := os.Create(basePath)
			if err != nil {
				log.Printf("Could not create file %s, failed with error: %v\n", basePath, err)
				return
			}
			defer f.Close()

			w := bufio.NewWriter(f)
			defer w.Flush()

			s.storeLock.RLock()
			data, err := json.Marshal(s.store)
			s.storeLock.RUnlock()
			if err != nil {
				log.Printf("Could not marshall delta log, with error: %v\n", err)
			}
			w.Write(data)
			if err != nil {
				log.Printf("Could not write data failed, with error: %v\n", err)
			}
			go deleteOldPersistence(t.UnixNano())
		}(s)
	}
}

func deleteOldPersistence(epoch int64) {
	entries, err := ioutil.ReadDir(LogDir)
	if err != nil {
		log.Printf("Error reading log directory: %v", err)
	}
	for _, entry := range entries {
		name := entry.Name()
		if strings.LastIndex(name, "-base") >= 0 || strings.LastIndex(name, "-delta") >= 0 {
			split := strings.Split(name, "-")
			if len(split) == 2 {
				touch, err := strconv.ParseInt(split[0], 10, 64)
				if err == nil && touch < epoch {
					os.Remove(path.Join(LogDir, name))
				}
			}
		}
	}
}

func (s *Server) Get(key string) (int, string) {
	if s.store == nil {
		log.Printf("Server Store is not initialized\n")
		return -1, ""
	}

	s.storeLock.RLock()
	value, present := s.store[key]
	s.storeLock.RUnlock()
	if present {
		return 0, value
	}
	return 1, ""
}

func (s *Server) Set(key string, value string) (int, string) {
	status, oldValue := s.Get(key)

	s.pending <- &set{Key: key, Value: value}

	return status, oldValue
}

func (s *Server) Close() {
	s.listener.Close()
}
<|endoftext|>


<commit_before>package analytic

import (
	"errors"
	"math"

	"github.com/ready-steady/hotspot"
	"github.com/ready-steady/linear/decomposition"
	"github.com/ready-steady/linear/matrix"
)

// Temperature represents an integrator.
type Temperature struct {
	nc uint
	nn uint

	system system
}

// New returns an integrator set up according to the given configuration.
func New(c *Config) (*Temperature, error) {
	if c.TimeStep <= 0 {
		return nil, errors.New("the time step should be positive")
	}

	model := hotspot.New((*hotspot.Config)(&c.Config))
	nc, nn := model.Cores, model.Nodes

	// Reusing model.G to store A and model.C to store D.
	A := model.G
	D := model.C
	for i := uint(0); i < nn; i++ {
		D[i] = math.Sqrt(1 / model.C[i])
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nn; j++ {
			A[j*nn+i] = -D[i] * D[j] * A[j*nn+i]
		}
	}

	// Reusing A (which is model.G) to store U.
	U := A
	Λ := make([]float64, nn)
	if err := decomposition.SymEig(A, U, Λ, nn); err != nil {
		return nil, err
	}

	Δt := c.TimeStep

	coef := make([]float64, nn)
	temp := make([]float64, nn*nn)

	for i := uint(0); i < nn; i++ {
		coef[i] = math.Exp(Δt * Λ[i])
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nn; j++ {
			temp[j*nn+i] = coef[i] * U[i*nn+j]
		}
	}

	E := make([]float64, nn*nn)
	matrix.Multiply(U, temp, E, nn, nn, nn)

	// Technically, temp = temp[0 : nn*nc].
	for i := uint(0); i < nn; i++ {
		coef[i] = (coef[i] - 1) / Λ[i]
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nc; j++ {
			temp[j*nn+i] = coef[i] * U[i*nn+j] * D[j]
		}
	}

	F := make([]float64, nn*nc)
	matrix.Multiply(U, temp, F, nn, nn, nc)

	temperature := &Temperature{
		nc: nc,
		nn: nn,

		system: system{
			D: D,

			Λ: Λ,
			U: U,

			E: E,
			F: F,

			Qamb: c.Ambience,
		},
	}

	return temperature, nil
}
<commit_msg>Update the usage of linear<commit_after>package analytic

import (
	"errors"
	"math"

	"github.com/ready-steady/hotspot"
	"github.com/ready-steady/linear/matrix"
)

// Temperature represents an integrator.
type Temperature struct {
	nc uint
	nn uint

	system system
}

// New returns an integrator set up according to the given configuration.
func New(c *Config) (*Temperature, error) {
	if c.TimeStep <= 0 {
		return nil, errors.New("the time step should be positive")
	}

	model := hotspot.New((*hotspot.Config)(&c.Config))
	nc, nn := model.Cores, model.Nodes

	// Reusing model.G to store A and model.C to store D.
	A := model.G
	D := model.C
	for i := uint(0); i < nn; i++ {
		D[i] = math.Sqrt(1 / model.C[i])
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nn; j++ {
			A[j*nn+i] = -D[i] * D[j] * A[j*nn+i]
		}
	}

	// Reusing A (which is model.G) to store U.
	U := A
	Λ := make([]float64, nn)
	if err := matrix.SymmetricEigen(A, U, Λ, nn); err != nil {
		return nil, err
	}

	Δt := c.TimeStep

	coef := make([]float64, nn)
	temp := make([]float64, nn*nn)

	for i := uint(0); i < nn; i++ {
		coef[i] = math.Exp(Δt * Λ[i])
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nn; j++ {
			temp[j*nn+i] = coef[i] * U[i*nn+j]
		}
	}

	E := make([]float64, nn*nn)
	matrix.Multiply(U, temp, E, nn, nn, nn)

	// Technically, temp = temp[0 : nn*nc].
	for i := uint(0); i < nn; i++ {
		coef[i] = (coef[i] - 1) / Λ[i]
	}
	for i := uint(0); i < nn; i++ {
		for j := uint(0); j < nc; j++ {
			temp[j*nn+i] = coef[i] * U[i*nn+j] * D[j]
		}
	}

	F := make([]float64, nn*nc)
	matrix.Multiply(U, temp, F, nn, nn, nc)

	temperature := &Temperature{
		nc: nc,
		nn: nn,

		system: system{
			D: D,

			Λ: Λ,
			U: U,

			E: E,
			F: F,

			Qamb: c.Ambience,
		},
	}

	return temperature, nil
}
<|endoftext|>