<commit_before>package logrus_fluent

import (
	"fmt"
	"reflect"
	"strings"
)

// ConvertToValue make map data from struct and tags
func ConvertToValue(p interface{}, tagName string) interface{} {
	rv := toValue(p)
	switch rv.Kind() {
	case reflect.Struct:
		return converFromStruct(rv.Interface(), tagName)
	case reflect.Map:
		return convertFromMap(rv, tagName)
	case reflect.Slice:
		return convertFromSlice(rv, tagName)
	case reflect.Invalid:
		return nil
	default:
		return rv.Interface()
	}
}

func convertFromMap(rv reflect.Value, tagName string) interface{} {
	result := make(map[string]interface{})
	for _, key := range rv.MapKeys() {
		kv := rv.MapIndex(key)
		result[fmt.Sprint(key.Interface())] = ConvertToValue(kv.Interface(), tagName)
	}
	return result
}

func convertFromSlice(rv reflect.Value, tagName string) interface{} {
	var result []interface{}
	for i, max := 0, rv.Len(); i < max; i++ {
		result = append(result, ConvertToValue(rv.Index(i).Interface(), tagName))
	}
	return result
}

// converFromStruct converts struct to value
// see: https://github.com/fatih/structs/
func converFromStruct(p interface{}, tagName string) interface{} {
	result := make(map[string]interface{})
	t := toType(p)
	values := toValue(p)
	for i, max := 0, t.NumField(); i < max; i++ {
		f := t.Field(i)
		if f.PkgPath != "" {
			continue // skip private field
		}
		tag, opts := parseTag(f, tagName)
		if tag == "-" {
			continue // skip `-` tag
		}

		v := values.Field(i)
		if opts.Has("omitempty") && isZero(v) {
			continue // skip zero-value when omitempty option exists in tag
		}
		name := getNameFromTag(f, tagName)
		result[name] = ConvertToValue(v.Interface(), TagName)
	}
	return result
}

// toValue converts any value to reflect.Value
func toValue(p interface{}) reflect.Value {
	v := reflect.ValueOf(p)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	return v
}

// toType converts any value to reflect.Type
func toType(p interface{}) reflect.Type {
	t := reflect.ValueOf(p).Type()
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	return t
}

// isZero checks the value is zero-value or not
func isZero(v reflect.Value) bool {
	zero := reflect.Zero(v.Type()).Interface()
	value := v.Interface()
	return reflect.DeepEqual(value, zero)
}

// getNameFromTag return the value in tag or field name in the struct field
func getNameFromTag(f reflect.StructField, tagName string) string {
	tag, _ := parseTag(f, tagName)
	if tag != "" {
		return tag
	}
	return f.Name
}

// getTagValues returns tag value of the struct field
func getTagValues(f reflect.StructField, tag string) string {
	return f.Tag.Get(tag)
}

// parseTag returns the first tag value of the struct field
func parseTag(f reflect.StructField, tag string) (string, options) {
	return splitTags(getTagValues(f, tag))
}

// splitTags returns the first tag value and rest slice
func splitTags(tags string) (string, options) {
	res := strings.Split(tags, ",")
	return res[0], res[1:]
}

// TagOptions is wrapper struct for rest tag values
type options []string

// Has checks the value exists in the rest values or not
func (t options) Has(tag string) bool {
	for _, opt := range t {
		if opt == tag {
			return true
		}
	}
	return false
}
<commit_msg>Ignore channel value<commit_after>package logrus_fluent

import (
	"fmt"
	"reflect"
	"strings"
)

// ConvertToValue make map data from struct and tags
func ConvertToValue(p interface{}, tagName string) interface{} {
	rv := toValue(p)
	switch rv.Kind() {
	case reflect.Struct:
		return converFromStruct(rv.Interface(), tagName)
	case reflect.Map:
		return convertFromMap(rv, tagName)
	case reflect.Slice:
		return convertFromSlice(rv, tagName)
	case reflect.Chan:
		return nil
	case reflect.Invalid:
		return nil
	default:
		return rv.Interface()
	}
}

func convertFromMap(rv reflect.Value, tagName string) interface{} {
	result := make(map[string]interface{})
	for _, key := range rv.MapKeys() {
		kv := rv.MapIndex(key)
		result[fmt.Sprint(key.Interface())] = ConvertToValue(kv.Interface(), tagName)
	}
	return result
}

func convertFromSlice(rv reflect.Value, tagName string) interface{} {
	var result []interface{}
	for i, max := 0, rv.Len(); i < max; i++ {
		result = append(result, ConvertToValue(rv.Index(i).Interface(), tagName))
	}
	return result
}

// converFromStruct converts struct to value
// see: https://github.com/fatih/structs/
func converFromStruct(p interface{}, tagName string) interface{} {
	result := make(map[string]interface{})
	t := toType(p)
	values := toValue(p)
	for i, max := 0, t.NumField(); i < max; i++ {
		f := t.Field(i)
		if f.PkgPath != "" {
			continue // skip private field
		}
		tag, opts := parseTag(f, tagName)
		if tag == "-" {
			continue // skip `-` tag
		}

		v := values.Field(i)
		if opts.Has("omitempty") && isZero(v) {
			continue // skip zero-value when omitempty option exists in tag
		}
		name := getNameFromTag(f, tagName)
		result[name] = ConvertToValue(v.Interface(), TagName)
	}
	return result
}

// toValue converts any value to reflect.Value
func toValue(p interface{}) reflect.Value {
	v := reflect.ValueOf(p)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	return v
}

// toType converts any value to reflect.Type
func toType(p interface{}) reflect.Type {
	t := reflect.ValueOf(p).Type()
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	return t
}

// isZero checks the value is zero-value or not
func isZero(v reflect.Value) bool {
	zero := reflect.Zero(v.Type()).Interface()
	value := v.Interface()
	return reflect.DeepEqual(value, zero)
}

// getNameFromTag return the value in tag or field name in the struct field
func getNameFromTag(f reflect.StructField, tagName string) string {
	tag, _ := parseTag(f, tagName)
	if tag != "" {
		return tag
	}
	return f.Name
}

// getTagValues returns tag value of the struct field
func getTagValues(f reflect.StructField, tag string) string {
	return f.Tag.Get(tag)
}

// parseTag returns the first tag value of the struct field
func parseTag(f reflect.StructField, tag string) (string, options) {
	return splitTags(getTagValues(f, tag))
}

// splitTags returns the first tag value and rest slice
func splitTags(tags string) (string, options) {
	res := strings.Split(tags, ",")
	return res[0], res[1:]
}

// TagOptions is wrapper struct for rest tag values
type options []string

// Has checks the value exists in the rest values or not
func (t options) Has(tag string) bool {
	for _, opt := range t {
		if opt == tag {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package users

import (
	"github.com/gramework/threadsafe/cache"
)

type (
	System struct {
		store *Store
		cache *cache.Instance
	}
)
<commit_msg>users: fix build<commit_after>package users

import (
	"github.com/gramework/threadsafe/cache"
	"github.com/gramework/threadsafe/store"
)

type (
	System struct {
		store *store.Store
		cache *cache.Instance
	}
)
<|endoftext|>


<commit_before>/*
 * Minio Client (C) 2014, 2015 Minio, Inc.
 *
 * 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 (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio-xl/pkg/probe"
)

// rm specific flags.
var (
	rmFlagRecursive = cli.BoolFlag{
		Name:  "recursive, r",
		Usage: "Remove recursively.",
	}
	rmFlagForce = cli.BoolFlag{
		Name:  "force",
		Usage: "Force a dangerous remove operation.",
	}
	rmFlagIncomplete = cli.BoolFlag{
		Name:  "incomplete, I",
		Usage: "Remove an incomplete upload(s).",
	}
	rmFlagFake = cli.BoolFlag{
		Name:  "fake",
		Usage: "Perform a fake remove operation.",
	}
	rmFlagHelp = cli.BoolFlag{
		Name:  "help, h",
		Usage: "Help of rm.",
	}
)

// remove a file or folder.
var rmCmd = cli.Command{
	Name:   "rm",
	Usage:  "Remove file or bucket [WARNING: Use with care].",
	Action: mainRm,
	Flags:  []cli.Flag{rmFlagRecursive, rmFlagForce, rmFlagIncomplete, rmFlagFake, rmFlagHelp},
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] TARGET [TARGET ...]

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Remove a file.
      $ mc {{.Name}} 1999/old-backup.tgz

   2. Remove contents of a folder, excluding its sub-folders.
     $ mc {{.Name}} --force https://s3.amazonaws.com/jazz-songs/louis/

   3. Remove contents of a folder recursively.
     $ mc {{.Name}} --force --recursive https://s3.amazonaws.com/jazz-songs/louis/

   4. Remove all matching objects with this prefix.
     $ mc {{.Name}} --force --force https://s3.amazonaws.com/ogg/gunmetal

   5. Drop an incomplete upload of an object.
      $ mc {{.Name}} --incomplete https://s3.amazonaws.com/jazz-songs/louis/file01.mp3

   6. Drop all incomplete uploads recursively matching this prefix.
      $ mc {{.Name}} --incomplete --force --recursive https://s3.amazonaws.com/jazz-songs/louis/
`,
}

// Structured message depending on the type of console.
type rmMessage struct {
	URL string `json:"url"`
}

// Colorized message for console printing.
func (r rmMessage) String() string {
	return console.Colorize("Remove", fmt.Sprintf("Removed ‘%s’.", r.URL))
}

// JSON'ified message for scripting.
func (r rmMessage) JSON() string {
	msgBytes, e := json.Marshal(r)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(msgBytes)
}

// Validate command line arguments.
func checkRmSyntax(ctx *cli.Context) {
	isForce := ctx.Bool("force")
	isRecursive := ctx.Bool("recursive")

	if !ctx.Args().Present() {
		exitCode := 1
		cli.ShowCommandHelpAndExit(ctx, "rm", exitCode)
	}

	if isRecursive && !isForce {
		fatalIf(errDummy().Trace(),
			"Recursive removal requires --force option. Please review carefully before performing this *DANGEROUS* operation.")
	}
}

// Remove a single object.
func rm(url string, isIncomplete, isFake bool) *probe.Error {
	clnt, err := url2Client(url)
	if err != nil {
		return err.Trace(url)
	}

	if isFake { // It is a fake remove. Return success.
		return nil
	}

	if err = clnt.Remove(isIncomplete); err != nil {
		return err.Trace(url)
	}

	return nil
}

// Remove all objects recursively.
func rmAll(url string, isRecursive, isIncomplete, isFake bool) {
	// Initialize new client.
	clnt, err := url2Client(url)
	if err != nil {
		errorIf(err.Trace(url), "Invalid URL ‘"+url+"’.")
		return // End of journey.
	}

	/* Disable recursion and only list this folder's contents. We
	perform manual depth-first recursion ourself here. */
	nonRecursive := false
	for entry := range clnt.List(nonRecursive, isIncomplete) {
		if entry.Err != nil {
			errorIf(entry.Err.Trace(url), "Unable to list ‘"+url+"’.")
			return // End of journey.
		}

		if entry.Type.IsDir() && isRecursive {
			// Add separator at the end to remove all its contents.
			url := entry.URL
			url.Path = strings.TrimSuffix(entry.URL.Path, string(entry.URL.Separator)) + string(entry.URL.Separator)

			// Recursively remove contents of this directory.
			rmAll(url.String(), isRecursive, isIncomplete, isFake)
		}

		// Regular type.
		if err = rm(entry.URL.String(), isIncomplete, isFake); err != nil {
			errorIf(err.Trace(entry.URL.String()), "Unable to remove ‘"+entry.URL.String()+"’.")
			continue
		}
		printMsg(rmMessage{entry.URL.String()})
	}
}

// main for rm command.
func mainRm(ctx *cli.Context) {
	checkRmSyntax(ctx)

	// rm specific flags.
	isForce := ctx.Bool("force")
	isIncomplete := ctx.Bool("incomplete")
	isRecursive := ctx.Bool("recursive")
	isFake := ctx.Bool("fake")

	// Set color.
	console.SetColor("Remove", color.New(color.FgGreen, color.Bold))

	// Parse args.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	// Support multiple targets.
	for _, url := range URLs {
		if isRecursive && isForce {
			rmAll(url, isRecursive, isIncomplete, isFake)
		} else {
			if err := rm(url, isIncomplete, isFake); err != nil {
				errorIf(err.Trace(url), "Unable to remove ‘"+url+"’.")
			}
			printMsg(rmMessage{url})
		}
	}
}
<commit_msg>rm on non-empty dir was wrongly printing that it was removed - fixes #1371<commit_after>/*
 * Minio Client (C) 2014, 2015 Minio, Inc.
 *
 * 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 (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio-xl/pkg/probe"
)

// rm specific flags.
var (
	rmFlagRecursive = cli.BoolFlag{
		Name:  "recursive, r",
		Usage: "Remove recursively.",
	}
	rmFlagForce = cli.BoolFlag{
		Name:  "force",
		Usage: "Force a dangerous remove operation.",
	}
	rmFlagIncomplete = cli.BoolFlag{
		Name:  "incomplete, I",
		Usage: "Remove an incomplete upload(s).",
	}
	rmFlagFake = cli.BoolFlag{
		Name:  "fake",
		Usage: "Perform a fake remove operation.",
	}
	rmFlagHelp = cli.BoolFlag{
		Name:  "help, h",
		Usage: "Help of rm.",
	}
)

// remove a file or folder.
var rmCmd = cli.Command{
	Name:   "rm",
	Usage:  "Remove file or bucket [WARNING: Use with care].",
	Action: mainRm,
	Flags:  []cli.Flag{rmFlagRecursive, rmFlagForce, rmFlagIncomplete, rmFlagFake, rmFlagHelp},
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] TARGET [TARGET ...]

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Remove a file.
      $ mc {{.Name}} 1999/old-backup.tgz

   2. Remove contents of a folder, excluding its sub-folders.
     $ mc {{.Name}} --force https://s3.amazonaws.com/jazz-songs/louis/

   3. Remove contents of a folder recursively.
     $ mc {{.Name}} --force --recursive https://s3.amazonaws.com/jazz-songs/louis/

   4. Remove all matching objects with this prefix.
     $ mc {{.Name}} --force --force https://s3.amazonaws.com/ogg/gunmetal

   5. Drop an incomplete upload of an object.
      $ mc {{.Name}} --incomplete https://s3.amazonaws.com/jazz-songs/louis/file01.mp3

   6. Drop all incomplete uploads recursively matching this prefix.
      $ mc {{.Name}} --incomplete --force --recursive https://s3.amazonaws.com/jazz-songs/louis/
`,
}

// Structured message depending on the type of console.
type rmMessage struct {
	URL string `json:"url"`
}

// Colorized message for console printing.
func (r rmMessage) String() string {
	return console.Colorize("Remove", fmt.Sprintf("Removed ‘%s’.", r.URL))
}

// JSON'ified message for scripting.
func (r rmMessage) JSON() string {
	msgBytes, e := json.Marshal(r)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(msgBytes)
}

// Validate command line arguments.
func checkRmSyntax(ctx *cli.Context) {
	isForce := ctx.Bool("force")
	isRecursive := ctx.Bool("recursive")

	if !ctx.Args().Present() {
		exitCode := 1
		cli.ShowCommandHelpAndExit(ctx, "rm", exitCode)
	}

	if isRecursive && !isForce {
		fatalIf(errDummy().Trace(),
			"Recursive removal requires --force option. Please review carefully before performing this *DANGEROUS* operation.")
	}
}

// Remove a single object.
func rm(url string, isIncomplete, isFake bool) *probe.Error {
	clnt, err := url2Client(url)
	if err != nil {
		return err.Trace(url)
	}

	if isFake { // It is a fake remove. Return success.
		return nil
	}

	if err = clnt.Remove(isIncomplete); err != nil {
		return err.Trace(url)
	}

	return nil
}

// Remove all objects recursively.
func rmAll(url string, isRecursive, isIncomplete, isFake bool) {
	// Initialize new client.
	clnt, err := url2Client(url)
	if err != nil {
		errorIf(err.Trace(url), "Invalid URL ‘"+url+"’.")
		return // End of journey.
	}

	/* Disable recursion and only list this folder's contents. We
	perform manual depth-first recursion ourself here. */
	nonRecursive := false
	for entry := range clnt.List(nonRecursive, isIncomplete) {
		if entry.Err != nil {
			errorIf(entry.Err.Trace(url), "Unable to list ‘"+url+"’.")
			return // End of journey.
		}

		if entry.Type.IsDir() && isRecursive {
			// Add separator at the end to remove all its contents.
			url := entry.URL
			url.Path = strings.TrimSuffix(entry.URL.Path, string(entry.URL.Separator)) + string(entry.URL.Separator)

			// Recursively remove contents of this directory.
			rmAll(url.String(), isRecursive, isIncomplete, isFake)
		}

		// Regular type.
		if err = rm(entry.URL.String(), isIncomplete, isFake); err != nil {
			errorIf(err.Trace(entry.URL.String()), "Unable to remove ‘"+entry.URL.String()+"’.")
			continue
		}
		printMsg(rmMessage{entry.URL.String()})
	}
}

// main for rm command.
func mainRm(ctx *cli.Context) {
	checkRmSyntax(ctx)

	// rm specific flags.
	isForce := ctx.Bool("force")
	isIncomplete := ctx.Bool("incomplete")
	isRecursive := ctx.Bool("recursive")
	isFake := ctx.Bool("fake")

	// Set color.
	console.SetColor("Remove", color.New(color.FgGreen, color.Bold))

	// Parse args.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	// Support multiple targets.
	for _, url := range URLs {
		if isRecursive && isForce {
			rmAll(url, isRecursive, isIncomplete, isFake)
		} else {
			if err := rm(url, isIncomplete, isFake); err != nil {
				errorIf(err.Trace(url), "Unable to remove ‘"+url+"’.")
				continue
			}
			printMsg(rmMessage{url})
		}
	}
}
<|endoftext|>


<commit_before>package mtp

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"reflect"
	"strings"
	"time"
	"unicode/utf8"
)

var byteOrder = binary.LittleEndian

func decodeStr(r io.Reader) (string, error) {
	var szSlice [1]byte
	_, err := r.Read(szSlice[:])
	if err != nil {
		return "", err
	}
	sz := int(szSlice[0])
	if sz == 0 {
		return "", nil
	}
	utfStr := make([]byte, 4*sz)
	data := make([]byte, 2*sz)
	n, err := r.Read(data)
	if err != nil {
		return "", err
	}
	if n < len(data) {
		return "", fmt.Errorf("underflow")
	}
	w := 0
	for i := 0; i < int(2*sz); i += 2 {
		cp := byteOrder.Uint16(data[i:])
		w += utf8.EncodeRune(utfStr[w:], rune(cp))
	}
	if utfStr[w-1] == 0 {
		w--
	}
	s := string(utfStr[:w])
	return s, nil
}

func encodeStr(buf []byte, s string) ([]byte, error) {
	if s == "" {
		buf[0] = 0
		return buf[:1], nil
	}

	codepoints := 0
	buf = append(buf[:0], 0)

	var rune [2]byte
	for _, r := range s {
		byteOrder.PutUint16(rune[:], uint16(r))
		buf = append(buf, rune[0], rune[1])
		codepoints++
	}
	buf = append(buf, 0, 0)
	codepoints++
	if codepoints > 254 {
		return nil, fmt.Errorf("string too long")
	}

	buf[0] = byte(codepoints)
	return buf, nil
}

func encodeStrField(w io.Writer, f reflect.Value) error {
	out := make([]byte, 2*f.Len()+4)
	enc, err := encodeStr(out, f.Interface().(string))
	if err != nil {
		return err
	}
	_, err = w.Write(enc)
	return err
}

func kindSize(k reflect.Kind) int {
	switch k {
	case reflect.Int8:
		return 1
	case reflect.Int16:
		return 2
	case reflect.Int32:
		return 4
	case reflect.Int64:
		return 8
	case reflect.Uint8:
		return 1
	case reflect.Uint16:
		return 2
	case reflect.Uint32:
		return 4
	default:
		panic(fmt.Sprintf("unknown kind %v", k))
	}
	return 0
}

var nullValue reflect.Value

func decodeArray(r io.Reader, t reflect.Type) (reflect.Value, error) {
	var sz uint32
	err := binary.Read(r, byteOrder, &sz)
	if err != nil {
		return nullValue, err
	}

	ksz := int(kindSize(t.Elem().Kind()))

	data := make([]byte, int(sz)*ksz)
	_, err = r.Read(data)
	if err != nil {
		return nullValue, err
	}
	slice := reflect.MakeSlice(t, int(sz), int(sz))
	for i := 0; i < int(sz); i++ {
		from := data[i*ksz:]
		var val uint64
		switch ksz {
		case 1:
			val = uint64(from[0])
		case 2:
			val = uint64(byteOrder.Uint16(from[0:]))
		case 4:
			val = uint64(byteOrder.Uint32(from[0:]))
		default:
			panic("unimp")
		}

		slice.Index(i).SetUint(val)
	}
	return slice, nil
}

func encodeArray(w io.Writer, val reflect.Value) error {
	sz := uint32(val.Len())
	err := binary.Write(w, byteOrder, &sz)
	if err != nil {
		return err
	}

	kind := val.Type().Elem().Kind()
	ksz := 0
	if kind == reflect.Interface {
		log.Println("OK")
		ksz = int(kindSize(val.Index(0).Elem().Kind()))
	} else {
		ksz = int(kindSize(kind))
	}
	data := make([]byte, int(sz)*ksz)
	for i := 0; i < int(sz); i++ {
		elt := val.Index(i)
		to := data[i*ksz:]

		switch kind {
		case reflect.Uint8:
			to[0] = byte(elt.Uint())
		case reflect.Uint16:
			byteOrder.PutUint16(to, uint16(elt.Uint()))
		case reflect.Uint32:
			byteOrder.PutUint32(to, uint32(elt.Uint()))
		case reflect.Uint64:
			byteOrder.PutUint64(to, uint64(elt.Uint()))

		case reflect.Int8:
			to[0] = byte(elt.Int())
		case reflect.Int16:
			byteOrder.PutUint16(to, uint16(elt.Int()))
		case reflect.Int32:
			byteOrder.PutUint32(to, uint32(elt.Int()))
		case reflect.Int64:
			byteOrder.PutUint64(to, uint64(elt.Int()))
		default:
			panic(fmt.Sprintf("unimplemented: encode for kind %v", kind))
		}
	}
	_, err = w.Write(data)
	return err
}

var timeType = reflect.ValueOf(time.Now()).Type()

const timeFormat = "20060102T150405"

var zeroTime = time.Time{}

func encodeTime(w io.Writer, f reflect.Value) error {
	tptr := f.Addr().Interface().(*time.Time)
	s := ""
	if !tptr.Equal(zeroTime) {
		s = tptr.Format(timeFormat)
	}

	out := make([]byte, 2*len(s)+3)
	out, err := encodeStr(out, s)
	if err != nil {
		return err
	}
	_, err = w.Write(out)
	return err
}

func decodeTime(r io.Reader, f reflect.Value) error {
	s, err := decodeStr(r)
	if err != nil {
		return err
	}
	var t time.Time
	if s != "" {
		// Samsung has trailing dots.
		s = strings.TrimRight(s, ".")
		t, err = time.Parse(timeFormat, s)
		if err != nil {
			return err
		}
	}
	f.Set(reflect.ValueOf(t))
	return nil
}

func decodeField(r io.Reader, f reflect.Value, typeSelector DataTypeSelector) error {
	if !f.CanAddr() {
		return fmt.Errorf("canaddr false")
	}

	if f.Type() == timeType {
		return decodeTime(r, f)
	}

	switch f.Kind() {
	case reflect.Uint8:
		fallthrough
	case reflect.Uint16:
		fallthrough
	case reflect.Uint32:
		fallthrough
	case reflect.Uint64:
		fallthrough
	case reflect.Int64:
		fallthrough
	case reflect.Int32:
		fallthrough
	case reflect.Int16:
		fallthrough
	case reflect.Int8:
		return binary.Read(r, byteOrder, f.Addr().Interface())
	case reflect.String:
		s, err := decodeStr(r)
		if err != nil {
			return err
		}
		f.SetString(s)
	case reflect.Slice:
		sl, err := decodeArray(r, f.Type())
		if err != nil {
			return err
		}
		f.Set(sl)
	case reflect.Interface:
		val := InstantiateType(typeSelector)
		decodeField(r, val, typeSelector)
		f.Set(val)
	default:
		panic(fmt.Sprintf("unimplemented kind %v", f))
	}
	return nil
}

func encodeField(w io.Writer, f reflect.Value) error {
	if f.Type() == timeType {
		return encodeTime(w, f)
	}

	switch f.Kind() {
	case reflect.Uint8:
		fallthrough
	case reflect.Uint16:
		fallthrough
	case reflect.Uint32:
		fallthrough
	case reflect.Uint64:
		fallthrough
	case reflect.Int64:
		fallthrough
	case reflect.Int32:
		fallthrough
	case reflect.Int16:
		fallthrough
	case reflect.Int8:
		return binary.Write(w, byteOrder, f.Interface())
	case reflect.String:
		return encodeStrField(w, f)
	case reflect.Slice:
		return encodeArray(w, f)
	case reflect.Interface:
		return encodeField(w, f.Elem())
	default:
		panic(fmt.Sprintf("unimplemented kind %v", f))
	}
	return nil
}

// Decode MTP data stream into data structure.
func Decode(r io.Reader, iface interface{}) error {
	decoder, ok := iface.(Decoder)
	if ok {
		return decoder.Decode(r)
	}

	typeSel := DataTypeSelector(0xfe)
	return decodeWithSelector(r, iface, typeSel)
}

func decodeWithSelector(r io.Reader, iface interface{}, typeSel DataTypeSelector) error {
	val := reflect.ValueOf(iface)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("need ptr argument: %T", iface)
	}
	val = val.Elem()
	t := val.Type()

	for i := 0; i < t.NumField(); i++ {
		err := decodeField(r, val.Field(i), typeSel)

		if err != nil {
			return err
		}
		if val.Field(i).Type().Name() == "DataTypeSelector" {
			typeSel = val.Field(i).Interface().(DataTypeSelector)
		}

	}
	return nil
}

// Encode MTP data stream into data structure.
func Encode(w io.Writer, iface interface{}) error {
	encoder, ok := iface.(Encoder)
	if ok {
		return encoder.Encode(w)
	}

	val := reflect.ValueOf(iface)
	if val.Kind() != reflect.Ptr {
		msg := fmt.Sprintf("need ptr argument: %T", iface)
		return fmt.Errorf(msg)
		//panic("need ptr argument: %T")
	}
	val = val.Elem()
	t := val.Type()

	for i := 0; i < t.NumField(); i++ {
		err := encodeField(w, val.Field(i))
		if err != nil {
			return err
		}
	}
	return nil

}

// Instantiates an object of wanted type as addressable value.
func InstantiateType(t DataTypeSelector) reflect.Value {
	var val interface{}
	switch t {
	case DTC_INT8:
		v := int8(0)
		val = &v
	case DTC_UINT8:
		v := int8(0)
		val = &v
	case DTC_INT16:
		v := int16(0)
		val = &v
	case DTC_UINT16:
		v := uint16(0)
		val = &v
	case DTC_INT32:
		v := int32(0)
		val = &v
	case DTC_UINT32:
		v := uint32(0)
		val = &v
	case DTC_INT64:
		v := int64(0)
		val = &v
	case DTC_UINT64:
		v := uint64(0)
		val = &v
	case DTC_INT128:
		v := [16]byte{}
		val = &v
	case DTC_UINT128:
		v := [16]byte{}
		val = &v
	case DTC_STR:
		s := ""
		val = &s
	default:
		panic(fmt.Sprintf("type not known 0x%x", t))
	}

	return reflect.ValueOf(val).Elem()
}

func decodePropDescForm(r io.Reader, selector DataTypeSelector, formFlag uint8) (DataDependentType, error) {
	if formFlag == DPFF_Range {
		f := PropDescRangeForm{}
		err := decodeWithSelector(r, reflect.ValueOf(&f).Interface(),
			selector)
		return &f, err
	} else if formFlag == DPFF_Enumeration {
		f := PropDescEnumForm{}
		err := decodeWithSelector(r, reflect.ValueOf(&f).Interface(),
			selector)
		return &f, err
	}
	return nil, nil
}

func (pd *ObjectPropDesc) Decode(r io.Reader) (err error) {
	err = Decode(r, &pd.ObjectPropDescFixed)
	if err != nil {
		return err
	}
	form, err := decodePropDescForm(r, pd.DataType, pd.FormFlag)
	pd.Form = form
	return err
}

func (pd *DevicePropDesc) Decode(r io.Reader) (err error) {
	err = Decode(r, &pd.DevicePropDescFixed)
	if err != nil {
		return err
	}
	form, err := decodePropDescForm(r, pd.DataType, pd.FormFlag)
	pd.Form = form
	return err
}

func (pd *DevicePropDesc) Encode(w io.Writer) (err error) {
	err = Encode(w, &pd.DevicePropDescFixed)
	if err != nil {
		return err
	}

	err = Encode(w, pd.Form)
	return err
}

func (pd *ObjectPropDesc) Encode(w io.Writer) (err error) {
	err = Encode(w, &pd.ObjectPropDescFixed)
	if err != nil {
		return err
	}
	return Encode(w, pd.Form)
}
<commit_msg>Parse time zone in timestamp strings.<commit_after>package mtp

import (
	"encoding/binary"
	"fmt"
	"io"
	"log"
	"reflect"
	"strings"
	"time"
	"unicode/utf8"
)

var byteOrder = binary.LittleEndian

func decodeStr(r io.Reader) (string, error) {
	var szSlice [1]byte
	_, err := r.Read(szSlice[:])
	if err != nil {
		return "", err
	}
	sz := int(szSlice[0])
	if sz == 0 {
		return "", nil
	}
	utfStr := make([]byte, 4*sz)
	data := make([]byte, 2*sz)
	n, err := r.Read(data)
	if err != nil {
		return "", err
	}
	if n < len(data) {
		return "", fmt.Errorf("underflow")
	}
	w := 0
	for i := 0; i < int(2*sz); i += 2 {
		cp := byteOrder.Uint16(data[i:])
		w += utf8.EncodeRune(utfStr[w:], rune(cp))
	}
	if utfStr[w-1] == 0 {
		w--
	}
	s := string(utfStr[:w])
	return s, nil
}

func encodeStr(buf []byte, s string) ([]byte, error) {
	if s == "" {
		buf[0] = 0
		return buf[:1], nil
	}

	codepoints := 0
	buf = append(buf[:0], 0)

	var rune [2]byte
	for _, r := range s {
		byteOrder.PutUint16(rune[:], uint16(r))
		buf = append(buf, rune[0], rune[1])
		codepoints++
	}
	buf = append(buf, 0, 0)
	codepoints++
	if codepoints > 254 {
		return nil, fmt.Errorf("string too long")
	}

	buf[0] = byte(codepoints)
	return buf, nil
}

func encodeStrField(w io.Writer, f reflect.Value) error {
	out := make([]byte, 2*f.Len()+4)
	enc, err := encodeStr(out, f.Interface().(string))
	if err != nil {
		return err
	}
	_, err = w.Write(enc)
	return err
}

func kindSize(k reflect.Kind) int {
	switch k {
	case reflect.Int8:
		return 1
	case reflect.Int16:
		return 2
	case reflect.Int32:
		return 4
	case reflect.Int64:
		return 8
	case reflect.Uint8:
		return 1
	case reflect.Uint16:
		return 2
	case reflect.Uint32:
		return 4
	default:
		panic(fmt.Sprintf("unknown kind %v", k))
	}
	return 0
}

var nullValue reflect.Value

func decodeArray(r io.Reader, t reflect.Type) (reflect.Value, error) {
	var sz uint32
	err := binary.Read(r, byteOrder, &sz)
	if err != nil {
		return nullValue, err
	}

	ksz := int(kindSize(t.Elem().Kind()))

	data := make([]byte, int(sz)*ksz)
	_, err = r.Read(data)
	if err != nil {
		return nullValue, err
	}
	slice := reflect.MakeSlice(t, int(sz), int(sz))
	for i := 0; i < int(sz); i++ {
		from := data[i*ksz:]
		var val uint64
		switch ksz {
		case 1:
			val = uint64(from[0])
		case 2:
			val = uint64(byteOrder.Uint16(from[0:]))
		case 4:
			val = uint64(byteOrder.Uint32(from[0:]))
		default:
			panic("unimp")
		}

		slice.Index(i).SetUint(val)
	}
	return slice, nil
}

func encodeArray(w io.Writer, val reflect.Value) error {
	sz := uint32(val.Len())
	err := binary.Write(w, byteOrder, &sz)
	if err != nil {
		return err
	}

	kind := val.Type().Elem().Kind()
	ksz := 0
	if kind == reflect.Interface {
		log.Println("OK")
		ksz = int(kindSize(val.Index(0).Elem().Kind()))
	} else {
		ksz = int(kindSize(kind))
	}
	data := make([]byte, int(sz)*ksz)
	for i := 0; i < int(sz); i++ {
		elt := val.Index(i)
		to := data[i*ksz:]

		switch kind {
		case reflect.Uint8:
			to[0] = byte(elt.Uint())
		case reflect.Uint16:
			byteOrder.PutUint16(to, uint16(elt.Uint()))
		case reflect.Uint32:
			byteOrder.PutUint32(to, uint32(elt.Uint()))
		case reflect.Uint64:
			byteOrder.PutUint64(to, uint64(elt.Uint()))

		case reflect.Int8:
			to[0] = byte(elt.Int())
		case reflect.Int16:
			byteOrder.PutUint16(to, uint16(elt.Int()))
		case reflect.Int32:
			byteOrder.PutUint32(to, uint32(elt.Int()))
		case reflect.Int64:
			byteOrder.PutUint64(to, uint64(elt.Int()))
		default:
			panic(fmt.Sprintf("unimplemented: encode for kind %v", kind))
		}
	}
	_, err = w.Write(data)
	return err
}

var timeType = reflect.ValueOf(time.Now()).Type()

const timeFormat = "20060102T150405"
const timeFormatNumTZ = "20060102T150405-0700"

var zeroTime = time.Time{}

func encodeTime(w io.Writer, f reflect.Value) error {
	tptr := f.Addr().Interface().(*time.Time)
	s := ""
	if !tptr.Equal(zeroTime) {
		s = tptr.Format(timeFormat)
	}

	out := make([]byte, 2*len(s)+3)
	out, err := encodeStr(out, s)
	if err != nil {
		return err
	}
	_, err = w.Write(out)
	return err
}

func decodeTime(r io.Reader, f reflect.Value) error {
	s, err := decodeStr(r)
	if err != nil {
		return err
	}
	var t time.Time
	if s != "" {
		// Samsung has trailing dots.
		s = strings.TrimRight(s, ".")
		t, err = time.Parse(timeFormat, s)
		if err != nil {
			// Nokia lumia has numTZ
			t, err = time.Parse(timeFormatNumTZ, s)
			if err != nil {
				return err
			}
		}
	}
	f.Set(reflect.ValueOf(t))
	return nil
}

func decodeField(r io.Reader, f reflect.Value, typeSelector DataTypeSelector) error {
	if !f.CanAddr() {
		return fmt.Errorf("canaddr false")
	}

	if f.Type() == timeType {
		return decodeTime(r, f)
	}

	switch f.Kind() {
	case reflect.Uint8:
		fallthrough
	case reflect.Uint16:
		fallthrough
	case reflect.Uint32:
		fallthrough
	case reflect.Uint64:
		fallthrough
	case reflect.Int64:
		fallthrough
	case reflect.Int32:
		fallthrough
	case reflect.Int16:
		fallthrough
	case reflect.Int8:
		return binary.Read(r, byteOrder, f.Addr().Interface())
	case reflect.String:
		s, err := decodeStr(r)
		if err != nil {
			return err
		}
		f.SetString(s)
	case reflect.Slice:
		sl, err := decodeArray(r, f.Type())
		if err != nil {
			return err
		}
		f.Set(sl)
	case reflect.Interface:
		val := InstantiateType(typeSelector)
		decodeField(r, val, typeSelector)
		f.Set(val)
	default:
		panic(fmt.Sprintf("unimplemented kind %v", f))
	}
	return nil
}

func encodeField(w io.Writer, f reflect.Value) error {
	if f.Type() == timeType {
		return encodeTime(w, f)
	}

	switch f.Kind() {
	case reflect.Uint8:
		fallthrough
	case reflect.Uint16:
		fallthrough
	case reflect.Uint32:
		fallthrough
	case reflect.Uint64:
		fallthrough
	case reflect.Int64:
		fallthrough
	case reflect.Int32:
		fallthrough
	case reflect.Int16:
		fallthrough
	case reflect.Int8:
		return binary.Write(w, byteOrder, f.Interface())
	case reflect.String:
		return encodeStrField(w, f)
	case reflect.Slice:
		return encodeArray(w, f)
	case reflect.Interface:
		return encodeField(w, f.Elem())
	default:
		panic(fmt.Sprintf("unimplemented kind %v", f))
	}
	return nil
}

// Decode MTP data stream into data structure.
func Decode(r io.Reader, iface interface{}) error {
	decoder, ok := iface.(Decoder)
	if ok {
		return decoder.Decode(r)
	}

	typeSel := DataTypeSelector(0xfe)
	return decodeWithSelector(r, iface, typeSel)
}

func decodeWithSelector(r io.Reader, iface interface{}, typeSel DataTypeSelector) error {
	val := reflect.ValueOf(iface)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("need ptr argument: %T", iface)
	}
	val = val.Elem()
	t := val.Type()

	for i := 0; i < t.NumField(); i++ {
		err := decodeField(r, val.Field(i), typeSel)

		if err != nil {
			return err
		}
		if val.Field(i).Type().Name() == "DataTypeSelector" {
			typeSel = val.Field(i).Interface().(DataTypeSelector)
		}

	}
	return nil
}

// Encode MTP data stream into data structure.
func Encode(w io.Writer, iface interface{}) error {
	encoder, ok := iface.(Encoder)
	if ok {
		return encoder.Encode(w)
	}

	val := reflect.ValueOf(iface)
	if val.Kind() != reflect.Ptr {
		msg := fmt.Sprintf("need ptr argument: %T", iface)
		return fmt.Errorf(msg)
		//panic("need ptr argument: %T")
	}
	val = val.Elem()
	t := val.Type()

	for i := 0; i < t.NumField(); i++ {
		err := encodeField(w, val.Field(i))
		if err != nil {
			return err
		}
	}
	return nil

}

// Instantiates an object of wanted type as addressable value.
func InstantiateType(t DataTypeSelector) reflect.Value {
	var val interface{}
	switch t {
	case DTC_INT8:
		v := int8(0)
		val = &v
	case DTC_UINT8:
		v := int8(0)
		val = &v
	case DTC_INT16:
		v := int16(0)
		val = &v
	case DTC_UINT16:
		v := uint16(0)
		val = &v
	case DTC_INT32:
		v := int32(0)
		val = &v
	case DTC_UINT32:
		v := uint32(0)
		val = &v
	case DTC_INT64:
		v := int64(0)
		val = &v
	case DTC_UINT64:
		v := uint64(0)
		val = &v
	case DTC_INT128:
		v := [16]byte{}
		val = &v
	case DTC_UINT128:
		v := [16]byte{}
		val = &v
	case DTC_STR:
		s := ""
		val = &s
	default:
		panic(fmt.Sprintf("type not known 0x%x", t))
	}

	return reflect.ValueOf(val).Elem()
}

func decodePropDescForm(r io.Reader, selector DataTypeSelector, formFlag uint8) (DataDependentType, error) {
	if formFlag == DPFF_Range {
		f := PropDescRangeForm{}
		err := decodeWithSelector(r, reflect.ValueOf(&f).Interface(),
			selector)
		return &f, err
	} else if formFlag == DPFF_Enumeration {
		f := PropDescEnumForm{}
		err := decodeWithSelector(r, reflect.ValueOf(&f).Interface(),
			selector)
		return &f, err
	}
	return nil, nil
}

func (pd *ObjectPropDesc) Decode(r io.Reader) (err error) {
	err = Decode(r, &pd.ObjectPropDescFixed)
	if err != nil {
		return err
	}
	form, err := decodePropDescForm(r, pd.DataType, pd.FormFlag)
	pd.Form = form
	return err
}

func (pd *DevicePropDesc) Decode(r io.Reader) (err error) {
	err = Decode(r, &pd.DevicePropDescFixed)
	if err != nil {
		return err
	}
	form, err := decodePropDescForm(r, pd.DataType, pd.FormFlag)
	pd.Form = form
	return err
}

func (pd *DevicePropDesc) Encode(w io.Writer) (err error) {
	err = Encode(w, &pd.DevicePropDescFixed)
	if err != nil {
		return err
	}

	err = Encode(w, pd.Form)
	return err
}

func (pd *ObjectPropDesc) Encode(w io.Writer) (err error) {
	err = Encode(w, &pd.ObjectPropDescFixed)
	if err != nil {
		return err
	}
	return Encode(w, pd.Form)
}
<|endoftext|>


<commit_before>package gps

import (
	"fmt"
	"log"
	"bufio"
	"time"

	"github.com/tarm/serial"
	"github.com/mitchellh/go-linereader"
)

func InitGPS() {
	log.Printf("In gps.InitGPS()\n")

	// eventually I would like to come up with a reliable autodetection scheme for different types of gps.
	// for now I'll just have entry points into different configurations that get uncommented here

	err := initUltimateGPS()
	if err != nil {
		log.Printf("Error initializing gps: %v\n", err)
	}
}

// this works based on a channel/goroutine based timeout pattern
// GPS should provide some valid sentence at least once per second.
// If I don't receive something in two seconds, this probably isn't a valid config
func detectGPS(config *serial.Config) (bool, error) {
	p, err := serial.OpenPort(config)
	if err != nil { return false, err }
	defer p.Close()

	lr := linereader.New(p)
	lr.Timeout = time.Second * 2

	for {
		select {
		case line := <-lr.Ch:
			log.Printf("Got line from linereader: %v\n", line)
			if sentence, valid := validateNMEAChecksum(line); valid {
				log.Printf("Valid sentence %s on %s:%d\n", sentence, config.Name, config.Baud)
				return true, nil
			}
		case <-time.After(time.Second * 2):
			log.Printf("timeout reached on %s:%d\n", config.Name, config.Baud)
			return false, nil
		}
	}
}

func findGPS() *serial.Config {
	// ports and baud rates are listed in the order they should be tried
	ports := []string{ "/dev/ttyAMA0", "/dev/ttyACM0", "/dev/ttyUSB0" }
	rates := []int{ 38400, 9600, 4800 }

	for _, port := range ports {
		for _, rate := range rates {
			config := &serial.Config{Name: port, Baud: rate}
			if valid, err := detectGPS(config); valid { return config } else {
				if err != nil { log.Printf("Error detecting GPS: %v\n", err) }
			}
		}
	}
	return nil
}

func changeGPSBaudRate(config *serial.Config, newRate int) error {
	if config.Baud == newRate {
		return nil
	}

	p, err := serial.OpenPort(serialConfig)
	if err != nil { return err }
	defer p.Close()

	baud_cfg := createChecksummedNMEASentence([]byte(fmt.Sprintf("PMTK251,%d", newRate))

	n, err := p.Write(baud_cfg)
	if err != nil { return err }

	config.Baud = newRate

	valid, err := detectGPS(config)
	if !valid {
		err = fmt.Errorf("Set GPS to new rate, but unable to detect it at that new rate!")
	}
	return err
}

// for the Adafruit Ultimate GPS Hat (https://www.adafruit.com/products/2324)
// MT3339 chipset
func initUltimateGPS() error {

	// module is attached via serial UART, shows up as /dev/ttyAMA0 on rpi
	device := "/dev/ttyAMA0"
	log.Printf("Using %s for GPS\n", device)

	serialConfig := findGPS()
	if serialConfig == nil {
		return fmt.Errorf("Couldn't find gps module anywhere!  We looked!")
	}

	if serialConfig.Baud != 38400 {
		changeGPSBaudRate(serialConfig, 38400)
	}

	go gpsSerialReader(serialConfig)

	return nil
}

// goroutine which scans for incoming sentences (which are newline terminated) and sends them downstream for processing
func gpsSerialReader(serialConfig *serial.Config) {
	p, err := serial.OpenPort(serialConfig)
	log.Printf("Opening GPS on %s at %dbaud\n", serialConfig.Name, serialConfig.Baud)
	if err != nil {
		log.Printf("Error opening serial port: %v", err)
		log.Printf("  GPS Serial Reader routine is terminating.\n")
		return
	}
	defer p.Close()

	scanner := bufio.NewScanner(p)

	for scanner.Scan() {
		line := scanner.Text()
		//log.Printf("gps data: %s\n", line)

		processNMEASentence(line)
	}
	if err := scanner.Err(); err != nil {
		log.Printf("Error reading serial data: %v\n", err)
	}
}
<commit_msg>fixes<commit_after>package gps

import (
	"fmt"
	"log"
	"bufio"
	"time"

	"github.com/tarm/serial"
	"github.com/mitchellh/go-linereader"
)

func InitGPS() {
	log.Printf("In gps.InitGPS()\n")

	// eventually I would like to come up with a reliable autodetection scheme for different types of gps.
	// for now I'll just have entry points into different configurations that get uncommented here

	err := initUltimateGPS()
	if err != nil {
		log.Printf("Error initializing gps: %v\n", err)
	}
}

// this works based on a channel/goroutine based timeout pattern
// GPS should provide some valid sentence at least once per second.
// If I don't receive something in two seconds, this probably isn't a valid config
func detectGPS(config *serial.Config) (bool, error) {
	p, err := serial.OpenPort(config)
	if err != nil { return false, err }
	defer p.Close()

	lr := linereader.New(p)
	lr.Timeout = time.Second * 2

	for {
		select {
		case line := <-lr.Ch:
			log.Printf("Got line from linereader: %v\n", line)
			if sentence, valid := validateNMEAChecksum(line); valid {
				log.Printf("Valid sentence %s on %s:%d\n", sentence, config.Name, config.Baud)
				return true, nil
			}
		case <-time.After(time.Second * 2):
			log.Printf("timeout reached on %s:%d\n", config.Name, config.Baud)
			return false, nil
		}
	}
}

func findGPS() *serial.Config {
	// ports and baud rates are listed in the order they should be tried
	ports := []string{ "/dev/ttyAMA0", "/dev/ttyACM0", "/dev/ttyUSB0" }
	rates := []int{ 38400, 9600, 4800 }

	for _, port := range ports {
		for _, rate := range rates {
			config := &serial.Config{Name: port, Baud: rate}
			if valid, err := detectGPS(config); valid {
				return config
			} else {
				if err != nil {
					log.Printf("Error detecting GPS: %v\n", err)
				}
			}
		}
	}
	return nil
}

func changeGPSBaudRate(config *serial.Config, newRate int) error {
	if config.Baud == newRate {
		return nil
	}

	p, err := serial.OpenPort(config)
	if err != nil { return err }
	defer p.Close()

	baud_cfg := createChecksummedNMEASentence([]byte(fmt.Sprintf("PMTK251,%d", newRate)))

	n, err := p.Write(baud_cfg)
	if err != nil { return err }

	config.Baud = newRate

	valid, err := detectGPS(config)
	if !valid {
		err = fmt.Errorf("Set GPS to new rate, but unable to detect it at that new rate!")
	}
	return err
}

// for the Adafruit Ultimate GPS Hat (https://www.adafruit.com/products/2324)
// MT3339 chipset
func initUltimateGPS() error {

	// module is attached via serial UART, shows up as /dev/ttyAMA0 on rpi
	device := "/dev/ttyAMA0"
	log.Printf("Using %s for GPS\n", device)

	serialConfig := findGPS()
	if serialConfig == nil {
		return fmt.Errorf("Couldn't find gps module anywhere!  We looked!")
	}

	if serialConfig.Baud != 38400 {
		changeGPSBaudRate(serialConfig, 38400)
	}

	go gpsSerialReader(serialConfig)

	return nil
}

// goroutine which scans for incoming sentences (which are newline terminated) and sends them downstream for processing
func gpsSerialReader(serialConfig *serial.Config) {
	p, err := serial.OpenPort(serialConfig)
	log.Printf("Opening GPS on %s at %dbaud\n", serialConfig.Name, serialConfig.Baud)
	if err != nil {
		log.Printf("Error opening serial port: %v", err)
		log.Printf("  GPS Serial Reader routine is terminating.\n")
		return
	}
	defer p.Close()

	scanner := bufio.NewScanner(p)

	for scanner.Scan() {
		line := scanner.Text()
		//log.Printf("gps data: %s\n", line)

		processNMEASentence(line)
	}
	if err := scanner.Err(); err != nil {
		log.Printf("Error reading serial data: %v\n", err)
	}
}
<|endoftext|>


<commit_before>package filer

import (
	"context"
	"errors"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/viant/ptrie"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	ErrUnsupportedListDirectoryPrefixed = errors.New("unsupported directory prefix listing")
	ErrKvNotImplemented                 = errors.New("kv not implemented yet")
	ErrKvNotFound                       = errors.New("kv: not found")

	_ = VirtualFilerStore(&FilerStoreWrapper{})
)

type FilerStore interface {
	// GetName gets the name to locate the configuration in filer.toml file
	GetName() string
	// Initialize initializes the file store
	Initialize(configuration util.Configuration, prefix string) error
	InsertEntry(context.Context, *Entry) error
	UpdateEntry(context.Context, *Entry) (err error)
	// err == filer_pb.ErrNotFound if not found
	FindEntry(context.Context, util.FullPath) (entry *Entry, err error)
	DeleteEntry(context.Context, util.FullPath) (err error)
	DeleteFolderChildren(context.Context, util.FullPath) (err error)
	ListDirectoryEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int) ([]*Entry, error)
	ListDirectoryPrefixedEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) ([]*Entry, error)

	BeginTransaction(ctx context.Context) (context.Context, error)
	CommitTransaction(ctx context.Context) error
	RollbackTransaction(ctx context.Context) error

	KvPut(ctx context.Context, key []byte, value []byte) (err error)
	KvGet(ctx context.Context, key []byte) (value []byte, err error)
	KvDelete(ctx context.Context, key []byte) (err error)

	Shutdown()
}

type VirtualFilerStore interface {
	FilerStore
	DeleteHardLink(ctx context.Context, hardLinkId HardLinkId) error
	DeleteOneEntry(ctx context.Context, entry *Entry) error
}

type FilerStoreWrapper struct {
	defaultStore FilerStore
	pathToStore  ptrie.Trie
}

func NewFilerStoreWrapper(store FilerStore) *FilerStoreWrapper {
	if innerStore, ok := store.(*FilerStoreWrapper); ok {
		return innerStore
	}
	return &FilerStoreWrapper{
		defaultStore: store,
		pathToStore:  ptrie.New(),
	}
}

func (fsw *FilerStoreWrapper) addStore(path string, store FilerStore) {
	fsw.pathToStore.Put([]byte(path), store)
}

func (fsw *FilerStoreWrapper) getActualStore(path util.FullPath) FilerStore {
	if path == "" {
		return fsw.defaultStore
	}
	if store, found := fsw.pathToStore.Get([]byte(path)); found {
		return store.(FilerStore)
	}
	return fsw.defaultStore
}

func (fsw *FilerStoreWrapper) GetName() string {
	return fsw.getActualStore("").GetName()
}

func (fsw *FilerStoreWrapper) Initialize(configuration util.Configuration, prefix string) error {
	return fsw.getActualStore("").Initialize(configuration, prefix)
}

func (fsw *FilerStoreWrapper) InsertEntry(ctx context.Context, entry *Entry) error {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "insert").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "insert").Observe(time.Since(start).Seconds())
	}()

	filer_pb.BeforeEntrySerialization(entry.Chunks)
	if entry.Mime == "application/octet-stream" {
		entry.Mime = ""
	}

	if err := fsw.handleUpdateToHardLinks(ctx, entry); err != nil {
		return err
	}

	glog.V(4).Infof("InsertEntry %s", entry.FullPath)
	return actualStore.InsertEntry(ctx, entry)
}

func (fsw *FilerStoreWrapper) UpdateEntry(ctx context.Context, entry *Entry) error {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "update").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "update").Observe(time.Since(start).Seconds())
	}()

	filer_pb.BeforeEntrySerialization(entry.Chunks)
	if entry.Mime == "application/octet-stream" {
		entry.Mime = ""
	}

	if err := fsw.handleUpdateToHardLinks(ctx, entry); err != nil {
		return err
	}

	glog.V(4).Infof("UpdateEntry %s", entry.FullPath)
	return actualStore.UpdateEntry(ctx, entry)
}

func (fsw *FilerStoreWrapper) FindEntry(ctx context.Context, fp util.FullPath) (entry *Entry, err error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "find").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "find").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("FindEntry %s", fp)
	entry, err = actualStore.FindEntry(ctx, fp)
	if err != nil {
		return nil, err
	}

	fsw.maybeReadHardLink(ctx, entry)

	filer_pb.AfterEntryDeserialization(entry.Chunks)
	return
}

func (fsw *FilerStoreWrapper) DeleteEntry(ctx context.Context, fp util.FullPath) (err error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "delete").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "delete").Observe(time.Since(start).Seconds())
	}()

	existingEntry, findErr := fsw.FindEntry(ctx, fp)
	if findErr == filer_pb.ErrNotFound {
		return nil
	}
	if len(existingEntry.HardLinkId) != 0 {
		// remove hard link
		glog.V(4).Infof("DeleteHardLink %s", existingEntry.FullPath)
		if err = fsw.DeleteHardLink(ctx, existingEntry.HardLinkId); err != nil {
			return err
		}
	}

	glog.V(4).Infof("DeleteEntry %s", fp)
	return actualStore.DeleteEntry(ctx, fp)
}

func (fsw *FilerStoreWrapper) DeleteOneEntry(ctx context.Context, existingEntry *Entry) (err error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "delete").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "delete").Observe(time.Since(start).Seconds())
	}()

	if len(existingEntry.HardLinkId) != 0 {
		// remove hard link
		glog.V(4).Infof("DeleteHardLink %s", existingEntry.FullPath)
		if err = fsw.DeleteHardLink(ctx, existingEntry.HardLinkId); err != nil {
			return err
		}
	}

	glog.V(4).Infof("DeleteOneEntry %s", existingEntry.FullPath)
	return actualStore.DeleteEntry(ctx, existingEntry.FullPath)
}

func (fsw *FilerStoreWrapper) DeleteFolderChildren(ctx context.Context, fp util.FullPath) (err error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "deleteFolderChildren").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "deleteFolderChildren").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("DeleteFolderChildren %s", fp)
	return actualStore.DeleteFolderChildren(ctx, fp)
}

func (fsw *FilerStoreWrapper) ListDirectoryEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int) ([]*Entry, error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "list").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "list").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("ListDirectoryEntries %s from %s limit %d", dirPath, startFileName, limit)
	entries, err := actualStore.ListDirectoryEntries(ctx, dirPath, startFileName, includeStartFile, limit)
	if err != nil {
		return nil, err
	}
	for _, entry := range entries {
		fsw.maybeReadHardLink(ctx, entry)
		filer_pb.AfterEntryDeserialization(entry.Chunks)
	}
	return entries, err
}

func (fsw *FilerStoreWrapper) ListDirectoryPrefixedEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) ([]*Entry, error) {
	actualStore := fsw.getActualStore("")
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "prefixList").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "prefixList").Observe(time.Since(start).Seconds())
	}()
	glog.V(4).Infof("ListDirectoryPrefixedEntries %s from %s prefix %s limit %d", dirPath, startFileName, prefix, limit)
	entries, err := actualStore.ListDirectoryPrefixedEntries(ctx, dirPath, startFileName, includeStartFile, limit, prefix)
	if err == ErrUnsupportedListDirectoryPrefixed {
		entries, err = fsw.prefixFilterEntries(ctx, dirPath, startFileName, includeStartFile, limit, prefix)
	}
	if err != nil {
		return nil, err
	}
	for _, entry := range entries {
		fsw.maybeReadHardLink(ctx, entry)
		filer_pb.AfterEntryDeserialization(entry.Chunks)
	}
	return entries, nil
}

func (fsw *FilerStoreWrapper) prefixFilterEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) (entries []*Entry, err error) {
	actualStore := fsw.getActualStore("")
	entries, err = actualStore.ListDirectoryEntries(ctx, dirPath, startFileName, includeStartFile, limit)
	if err != nil {
		return nil, err
	}

	if prefix == "" {
		return
	}

	count := 0
	var lastFileName string
	notPrefixed := entries
	entries = nil
	for count < limit && len(notPrefixed) > 0 {
		for _, entry := range notPrefixed {
			lastFileName = entry.Name()
			if strings.HasPrefix(entry.Name(), prefix) {
				count++
				entries = append(entries, entry)
				if count >= limit {
					break
				}
			}
		}
		if count < limit {
			notPrefixed, err = actualStore.ListDirectoryEntries(ctx, dirPath, lastFileName, false, limit)
			if err != nil {
				return
			}
		}
	}
	return
}

func (fsw *FilerStoreWrapper) BeginTransaction(ctx context.Context) (context.Context, error) {
	return fsw.getActualStore("").BeginTransaction(ctx)
}

func (fsw *FilerStoreWrapper) CommitTransaction(ctx context.Context) error {
	return fsw.getActualStore("").CommitTransaction(ctx)
}

func (fsw *FilerStoreWrapper) RollbackTransaction(ctx context.Context) error {
	return fsw.getActualStore("").RollbackTransaction(ctx)
}

func (fsw *FilerStoreWrapper) Shutdown() {
	fsw.getActualStore("").Shutdown()
}

func (fsw *FilerStoreWrapper) KvPut(ctx context.Context, key []byte, value []byte) (err error) {
	return fsw.getActualStore("").KvPut(ctx, key, value)
}
func (fsw *FilerStoreWrapper) KvGet(ctx context.Context, key []byte) (value []byte, err error) {
	return fsw.getActualStore("").KvGet(ctx, key)
}
func (fsw *FilerStoreWrapper) KvDelete(ctx context.Context, key []byte) (err error) {
	return fsw.getActualStore("").KvDelete(ctx, key)
}
<commit_msg>filer: use store by path<commit_after>package filer

import (
	"context"
	"errors"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/viant/ptrie"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	ErrUnsupportedListDirectoryPrefixed = errors.New("unsupported directory prefix listing")
	ErrKvNotImplemented                 = errors.New("kv not implemented yet")
	ErrKvNotFound                       = errors.New("kv: not found")

	_ = VirtualFilerStore(&FilerStoreWrapper{})
)

type FilerStore interface {
	// GetName gets the name to locate the configuration in filer.toml file
	GetName() string
	// Initialize initializes the file store
	Initialize(configuration util.Configuration, prefix string) error
	InsertEntry(context.Context, *Entry) error
	UpdateEntry(context.Context, *Entry) (err error)
	// err == filer_pb.ErrNotFound if not found
	FindEntry(context.Context, util.FullPath) (entry *Entry, err error)
	DeleteEntry(context.Context, util.FullPath) (err error)
	DeleteFolderChildren(context.Context, util.FullPath) (err error)
	ListDirectoryEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int) ([]*Entry, error)
	ListDirectoryPrefixedEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) ([]*Entry, error)

	BeginTransaction(ctx context.Context) (context.Context, error)
	CommitTransaction(ctx context.Context) error
	RollbackTransaction(ctx context.Context) error

	KvPut(ctx context.Context, key []byte, value []byte) (err error)
	KvGet(ctx context.Context, key []byte) (value []byte, err error)
	KvDelete(ctx context.Context, key []byte) (err error)

	Shutdown()
}

type VirtualFilerStore interface {
	FilerStore
	DeleteHardLink(ctx context.Context, hardLinkId HardLinkId) error
	DeleteOneEntry(ctx context.Context, entry *Entry) error
}

type FilerStoreWrapper struct {
	defaultStore FilerStore
	pathToStore  ptrie.Trie
}

func NewFilerStoreWrapper(store FilerStore) *FilerStoreWrapper {
	if innerStore, ok := store.(*FilerStoreWrapper); ok {
		return innerStore
	}
	return &FilerStoreWrapper{
		defaultStore: store,
		pathToStore:  ptrie.New(),
	}
}

func (fsw *FilerStoreWrapper) addStore(path string, store FilerStore) {
	fsw.pathToStore.Put([]byte(path), store)
}

func (fsw *FilerStoreWrapper) getActualStore(path util.FullPath) FilerStore {
	if path == "" {
		return fsw.defaultStore
	}
	if store, found := fsw.pathToStore.Get([]byte(path)); found {
		return store.(FilerStore)
	}
	return fsw.defaultStore
}

func (fsw *FilerStoreWrapper) GetName() string {
	return fsw.getActualStore("").GetName()
}

func (fsw *FilerStoreWrapper) Initialize(configuration util.Configuration, prefix string) error {
	return fsw.getActualStore("").Initialize(configuration, prefix)
}

func (fsw *FilerStoreWrapper) InsertEntry(ctx context.Context, entry *Entry) error {
	actualStore := fsw.getActualStore(entry.FullPath)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "insert").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "insert").Observe(time.Since(start).Seconds())
	}()

	filer_pb.BeforeEntrySerialization(entry.Chunks)
	if entry.Mime == "application/octet-stream" {
		entry.Mime = ""
	}

	if err := fsw.handleUpdateToHardLinks(ctx, entry); err != nil {
		return err
	}

	glog.V(4).Infof("InsertEntry %s", entry.FullPath)
	return actualStore.InsertEntry(ctx, entry)
}

func (fsw *FilerStoreWrapper) UpdateEntry(ctx context.Context, entry *Entry) error {
	actualStore := fsw.getActualStore(entry.FullPath)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "update").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "update").Observe(time.Since(start).Seconds())
	}()

	filer_pb.BeforeEntrySerialization(entry.Chunks)
	if entry.Mime == "application/octet-stream" {
		entry.Mime = ""
	}

	if err := fsw.handleUpdateToHardLinks(ctx, entry); err != nil {
		return err
	}

	glog.V(4).Infof("UpdateEntry %s", entry.FullPath)
	return actualStore.UpdateEntry(ctx, entry)
}

func (fsw *FilerStoreWrapper) FindEntry(ctx context.Context, fp util.FullPath) (entry *Entry, err error) {
	actualStore := fsw.getActualStore(fp)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "find").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "find").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("FindEntry %s", fp)
	entry, err = actualStore.FindEntry(ctx, fp)
	if err != nil {
		return nil, err
	}

	fsw.maybeReadHardLink(ctx, entry)

	filer_pb.AfterEntryDeserialization(entry.Chunks)
	return
}

func (fsw *FilerStoreWrapper) DeleteEntry(ctx context.Context, fp util.FullPath) (err error) {
	actualStore := fsw.getActualStore(fp)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "delete").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "delete").Observe(time.Since(start).Seconds())
	}()

	existingEntry, findErr := fsw.FindEntry(ctx, fp)
	if findErr == filer_pb.ErrNotFound {
		return nil
	}
	if len(existingEntry.HardLinkId) != 0 {
		// remove hard link
		glog.V(4).Infof("DeleteHardLink %s", existingEntry.FullPath)
		if err = fsw.DeleteHardLink(ctx, existingEntry.HardLinkId); err != nil {
			return err
		}
	}

	glog.V(4).Infof("DeleteEntry %s", fp)
	return actualStore.DeleteEntry(ctx, fp)
}

func (fsw *FilerStoreWrapper) DeleteOneEntry(ctx context.Context, existingEntry *Entry) (err error) {
	actualStore := fsw.getActualStore(existingEntry.FullPath)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "delete").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "delete").Observe(time.Since(start).Seconds())
	}()

	if len(existingEntry.HardLinkId) != 0 {
		// remove hard link
		glog.V(4).Infof("DeleteHardLink %s", existingEntry.FullPath)
		if err = fsw.DeleteHardLink(ctx, existingEntry.HardLinkId); err != nil {
			return err
		}
	}

	glog.V(4).Infof("DeleteOneEntry %s", existingEntry.FullPath)
	return actualStore.DeleteEntry(ctx, existingEntry.FullPath)
}

func (fsw *FilerStoreWrapper) DeleteFolderChildren(ctx context.Context, fp util.FullPath) (err error) {
	actualStore := fsw.getActualStore(fp)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "deleteFolderChildren").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "deleteFolderChildren").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("DeleteFolderChildren %s", fp)
	return actualStore.DeleteFolderChildren(ctx, fp)
}

func (fsw *FilerStoreWrapper) ListDirectoryEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int) ([]*Entry, error) {
	actualStore := fsw.getActualStore(dirPath)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "list").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "list").Observe(time.Since(start).Seconds())
	}()

	glog.V(4).Infof("ListDirectoryEntries %s from %s limit %d", dirPath, startFileName, limit)
	entries, err := actualStore.ListDirectoryEntries(ctx, dirPath, startFileName, includeStartFile, limit)
	if err != nil {
		return nil, err
	}
	for _, entry := range entries {
		fsw.maybeReadHardLink(ctx, entry)
		filer_pb.AfterEntryDeserialization(entry.Chunks)
	}
	return entries, err
}

func (fsw *FilerStoreWrapper) ListDirectoryPrefixedEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) ([]*Entry, error) {
	actualStore := fsw.getActualStore(dirPath)
	stats.FilerStoreCounter.WithLabelValues(actualStore.GetName(), "prefixList").Inc()
	start := time.Now()
	defer func() {
		stats.FilerStoreHistogram.WithLabelValues(actualStore.GetName(), "prefixList").Observe(time.Since(start).Seconds())
	}()
	glog.V(4).Infof("ListDirectoryPrefixedEntries %s from %s prefix %s limit %d", dirPath, startFileName, prefix, limit)
	entries, err := actualStore.ListDirectoryPrefixedEntries(ctx, dirPath, startFileName, includeStartFile, limit, prefix)
	if err == ErrUnsupportedListDirectoryPrefixed {
		entries, err = fsw.prefixFilterEntries(ctx, dirPath, startFileName, includeStartFile, limit, prefix)
	}
	if err != nil {
		return nil, err
	}
	for _, entry := range entries {
		fsw.maybeReadHardLink(ctx, entry)
		filer_pb.AfterEntryDeserialization(entry.Chunks)
	}
	return entries, nil
}

func (fsw *FilerStoreWrapper) prefixFilterEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int, prefix string) (entries []*Entry, err error) {
	actualStore := fsw.getActualStore(dirPath)
	entries, err = actualStore.ListDirectoryEntries(ctx, dirPath, startFileName, includeStartFile, limit)
	if err != nil {
		return nil, err
	}

	if prefix == "" {
		return
	}

	count := 0
	var lastFileName string
	notPrefixed := entries
	entries = nil
	for count < limit && len(notPrefixed) > 0 {
		for _, entry := range notPrefixed {
			lastFileName = entry.Name()
			if strings.HasPrefix(entry.Name(), prefix) {
				count++
				entries = append(entries, entry)
				if count >= limit {
					break
				}
			}
		}
		if count < limit {
			notPrefixed, err = actualStore.ListDirectoryEntries(ctx, dirPath, lastFileName, false, limit)
			if err != nil {
				return
			}
		}
	}
	return
}

func (fsw *FilerStoreWrapper) BeginTransaction(ctx context.Context) (context.Context, error) {
	return fsw.getActualStore("").BeginTransaction(ctx)
}

func (fsw *FilerStoreWrapper) CommitTransaction(ctx context.Context) error {
	return fsw.getActualStore("").CommitTransaction(ctx)
}

func (fsw *FilerStoreWrapper) RollbackTransaction(ctx context.Context) error {
	return fsw.getActualStore("").RollbackTransaction(ctx)
}

func (fsw *FilerStoreWrapper) Shutdown() {
	fsw.getActualStore("").Shutdown()
}

func (fsw *FilerStoreWrapper) KvPut(ctx context.Context, key []byte, value []byte) (err error) {
	return fsw.getActualStore("").KvPut(ctx, key, value)
}
func (fsw *FilerStoreWrapper) KvGet(ctx context.Context, key []byte) (value []byte, err error) {
	return fsw.getActualStore("").KvGet(ctx, key)
}
func (fsw *FilerStoreWrapper) KvDelete(ctx context.Context, key []byte) (err error) {
	return fsw.getActualStore("").KvDelete(ctx, key)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"image"
	"image/color"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"log"
	"os"
)

func checkerror(err error) {
	if err != nil {
		log.Fatalln("[ERROR]", err)
	}
}

func invertcolor(somecolor uint32, somealpha uint32) uint32 {
	return somealpha - somecolor
}

var (
	red        = flag.Int("red", 0, "red percentage")
	green      = flag.Int("green", 0, "green percentage")
	blue       = flag.Int("blue", 0, "blue percentage")
	inputfile  = flag.String("input", "", "blue percentage")
	outputfile = flag.String("output", "", "blue percentage")
)

func outline(source image.Image) image.Image {
	bounds := source.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y; y <= bounds.Max.Y; y++ {
		r, g, b, a := source.At(bounds.Min.X+1, y).RGBA()
		target.Set(bounds.Min.X, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})

		r, g, b, a = source.At(bounds.Max.X-1, y).RGBA()
		target.Set(bounds.Max.X, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
	}

	for x := bounds.Min.X + 1; x < bounds.Max.X; x++ {
		r, g, b, a := source.At(x, bounds.Min.Y+1).RGBA()
		target.Set(x, bounds.Min.Y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})

		r, g, b, a = source.At(x, bounds.Max.Y-1).RGBA()
		target.Set(x, bounds.Max.Y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
	}

	for y := bounds.Min.Y + 1; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X + 1; x < bounds.Max.X; x++ {
			r, g, b, a := source.At(x, y).RGBA()
			target.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
		}
	}

	return target
}

func mini(source image.Image) image.Image {
	bounds := source.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	yboundary := float64(bounds.Max.Y / 3.0)
	y3 := float64(bounds.Max.Y / 2.0 * 3.0)
	h := float64(bounds.Max.Y)
	times := 30.0

	for y := bounds.Min.Y + 1; y < bounds.Max.Y-1; y++ {
		for x := bounds.Min.X + 1; x < bounds.Max.X-1; x++ {
			r, g, b, _ := source.At(x, y).RGBA()

			var num float64

			if float64(y) < yboundary {
				num = 9.0 * times / h / h * (float64(y) - yboundary) * (float64(y) - yboundary)
			} else if float64(y) < y3 {
				num = 0.0
			} else {
				num = 9.0 * times / h / h * (float64(y) - y3) * (float64(y) - y3)
			}

			target.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(num)})
		}
	}

	return target
}

func smooth(m image.Image) image.Image {
	bounds := m.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y + 1; y <= bounds.Max.Y-1; y++ {
		for x := bounds.Min.X + 1; x <= bounds.Max.X-1; x++ {
			r, g, b, a := m.At(x, y).RGBA()

			r1, g1, b1, _ := m.At(x, y-1).RGBA()
			r2, g2, b2, _ := m.At(x-1, y).RGBA()
			r3, g3, b3, _ := m.At(x+1, y).RGBA()
			r4, g4, b4, _ := m.At(x, y+1).RGBA()

			r0 := (r1 + r2 + r3 + r4 + (2.0 * r)) / 6.0
			g0 := (g1 + g2 + g3 + g4 + (2.0 * g)) / 6.0
			b0 := (b1 + b2 + b3 + b4 + (2.0 * b)) / 6.0

			target.Set(x, y, color.RGBA{uint8(r0 / 256), uint8(g0 / 256), uint8(b0 / 256), uint8(a / 256)})
		}
	}

	return target
}

func colour(m image.Image) image.Image {
	bounds := m.Bounds()

	rm := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			r, g, b, a := m.At(x, y).RGBA()

			r = invertcolor(r, a)
			g = invertcolor(g, a)
			b = invertcolor(b, a)

			//r = r * uint32(*red)
			//g = g * uint32(*green)
			//b = b * uint32(*blue)

			rm.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
		}
	}

	return rm
}

func main() {
	flag.Parse()

	file, err := os.Open(*inputfile)
	checkerror(err)

	tofile, err := os.Create(*outputfile)
	checkerror(err)

	defer file.Close()
	defer tofile.Close()

	m, _, err := image.Decode(file)

	// rm := colour(m)
	rm := smooth(m)
	rm = outline(rm)
	// rm = mini(rm)

	jpeg.Encode(tofile, rm, &jpeg.Options{jpeg.DefaultQuality})
}
<commit_msg>using resize<commit_after>package main

import (
	"flag"
	"github.com/nfnt/resize"
	"image"
	"image/color"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"log"
	"os"
)

func checkerror(err error) {
	if err != nil {
		log.Fatalln("[ERROR]", err)
	}
}

func invertcolor(somecolor uint32, somealpha uint32) uint32 {
	return somealpha - somecolor
}

var (
	red        = flag.Int("red", 0, "red percentage")
	green      = flag.Int("green", 0, "green percentage")
	blue       = flag.Int("blue", 0, "blue percentage")
	inputfile  = flag.String("input", "", "blue percentage")
	outputfile = flag.String("output", "", "blue percentage")
)

func outline(source image.Image) image.Image {
	bounds := source.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y; y <= bounds.Max.Y; y++ {
		r, g, b, a := source.At(bounds.Min.X+1, y).RGBA()
		target.Set(bounds.Min.X, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})

		r, g, b, a = source.At(bounds.Max.X-1, y).RGBA()
		target.Set(bounds.Max.X, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
	}

	for x := bounds.Min.X + 1; x < bounds.Max.X; x++ {
		r, g, b, a := source.At(x, bounds.Min.Y+1).RGBA()
		target.Set(x, bounds.Min.Y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})

		r, g, b, a = source.At(x, bounds.Max.Y-1).RGBA()
		target.Set(x, bounds.Max.Y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
	}

	for y := bounds.Min.Y + 1; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X + 1; x < bounds.Max.X; x++ {
			r, g, b, a := source.At(x, y).RGBA()
			target.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
		}
	}

	return target
}

func mini(source image.Image) image.Image {
	bounds := source.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	yboundary := float64(bounds.Max.Y / 3.0)
	y3 := float64(bounds.Max.Y / 2.0 * 3.0)
	h := float64(bounds.Max.Y)
	times := 30.0

	for y := bounds.Min.Y + 1; y < bounds.Max.Y-1; y++ {
		for x := bounds.Min.X + 1; x < bounds.Max.X-1; x++ {
			r, g, b, _ := source.At(x, y).RGBA()

			var num float64

			if float64(y) < yboundary {
				num = 9.0 * times / h / h * (float64(y) - yboundary) * (float64(y) - yboundary)
			} else if float64(y) < y3 {
				num = 0.0
			} else {
				num = 9.0 * times / h / h * (float64(y) - y3) * (float64(y) - y3)
			}

			target.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(num)})
		}
	}

	return target
}

func smooth(m image.Image) image.Image {
	bounds := m.Bounds()

	target := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y + 1; y <= bounds.Max.Y-1; y++ {
		for x := bounds.Min.X + 1; x <= bounds.Max.X-1; x++ {
			r, g, b, a := m.At(x, y).RGBA()

			r1, g1, b1, _ := m.At(x, y-1).RGBA()
			r2, g2, b2, _ := m.At(x-1, y).RGBA()
			r3, g3, b3, _ := m.At(x+1, y).RGBA()
			r4, g4, b4, _ := m.At(x, y+1).RGBA()

			r0 := (r1 + r2 + r3 + r4 + (2.0 * r)) / 6.0
			g0 := (g1 + g2 + g3 + g4 + (2.0 * g)) / 6.0
			b0 := (b1 + b2 + b3 + b4 + (2.0 * b)) / 6.0

			target.Set(x, y, color.RGBA{uint8(r0 / 256), uint8(g0 / 256), uint8(b0 / 256), uint8(a / 256)})
		}
	}

	return target
}

func colour(m image.Image) image.Image {
	bounds := m.Bounds()

	rm := image.NewRGBA(image.Rect(bounds.Min.Y, bounds.Min.X, bounds.Max.X, bounds.Max.Y))

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			r, g, b, a := m.At(x, y).RGBA()

			r = invertcolor(r, a)
			g = invertcolor(g, a)
			b = invertcolor(b, a)

			//r = r * uint32(*red)
			//g = g * uint32(*green)
			//b = b * uint32(*blue)

			rm.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
		}
	}

	return rm
}

func main() {
	flag.Parse()

	file, err := os.Open(*inputfile)
	checkerror(err)

	tofile, err := os.Create(*outputfile)
	checkerror(err)

	defer file.Close()
	defer tofile.Close()

	m, _, err := image.Decode(file)

	// rm := colour(m)
	// rm := smooth(m)
	// rm = outline(rm)
	// rm = mini(rm)

	rm := resize.Resize(250, 250, m, resize.Lanczos3)

	jpeg.Encode(tofile, rm, &jpeg.Options{jpeg.DefaultQuality})
}
<|endoftext|>


<commit_before>package utils

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// UploadFile used to upload file by S3 pre-signed URL
func UploadFile(path, url string) int {
	log.Println("Uploading app ...")
	file, err := os.Open(path)
	if err != nil {
		log.Fatal("Failed to get file for upload because of: ", err.Error())
	}
	info, err := file.Stat()
	if err != nil {
		log.Fatal("Failed to get info about file because of: ", err.Error())
	}
	client := &http.Client{}
	request, err := http.NewRequest("PUT", url, file)
	if err != nil {
		log.Fatal("Failed to create HTTP request because of: ", err.Error())
	}
	request.Header.Add("Content-Type", "application/octet-stream")
	request.ContentLength = info.Size()
	resp, err := client.Do(request)
	if err != nil {
		log.Fatal("Failed to upload file by S3 link because of: ", err.Error())
	}
	defer resp.Body.Close()
	var result int
	result = resp.StatusCode
	log.Println("Response code:", result)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Failed to get body of response because of: ", err.Error())
	}
	log.Println("Response body:", string(body))
	return result
}

// StringEndsWith check that string ends with specified substring
func StringEndsWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[len(original)-len(substring) : len(original)])
	return str == substring
}

// GetFilename returns file name from path string
func GetFilename(path string) string {
	if !strings.Contains(path, "/") {
		return path
	}
	pos := strings.LastIndex(path, "/")
	return string(path[pos+1:])
}
<commit_msg>Fix gofmt<commit_after>package utils

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// UploadFile used to upload file by S3 pre-signed URL
func UploadFile(path, url string) int {
	log.Println("Uploading app ...")
	file, err := os.Open(path)
	if err != nil {
		log.Fatal("Failed to get file for upload because of: ", err.Error())
	}
	info, err := file.Stat()
	if err != nil {
		log.Fatal("Failed to get info about file because of: ", err.Error())
	}
	client := &http.Client{}
	request, err := http.NewRequest("PUT", url, file)
	if err != nil {
		log.Fatal("Failed to create HTTP request because of: ", err.Error())
	}
	request.Header.Add("Content-Type", "application/octet-stream")
	request.ContentLength = info.Size()
	resp, err := client.Do(request)
	if err != nil {
		log.Fatal("Failed to upload file by S3 link because of: ", err.Error())
	}
	defer resp.Body.Close()
	var result int
	result = resp.StatusCode
	log.Println("Response code:", result)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Failed to get body of response because of: ", err.Error())
	}
	log.Println("Response body:", string(body))
	return result
}

// StringEndsWith check that string ends with specified substring
func StringEndsWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[len(original)-len(substring):])
	return str == substring
}

// GetFilename returns file name from path string
func GetFilename(path string) string {
	if !strings.Contains(path, "/") {
		return path
	}
	pos := strings.LastIndex(path, "/")
	return string(path[pos+1:])
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"os"
	"path/filepath"
	"runtime"
)

func CheckError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func CheckReturnCode(res int, mesg []byte) {
	if res >= 300 {
		log.Fatal(fmt.Sprintf("There was an issue with your http request: %d ; error message is: %s", res, mesg))
	}
}

func GetUsername() string {
	u := "unknown"
	osUser := ""

	switch runtime.GOOS {
	case "darwin", "linux":
		osUser = os.Getenv("USER")
	case "windows":
		osUser = os.Getenv("USERNAME")
	}

	if osUser != "" {
		u = osUser
	}

	return u
}

func GetHomeDir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("USERPROFILE")
	}
	return os.Getenv("HOME")
}

func GetBaseDir() string {
	baseDir := os.Getenv("MACHINE_DIR")
	if baseDir == "" {
		baseDir = GetHomeDir()
	}
	return baseDir
}

func GetConcertoDir() string {
	userName := GetUsername()
	if userName == "root" || Exists("/etc/concerto/client.xml") {
		return "/etc/concerto/"
	} else if userName == "Administrator" || Exists("c:\\concerto\\client.xml") || userName[len(userName)-1:] == "$" {
		return "c:\\concerto\\"
	} else {
		return filepath.Join(GetBaseDir(), ".concerto")
	}
}

func Exists(name string) bool {
	_, err := os.Stat(name)
	return !os.IsNotExist(err)
}
<commit_msg>fixed: raw HTML error from server.<commit_after>package utils

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
)

func CheckError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func CheckReturnCode(res int, mesg []byte) {
	if res >= 300 {
		// check if response is a web page.
		message := string(mesg[:])
		log.Debugf("Concerto API response: %s", message)

		webpageIdentified := "<html>"
		scrapResponse := "<title>(.*?)</title>"
		if strings.Contains(message, webpageIdentified) {

			re, err := regexp.Compile(scrapResponse)
			scrapped := re.FindStringSubmatch(message)

			if scrapped == nil || err != nil || len(scrapped) < 2 {
				// couldn't scrape, return generic error
				message = "Error executing operation"
			} else {
				// return scrapped response
				message = scrapped[1]
			}
		}
		// if it's not a web page, return raw message
		log.Fatal(fmt.Sprintf("There was an issue with your http request: status[%d] message [%s]", res, message))
	}
}

func GetUsername() string {
	u := "unknown"
	osUser := ""

	switch runtime.GOOS {
	case "darwin", "linux":
		osUser = os.Getenv("USER")
	case "windows":
		osUser = os.Getenv("USERNAME")
	}

	if osUser != "" {
		u = osUser
	}

	return u
}

func GetHomeDir() string {
	if runtime.GOOS == "windows" {
		return os.Getenv("USERPROFILE")
	}
	return os.Getenv("HOME")
}

func GetBaseDir() string {
	baseDir := os.Getenv("MACHINE_DIR")
	if baseDir == "" {
		baseDir = GetHomeDir()
	}
	return baseDir
}

func GetConcertoDir() string {
	userName := GetUsername()
	if userName == "root" || Exists("/etc/concerto/client.xml") {
		return "/etc/concerto/"
	} else if userName == "Administrator" || Exists("c:\\concerto\\client.xml") || userName[len(userName)-1:] == "$" {
		return "c:\\concerto\\"
	} else {
		return filepath.Join(GetBaseDir(), ".concerto")
	}
}

func Exists(name string) bool {
	_, err := os.Stat(name)
	return !os.IsNotExist(err)
}
<|endoftext|>


<commit_before>package utils

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

	"github.com/IBM/ubiquity/resources"

	"path"
	"strings"

	"bytes"
	"log"

	"github.com/gorilla/mux"
)

func ExtractErrorResponse(response *http.Response) error {
	errorResponse := resources.GenericResponse{}
	err := UnmarshalResponse(response, &errorResponse)
	if err != nil {
		return err
	}
	return fmt.Errorf("%s", errorResponse.Err)
}

func FormatURL(url string, entries ...string) string {
	base := url
	if !strings.HasSuffix(url, "/") {
		base = fmt.Sprintf("%s/", url)
	}
	suffix := ""
	for _, entry := range entries {
		suffix = path.Join(suffix, entry)
	}
	return fmt.Sprintf("%s%s", base, suffix)
}

func HttpExecute(httpClient *http.Client, logger *log.Logger, requestType string, requestURL string, rawPayload interface{}) (*http.Response, error) {
	payload, err := json.MarshalIndent(rawPayload, "", " ")
	if err != nil {
		logger.Printf("Internal error marshalling params %#v", err)
		return nil, fmt.Errorf("Internal error marshalling params")
	}

	request, err := http.NewRequest(requestType, requestURL, bytes.NewBuffer(payload))
	if err != nil {
		logger.Printf("Error in creating request %#v", err)
		return nil, fmt.Errorf("Error in creating request")
	}

	return httpClient.Do(request)
}

func ReadAndUnmarshal(object interface{}, dir string, fileName string) error {
	path := dir + string(os.PathSeparator) + fileName

	bytes, err := ReadFile(path)
	if err != nil {
		return err
	}

	err = json.Unmarshal(bytes, object)
	if err != nil {
		return err
	}

	return nil
}

func MarshalAndRecord(object interface{}, dir string, fileName string) error {
	MkDir(dir)
	path := dir + string(os.PathSeparator) + fileName

	bytes, err := json.MarshalIndent(object, "", " ")
	if err != nil {
		return err
	}

	return WriteFile(path, bytes)
}

func WriteResponse(w http.ResponseWriter, code int, object interface{}) {
	data, err := json.Marshal(object)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(code)
	fmt.Fprintf(w, string(data))
}

func Unmarshal(r *http.Request, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}

func UnmarshalResponse(r *http.Response, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}
func UnmarshalDataFromRequest(r *http.Request, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}

func ExtractVarsFromRequest(r *http.Request, varName string) string {
	return mux.Vars(r)[varName]
}

func ReadFile(path string) (content []byte, err error) {
	file, err := os.Open(path)
	if err != nil {
		return
	}
	defer file.Close()

	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return
	}
	content = bytes

	return
}

func WriteFile(path string, content []byte) error {
	err := ioutil.WriteFile(path, content, 0700)
	if err != nil {
		return err
	}

	return nil
}

func GetPath(paths []string) string {
	workDirectory, _ := os.Getwd()

	if len(paths) == 0 {
		return workDirectory
	}

	resultPath := workDirectory

	for _, path := range paths {
		resultPath += string(os.PathSeparator)
		resultPath += path
	}

	return resultPath
}

func Exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func MkDir(path string) error {
	var err error
	if _, err = os.Stat(path); os.IsNotExist(err) {
		err = os.MkdirAll(path, 0700)
		if err != nil {
			return err
		}
	}

	return err
}

func PrintResponse(f resources.FlexVolumeResponse) error {
	responseBytes, err := json.Marshal(f)
	if err != nil {
		return err
	}
	fmt.Printf("%s", string(responseBytes[:]))
	return nil
}

func SetupLogger(logPath string, loggerName string) (*log.Logger, *os.File) {
	logFile, err := os.OpenFile(path.Join(logPath, fmt.Sprintf("%s.log", loggerName)), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
	if err != nil {
		fmt.Printf("Failed to setup logger: %s\n", err.Error())
		return nil, nil
	}
	log.SetOutput(logFile)
	logger := log.New(io.MultiWriter(logFile, os.Stdout), fmt.Sprintf("%s: ", loggerName), log.Lshortfile|log.LstdFlags)
	return logger, logFile
}

func CloseLogs(logFile *os.File) {
	logFile.Sync()
	logFile.Close()
}

func SetupConfigDirectory(logger *log.Logger, executor Executor, configPath string) (string, error) {
	logger.Println("setupConfigPath start")
	defer logger.Println("setupConfigPath end")
	ubiquityConfigPath := path.Join(configPath, ".config")
	logger.Printf("User specified config path: %s", configPath)

	if _, err := executor.Stat(ubiquityConfigPath); os.IsNotExist(err) {
		args := []string{"mkdir", ubiquityConfigPath}
		_, err := executor.Execute("sudo", args)
		if err != nil {
			logger.Printf("Error creating directory")
			return "", err
		}

	}
	currentUser, err := user.Current()
	if err != nil {
		logger.Printf("Error determining current user: %s", err.Error())
		return "", err
	}

	args := []string{"chown", "-R", fmt.Sprintf("%s:%s", currentUser.Uid, currentUser.Gid), ubiquityConfigPath}
	_, err = executor.Execute("sudo", args)
	if err != nil {
		logger.Printf("Error setting permissions on config directory %s", ubiquityConfigPath)
		return "", err
	}
	return ubiquityConfigPath, nil
}
<commit_msg>Removed loggin to stdout<commit_after>package utils

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

	"github.com/IBM/ubiquity/resources"

	"path"
	"strings"

	"bytes"
	"log"

	"github.com/gorilla/mux"
)

func ExtractErrorResponse(response *http.Response) error {
	errorResponse := resources.GenericResponse{}
	err := UnmarshalResponse(response, &errorResponse)
	if err != nil {
		return err
	}
	return fmt.Errorf("%s", errorResponse.Err)
}

func FormatURL(url string, entries ...string) string {
	base := url
	if !strings.HasSuffix(url, "/") {
		base = fmt.Sprintf("%s/", url)
	}
	suffix := ""
	for _, entry := range entries {
		suffix = path.Join(suffix, entry)
	}
	return fmt.Sprintf("%s%s", base, suffix)
}

func HttpExecute(httpClient *http.Client, logger *log.Logger, requestType string, requestURL string, rawPayload interface{}) (*http.Response, error) {
	payload, err := json.MarshalIndent(rawPayload, "", " ")
	if err != nil {
		logger.Printf("Internal error marshalling params %#v", err)
		return nil, fmt.Errorf("Internal error marshalling params")
	}

	request, err := http.NewRequest(requestType, requestURL, bytes.NewBuffer(payload))
	if err != nil {
		logger.Printf("Error in creating request %#v", err)
		return nil, fmt.Errorf("Error in creating request")
	}

	return httpClient.Do(request)
}

func ReadAndUnmarshal(object interface{}, dir string, fileName string) error {
	path := dir + string(os.PathSeparator) + fileName

	bytes, err := ReadFile(path)
	if err != nil {
		return err
	}

	err = json.Unmarshal(bytes, object)
	if err != nil {
		return err
	}

	return nil
}

func MarshalAndRecord(object interface{}, dir string, fileName string) error {
	MkDir(dir)
	path := dir + string(os.PathSeparator) + fileName

	bytes, err := json.MarshalIndent(object, "", " ")
	if err != nil {
		return err
	}

	return WriteFile(path, bytes)
}

func WriteResponse(w http.ResponseWriter, code int, object interface{}) {
	data, err := json.Marshal(object)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(code)
	fmt.Fprintf(w, string(data))
}

func Unmarshal(r *http.Request, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}

func UnmarshalResponse(r *http.Response, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}
func UnmarshalDataFromRequest(r *http.Request, object interface{}) error {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, object)
	if err != nil {
		return err
	}

	return nil
}

func ExtractVarsFromRequest(r *http.Request, varName string) string {
	return mux.Vars(r)[varName]
}

func ReadFile(path string) (content []byte, err error) {
	file, err := os.Open(path)
	if err != nil {
		return
	}
	defer file.Close()

	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		return
	}
	content = bytes

	return
}

func WriteFile(path string, content []byte) error {
	err := ioutil.WriteFile(path, content, 0700)
	if err != nil {
		return err
	}

	return nil
}

func GetPath(paths []string) string {
	workDirectory, _ := os.Getwd()

	if len(paths) == 0 {
		return workDirectory
	}

	resultPath := workDirectory

	for _, path := range paths {
		resultPath += string(os.PathSeparator)
		resultPath += path
	}

	return resultPath
}

func Exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func MkDir(path string) error {
	var err error
	if _, err = os.Stat(path); os.IsNotExist(err) {
		err = os.MkdirAll(path, 0700)
		if err != nil {
			return err
		}
	}

	return err
}

func PrintResponse(f resources.FlexVolumeResponse) error {
	responseBytes, err := json.Marshal(f)
	if err != nil {
		return err
	}
	fmt.Printf("%s", string(responseBytes[:]))
	return nil
}

func SetupLogger(logPath string, loggerName string) (*log.Logger, *os.File) {
	logFile, err := os.OpenFile(path.Join(logPath, fmt.Sprintf("%s.log", loggerName)), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
	if err != nil {
		fmt.Printf("Failed to setup logger: %s\n", err.Error())
		return nil, nil
	}
	log.SetOutput(logFile)
	logger := log.New(io.MultiWriter(logFile), fmt.Sprintf("%s: ", loggerName), log.Lshortfile|log.LstdFlags)
	return logger, logFile
}

func CloseLogs(logFile *os.File) {
	logFile.Sync()
	logFile.Close()
}

func SetupConfigDirectory(logger *log.Logger, executor Executor, configPath string) (string, error) {
	logger.Println("setupConfigPath start")
	defer logger.Println("setupConfigPath end")
	ubiquityConfigPath := path.Join(configPath, ".config")
	logger.Printf("User specified config path: %s", configPath)

	if _, err := executor.Stat(ubiquityConfigPath); os.IsNotExist(err) {
		args := []string{"mkdir", ubiquityConfigPath}
		_, err := executor.Execute("sudo", args)
		if err != nil {
			logger.Printf("Error creating directory")
			return "", err
		}

	}
	currentUser, err := user.Current()
	if err != nil {
		logger.Printf("Error determining current user: %s", err.Error())
		return "", err
	}

	args := []string{"chown", "-R", fmt.Sprintf("%s:%s", currentUser.Uid, currentUser.Gid), ubiquityConfigPath}
	_, err = executor.Execute("sudo", args)
	if err != nil {
		logger.Printf("Error setting permissions on config directory %s", ubiquityConfigPath)
		return "", err
	}
	return ubiquityConfigPath, nil
}
<|endoftext|>