<commit_before>package kasia

import (
    "fmt"
    "reflect"
)

var cmp_map map[int]string

func init() {
    cmp_map = map[int]string{
        if_eq:    "==",
        if_ne:    "!=",
        if_lt:    "<",
        if_le:    "<=",
        if_gt:    ">",
        if_ge:    ">=",
    }
}

func revParse1Param(par interface{}) (ret string) {
    switch pv := par.(type) {
    case reflect.Value:
        ret += fmt.Sprint(pv.Interface())

    case []Element:
        ret += "\"" + revParse1(pv) + "\""

    case *VarFunElem:
        ret += revParse1VarFun(pv)

    default:
        ret += "!UNKNOWN_ARG!"
    }
    return
}

func revParse1VarFun(vf *VarFunElem) (ret string) {
    show_dot := false
    for vf != nil {
        switch pe := vf.name.(type) {
        case *reflect.StringValue:
            if show_dot {
                ret += "."
            }
            ret += pe.Get()

        case *reflect.IntValue:
            ret += fmt.Sprintf("[%d]", pe.Get())

        case nil:
            // Samowywolanie

        case []Element:
            ret += "[\"" + revParse1(pe) + "\"]"

        case *VarFunElem:
            ret += fmt.Sprintf("[%s]", revParse1VarFun(pe))

        default:
            ret += "!UNKNOWN_NAME!"
        }
        show_dot = true

        if vf.fun {
            ret += "("
            for ii := range vf.args {
                if ii != 0 {
                    ret += ", "
                }
                ret += revParse1Param(vf.args[ii])
            }
            ret += ")"
        }

        vf = vf.next
    }
    return
}

func revParse1(elems []Element) (ret string){
    for _, va := range elems {
        switch el := va.(type) {
        case *TxtElem:
            ret += el.txt

        case *VarFunElem:
            ret += "$"
            if !el.filt {
                ret += ":"
            }
            ret += "{" + revParse1VarFun(el)  + "}"

        case *IfElem:
            ret += "$if " + revParse1Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse1Param(el.arg2)
            }
            ret +=  ":"

        case *ElifElem:
            ret += "$elif " + revParse1Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse1Param(el.arg2)
            }
            ret +=  ":"

        case *ElseElem:
            ret += "$else:"

        case *EndElem:
            ret += "${end}"

        case *ForElem:
            inc := ""
            if el.iter_inc == 1 {
                inc = "+"
            }
            ret += fmt.Sprintf("$for %s%s, %s in %s:", el.iter, inc, el.val,
                revParse1VarFun(el.arg))

        default:
            ret += "!UNKNOWN ELEMENT!"
        }
    }
    return
}

func revParse2Param(par interface{}) (ret string) {
    switch pv := par.(type) {
    case reflect.Value:
        ret += fmt.Sprint(pv.Interface())

    case []Element:
        ret += "\"" + revParse2(pv) + "\""

    case *VarFunElem:
        ret += revParse2VarFun(pv)

    default:
        ret += "!UNKNOWN_ARG!"
    }
    return
}

func revParse2VarFun(vf *VarFunElem) (ret string) {
    show_dot := false
    for vf != nil {
        switch pe := vf.name.(type) {
        case *reflect.StringValue:
            if show_dot {
                ret += "."
            }
            ret += pe.Get()

        case *reflect.IntValue:
            ret += fmt.Sprintf("[%d]", pe.Get())

        case nil:
            // Samowywolanie

        case []Element:
            ret += "[\"" + revParse2(pe) + "\"]"

        case *VarFunElem:
            ret += fmt.Sprintf("[%s]", revParse2VarFun(pe))

        default:
            ret += "!UNKNOWN_NAME!"
        }
        show_dot = true

        if vf.fun {
            ret += "("
            for ii := range vf.args {
                if ii != 0 {
                    ret += ", "
                }
                ret += revParse2Param(vf.args[ii])
            }
            ret += ")"
        }

        vf = vf.next
    }
    return
}

func revParse2(elems []Element) (ret string) {
    for _, va := range elems {
        switch el := va.(type) {
        case *TxtElem:
            ret += el.txt

        case *VarFunElem:
            ret += "$"
            if !el.filt {
                ret += ":"
            }
            ret += "{" + revParse2VarFun(el)  + "}"

        case *IfElem:
            ret += "$if " + revParse2Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse2Param(el.arg2)
            }
            ret +=  ":"
            ret += revParse2(el.true_block)
            if el.false_block != nil {
                ret += "$else:" + revParse2(el.false_block)
            }
            ret += "${end}"

        case *ForElem:
            inc := ""
            if el.iter_inc == 1 {
                inc = "+"
            }
            ret += fmt.Sprintf("$for %s%s, %s in %s:", el.iter, inc, el.val,
                revParse2VarFun(el.arg))
            ret += revParse2(el.iter_block)
            if el.else_block != nil {
                ret += "$else:" + revParse2(el.else_block)
            }
            ret += "${end}"

        default:
            ret += "!UNKNOWN ELEMENT!"
        }
    }
    return
}
<commit_msg>Added support for maps with key of any type<commit_after>package kasia

import (
    "fmt"
    "reflect"
)

var cmp_map map[int]string

func init() {
    cmp_map = map[int]string{
        if_eq:    "==",
        if_ne:    "!=",
        if_lt:    "<",
        if_le:    "<=",
        if_gt:    ">",
        if_ge:    ">=",
    }
}

func revParse1Param(par interface{}) (ret string) {
    switch pv := par.(type) {
    case reflect.Value:
        ret += fmt.Sprint(pv.Interface())

    case []Element:
        ret += "\"" + revParse1(pv) + "\""

    case *VarFunElem:
        ret += revParse1VarFun(pv)

    default:
        ret += "!UNKNOWN_ARG!"
    }
    return
}

func revParse1VarFun(vf *VarFunElem) (ret string) {
    show_dot := false
    for vf != nil {
        switch pe := vf.name.(type) {
        case *reflect.StringValue:
            if show_dot {
                ret += "."
            }
            ret += pe.Get()

        case reflect.Value:
            ret += fmt.Sprintf("[%v]", pe.Interface())

        case nil:
            // Samowywolanie

        case []Element:
            ret += "[\"" + revParse1(pe) + "\"]"

        case *VarFunElem:
            ret += fmt.Sprintf("[%s]", revParse1VarFun(pe))

        default:
            ret += "!UNKNOWN_NAME!"
        }
        show_dot = true

        if vf.fun {
            ret += "("
            for ii := range vf.args {
                if ii != 0 {
                    ret += ", "
                }
                ret += revParse1Param(vf.args[ii])
            }
            ret += ")"
        }

        vf = vf.next
    }
    return
}

func revParse1(elems []Element) (ret string){
    for _, va := range elems {
        switch el := va.(type) {
        case *TxtElem:
            ret += el.txt

        case *VarFunElem:
            ret += "$"
            if !el.filt {
                ret += ":"
            }
            ret += "{" + revParse1VarFun(el)  + "}"

        case *IfElem:
            ret += "$if " + revParse1Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse1Param(el.arg2)
            }
            ret +=  ":"

        case *ElifElem:
            ret += "$elif " + revParse1Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse1Param(el.arg2)
            }
            ret +=  ":"

        case *ElseElem:
            ret += "$else:"

        case *EndElem:
            ret += "${end}"

        case *ForElem:
            inc := ""
            if el.iter_inc == 1 {
                inc = "+"
            }
            ret += fmt.Sprintf("$for %s%s, %s in %s:", el.iter, inc, el.val,
                revParse1VarFun(el.arg))

        default:
            ret += "!UNKNOWN ELEMENT!"
        }
    }
    return
}

func revParse2Param(par interface{}) (ret string) {
    switch pv := par.(type) {
    case reflect.Value:
        ret += fmt.Sprint(pv.Interface())

    case []Element:
        ret += "\"" + revParse2(pv) + "\""

    case *VarFunElem:
        ret += revParse2VarFun(pv)

    default:
        ret += "!UNKNOWN_ARG!"
    }
    return
}

func revParse2VarFun(vf *VarFunElem) (ret string) {
    show_dot := false
    for vf != nil {
        switch pe := vf.name.(type) {
        case *reflect.StringValue:
            if show_dot {
                ret += "."
            }
            ret += pe.Get()

        case reflect.Value:
            ret += fmt.Sprintf("[%v]", pe.Interface())

        case nil:
            // Samowywolanie

        case []Element:
            ret += "[\"" + revParse2(pe) + "\"]"

        case *VarFunElem:
            ret += fmt.Sprintf("[%s]", revParse2VarFun(pe))

        default:
            ret += "!UNKNOWN_NAME!"
        }
        show_dot = true

        if vf.fun {
            ret += "("
            for ii := range vf.args {
                if ii != 0 {
                    ret += ", "
                }
                ret += revParse2Param(vf.args[ii])
            }
            ret += ")"
        }

        vf = vf.next
    }
    return
}

func revParse2(elems []Element) (ret string) {
    for _, va := range elems {
        switch el := va.(type) {
        case *TxtElem:
            ret += el.txt

        case *VarFunElem:
            ret += "$"
            if !el.filt {
                ret += ":"
            }
            ret += "{" + revParse2VarFun(el)  + "}"

        case *IfElem:
            ret += "$if " + revParse2Param(el.arg1)
            if el.cmp != if_nocmp {
                ret += " "
                cmp, ok := cmp_map[el.cmp]
                if ok {
                    ret += cmp
                } else {
                    ret += "!UNKNOWN_CMP!"
                }
                ret += " " + revParse2Param(el.arg2)
            }
            ret +=  ":"
            ret += revParse2(el.true_block)
            if el.false_block != nil {
                ret += "$else:" + revParse2(el.false_block)
            }
            ret += "${end}"

        case *ForElem:
            inc := ""
            if el.iter_inc == 1 {
                inc = "+"
            }
            ret += fmt.Sprintf("$for %s%s, %s in %s:", el.iter, inc, el.val,
                revParse2VarFun(el.arg))
            ret += revParse2(el.iter_block)
            if el.else_block != nil {
                ret += "$else:" + revParse2(el.else_block)
            }
            ret += "${end}"

        default:
            ret += "!UNKNOWN ELEMENT!"
        }
    }
    return
}
<|endoftext|>


<commit_before>package filesys

import (
	"bazil.org/fuse/fs"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/filer2"
	"context"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"bazil.org/fuse"
	"bytes"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"time"
	"strings"
	"sync"
	"github.com/chrislusf/seaweedfs/weed/util"
)

type FileHandle struct {
	// cache file has been written to
	dirty bool

	cachePath string

	handle uint64

	wfs        *WFS
	dirPath    string
	name       string
	RequestId  fuse.RequestID // unique ID for request
	NodeId     fuse.NodeID    // file or directory the request is about
	Uid        uint32         // user ID of process making request
	Gid        uint32         // group ID of process making request
	attributes *filer_pb.FuseAttributes
	Chunks     []*filer_pb.FileChunk
}

var _ = fs.Handle(&FileHandle{})
// var _ = fs.HandleReadAller(&FileHandle{})
var _ = fs.HandleReader(&FileHandle{})
var _ = fs.HandleFlusher(&FileHandle{})
var _ = fs.HandleWriter(&FileHandle{})
var _ = fs.HandleReleaser(&FileHandle{})

func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {

	glog.V(3).Infof("%v/%v read fh: [%d,%d)", fh.dirPath, fh.name, req.Offset, req.Offset+int64(req.Size))

	if len(fh.Chunks) == 0 {
		glog.V(0).Infof("empty fh %v/%v", fh.dirPath, fh.name)
		return fmt.Errorf("empty file %v/%v", fh.dirPath, fh.name)
	}

	buff := make([]byte, req.Size)

	chunkViews := filer2.ReadFromChunks(fh.Chunks, req.Offset, req.Size)

	var vids []string
	for _, chunkView := range chunkViews {
		vids = append(vids, volumeId(chunkView.FileId))
	}

	vid2Locations := make(map[string]*filer_pb.Locations)

	err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		glog.V(4).Infof("read fh lookup volume id locations: %v", vids)
		resp, err := client.LookupVolume(ctx, &filer_pb.LookupVolumeRequest{
			VolumeIds: vids,
		})
		if err != nil {
			return err
		}

		vid2Locations = resp.LocationsMap

		return nil
	})

	if err != nil {
		glog.V(3).Infof("%v/%v read fh lookup volume ids: %v", fh.dirPath, fh.name, err)
		return fmt.Errorf("failed to lookup volume ids %v: %v", vids, err)
	}

	var totalRead int64
	var wg sync.WaitGroup
	for _, chunkView := range chunkViews {
		wg.Add(1)
		go func(chunkView *filer2.ChunkView) {
			defer wg.Done()

			glog.V(3).Infof("read fh reading chunk: %+v", chunkView)

			locations := vid2Locations[volumeId(chunkView.FileId)]
			if locations == nil || len(locations.Locations) == 0 {
				glog.V(0).Infof("failed to locate %s", chunkView.FileId)
				err = fmt.Errorf("failed to locate %s", chunkView.FileId)
				return
			}

			var n int64
			n, err = util.ReadUrl(
				fmt.Sprintf("http://%s/%s", locations.Locations[0].Url, chunkView.FileId),
				chunkView.Offset,
				int(chunkView.Size),
				buff[chunkView.LogicOffset-req.Offset:chunkView.LogicOffset-req.Offset+int64(chunkView.Size)])

			if err != nil {

				glog.V(0).Infof("%v/%v read http://%s/%v %v bytes: %v", fh.dirPath, fh.name, locations.Locations[0].Url, chunkView.FileId, n, err)

				err = fmt.Errorf("failed to read http://%s/%s: %v",
					locations.Locations[0].Url, chunkView.FileId, err)
				return
			}

			glog.V(3).Infof("read fh read %d bytes: %+v", n, chunkView)
			totalRead += n

		}(chunkView)
	}
	wg.Wait()

	resp.Data = buff[:totalRead]

	return err
}

// Write to the file handle
func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {

	// write the request to volume servers

	glog.V(3).Infof("%+v/%v write fh: %+v", fh.dirPath, fh.name, req)

	var fileId, host string

	if err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.AssignVolumeRequest{
			Count:       1,
			Replication: "000",
			Collection:  "",
		}

		glog.V(1).Infof("assign volume: %v", request)
		resp, err := client.AssignVolume(ctx, request)
		if err != nil {
			return err
		}

		fileId, host = resp.FileId, resp.Url

		return nil
	}); err != nil {
		return fmt.Errorf("filer assign volume: %v", err)
	}

	fileUrl := fmt.Sprintf("http://%s/%s", host, fileId)
	bufReader := bytes.NewReader(req.Data)
	uploadResult, err := operation.Upload(fileUrl, fh.name, bufReader, false, "application/octet-stream", nil, "")
	if err != nil {
		return fmt.Errorf("upload data: %v", err)
	}
	if uploadResult.Error != "" {
		return fmt.Errorf("upload result: %v", uploadResult.Error)
	}

	resp.Size = int(uploadResult.Size)

	fh.Chunks = append(fh.Chunks, &filer_pb.FileChunk{
		FileId: fileId,
		Offset: req.Offset,
		Size:   uint64(uploadResult.Size),
		Mtime:  time.Now().UnixNano(),
	})

	glog.V(1).Infof("uploaded %s/%s to: %v, [%d,%d)", fh.dirPath, fh.name, fileUrl, req.Offset, req.Offset+int64(resp.Size))

	fh.dirty = true

	return nil
}

func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) error {

	glog.V(3).Infof("%+v/%v release fh", fh.dirPath, fh.name)

	return nil
}

// Flush - experimenting with uploading at flush, this slows operations down till it has been
// completely flushed
func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) error {
	// fflush works at fh level
	// send the data to the OS
	glog.V(3).Infof("%s/%s fh flush %v", fh.dirPath, fh.name, req)

	if !fh.dirty {
		return nil
	}

	if len(fh.Chunks) == 0 {
		glog.V(2).Infof("fh %s/%s flush skipping empty: %v", fh.dirPath, fh.name, req)
		return nil
	}

	err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.UpdateEntryRequest{
			Directory: fh.dirPath,
			Entry: &filer_pb.Entry{
				Name:       fh.name,
				Attributes: fh.attributes,
				Chunks:     fh.Chunks,
			},
		}

		glog.V(1).Infof("%s/%s set chunks: %v", fh.dirPath, fh.name, len(fh.Chunks))
		if _, err := client.UpdateEntry(ctx, request); err != nil {
			return fmt.Errorf("update fh: %v", err)
		}

		return nil
	})

	if err == nil {
		fh.dirty = false
	}

	return err
}

func volumeId(fileId string) string {
	lastCommaIndex := strings.LastIndex(fileId, ",")
	if lastCommaIndex > 0 {
		return fileId[:lastCommaIndex]
	}
	return fileId
}
<commit_msg>better logs<commit_after>package filesys

import (
	"bazil.org/fuse/fs"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/filer2"
	"context"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"bazil.org/fuse"
	"bytes"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"time"
	"strings"
	"sync"
	"github.com/chrislusf/seaweedfs/weed/util"
)

type FileHandle struct {
	// cache file has been written to
	dirty bool

	cachePath string

	handle uint64

	wfs        *WFS
	dirPath    string
	name       string
	RequestId  fuse.RequestID // unique ID for request
	NodeId     fuse.NodeID    // file or directory the request is about
	Uid        uint32         // user ID of process making request
	Gid        uint32         // group ID of process making request
	attributes *filer_pb.FuseAttributes
	Chunks     []*filer_pb.FileChunk
}

var _ = fs.Handle(&FileHandle{})
// var _ = fs.HandleReadAller(&FileHandle{})
var _ = fs.HandleReader(&FileHandle{})
var _ = fs.HandleFlusher(&FileHandle{})
var _ = fs.HandleWriter(&FileHandle{})
var _ = fs.HandleReleaser(&FileHandle{})

func (fh *FileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {

	glog.V(3).Infof("%v/%v read fh: [%d,%d)", fh.dirPath, fh.name, req.Offset, req.Offset+int64(req.Size))

	if len(fh.Chunks) == 0 {
		glog.V(0).Infof("empty fh %v/%v", fh.dirPath, fh.name)
		return fmt.Errorf("empty file %v/%v", fh.dirPath, fh.name)
	}

	buff := make([]byte, req.Size)

	chunkViews := filer2.ReadFromChunks(fh.Chunks, req.Offset, req.Size)

	var vids []string
	for _, chunkView := range chunkViews {
		vids = append(vids, volumeId(chunkView.FileId))
	}

	vid2Locations := make(map[string]*filer_pb.Locations)

	err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		glog.V(4).Infof("read fh lookup volume id locations: %v", vids)
		resp, err := client.LookupVolume(ctx, &filer_pb.LookupVolumeRequest{
			VolumeIds: vids,
		})
		if err != nil {
			return err
		}

		vid2Locations = resp.LocationsMap

		return nil
	})

	if err != nil {
		glog.V(3).Infof("%v/%v read fh lookup volume ids: %v", fh.dirPath, fh.name, err)
		return fmt.Errorf("failed to lookup volume ids %v: %v", vids, err)
	}

	var totalRead int64
	var wg sync.WaitGroup
	for _, chunkView := range chunkViews {
		wg.Add(1)
		go func(chunkView *filer2.ChunkView) {
			defer wg.Done()

			glog.V(3).Infof("read fh reading chunk: %+v", chunkView)

			locations := vid2Locations[volumeId(chunkView.FileId)]
			if locations == nil || len(locations.Locations) == 0 {
				glog.V(0).Infof("failed to locate %s", chunkView.FileId)
				err = fmt.Errorf("failed to locate %s", chunkView.FileId)
				return
			}

			var n int64
			n, err = util.ReadUrl(
				fmt.Sprintf("http://%s/%s", locations.Locations[0].Url, chunkView.FileId),
				chunkView.Offset,
				int(chunkView.Size),
				buff[chunkView.LogicOffset-req.Offset:chunkView.LogicOffset-req.Offset+int64(chunkView.Size)])

			if err != nil {

				glog.V(0).Infof("%v/%v read http://%s/%v %v bytes: %v", fh.dirPath, fh.name, locations.Locations[0].Url, chunkView.FileId, n, err)

				err = fmt.Errorf("failed to read http://%s/%s: %v",
					locations.Locations[0].Url, chunkView.FileId, err)
				return
			}

			glog.V(3).Infof("read fh read %d bytes: %+v", n, chunkView)
			totalRead += n

		}(chunkView)
	}
	wg.Wait()

	resp.Data = buff[:totalRead]

	return err
}

// Write to the file handle
func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {

	// write the request to volume servers

	glog.V(3).Infof("%+v/%v write fh: %+v", fh.dirPath, fh.name, req)

	var fileId, host string

	if err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.AssignVolumeRequest{
			Count:       1,
			Replication: "000",
			Collection:  "",
		}

		resp, err := client.AssignVolume(ctx, request)
		if err != nil {
			glog.V(0).Infof("assign volume failure %v: %v", request, err)
			return err
		}

		fileId, host = resp.FileId, resp.Url

		return nil
	}); err != nil {
		return fmt.Errorf("filer assign volume: %v", err)
	}

	fileUrl := fmt.Sprintf("http://%s/%s", host, fileId)
	bufReader := bytes.NewReader(req.Data)
	uploadResult, err := operation.Upload(fileUrl, fh.name, bufReader, false, "application/octet-stream", nil, "")
	if err != nil {
		glog.V(0).Infof("upload data %v to %s: %v", req, fileUrl, err)
		return fmt.Errorf("upload data: %v", err)
	}
	if uploadResult.Error != "" {
		glog.V(0).Infof("upload failure %v to %s: %v", req, fileUrl, err)
		return fmt.Errorf("upload result: %v", uploadResult.Error)
	}

	resp.Size = int(uploadResult.Size)

	fh.Chunks = append(fh.Chunks, &filer_pb.FileChunk{
		FileId: fileId,
		Offset: req.Offset,
		Size:   uint64(uploadResult.Size),
		Mtime:  time.Now().UnixNano(),
	})

	glog.V(1).Infof("uploaded %s/%s to: %v, [%d,%d)", fh.dirPath, fh.name, fileUrl, req.Offset, req.Offset+int64(resp.Size))

	fh.dirty = true

	return nil
}

func (fh *FileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) error {

	glog.V(3).Infof("%+v/%v release fh", fh.dirPath, fh.name)

	return nil
}

// Flush - experimenting with uploading at flush, this slows operations down till it has been
// completely flushed
func (fh *FileHandle) Flush(ctx context.Context, req *fuse.FlushRequest) error {
	// fflush works at fh level
	// send the data to the OS
	glog.V(3).Infof("%s/%s fh flush %v", fh.dirPath, fh.name, req)

	if !fh.dirty {
		return nil
	}

	if len(fh.Chunks) == 0 {
		glog.V(2).Infof("fh %s/%s flush skipping empty: %v", fh.dirPath, fh.name, req)
		return nil
	}

	err := fh.wfs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.UpdateEntryRequest{
			Directory: fh.dirPath,
			Entry: &filer_pb.Entry{
				Name:       fh.name,
				Attributes: fh.attributes,
				Chunks:     fh.Chunks,
			},
		}

		glog.V(1).Infof("%s/%s set chunks: %v", fh.dirPath, fh.name, len(fh.Chunks))
		for i, chunk := range fh.Chunks {
			glog.V(1).Infof("%s/%s chunks %d: %v [%d,%d)", fh.dirPath, fh.name, i, chunk.FileId, chunk.Offset, chunk.Offset+int64(chunk.Size))
		}
		if _, err := client.UpdateEntry(ctx, request); err != nil {
			return fmt.Errorf("update fh: %v", err)
		}

		return nil
	})

	if err == nil {
		fh.dirty = false
	}

	return err
}

func volumeId(fileId string) string {
	lastCommaIndex := strings.LastIndex(fileId, ",")
	if lastCommaIndex > 0 {
		return fileId[:lastCommaIndex]
	}
	return fileId
}
<|endoftext|>


<commit_before>// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// author           sigu-399
// author-github    https://github.com/sigu-399
// author-mail      sigu.399@gmail.com
//
// repository-name  gojsonschema
// repository-desc  An implementation of JSON Schema, based on IETF's draft v4 - Go language.
//
// description		Defines resources pooling.
//                  Eases referencing and avoids downloading the same resource twice.
//
// created          26-02-2013

package gojsonschema

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/sigu-399/gojsonreference"
	"io/ioutil"
	"net/http"
)

type schemaPool struct {
	schemaPoolDocuments map[string]*schemaPoolDocument
}

func newSchemaPool() *schemaPool {
	p := &schemaPool{}
	p.schemaPoolDocuments = make(map[string]*schemaPoolDocument)
	return p
}

func (p *schemaPool) GetPoolDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) {

	var err error

	if !reference.IsCanonical() {
		return nil, errors.New(fmt.Sprintf("Reference must be canonical %s", reference))
	}

	refToUrl := reference
	refToUrl.GetUrl().Fragment = ""

	var spd *schemaPoolDocument

	for k := range p.schemaPoolDocuments {
		if k == refToUrl.String() {
			spd = p.schemaPoolDocuments[k]
			fmt.Printf("Found in pool %s\n", refToUrl.String())
		}
	}

	if spd != nil {
		return spd, nil
	}

	document, err := GetHttpJson(refToUrl.String())
	if err != nil {
		return nil, err
	}

	spd = &schemaPoolDocument{Document: document}
	p.schemaPoolDocuments[refToUrl.String()] = spd

	fmt.Printf("Added to pool %s\n", refToUrl.String())

	return spd, nil
}

type schemaPoolDocument struct {
	Document interface{}
}

func GetHttpJson(url string) (interface{}, error) {

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var document interface{}
	err = json.Unmarshal(bodyBuff, &document)
	if err != nil {
		return nil, err
	}

	return document, nil
}
<commit_msg>pool now can load json files<commit_after>// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// author           sigu-399
// author-github    https://github.com/sigu-399
// author-mail      sigu.399@gmail.com
//
// repository-name  gojsonschema
// repository-desc  An implementation of JSON Schema, based on IETF's draft v4 - Go language.
//
// description		Defines resources pooling.
//                  Eases referencing and avoids downloading the same resource twice.
//
// created          26-02-2013

package gojsonschema

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/sigu-399/gojsonreference"
	"io/ioutil"
	"net/http"
)

type schemaPool struct {
	schemaPoolDocuments map[string]*schemaPoolDocument
}

func newSchemaPool() *schemaPool {
	p := &schemaPool{}
	p.schemaPoolDocuments = make(map[string]*schemaPoolDocument)
	return p
}

func (p *schemaPool) GetPoolDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) {

	var err error

	if !reference.IsCanonical() {
		return nil, errors.New(fmt.Sprintf("Reference must be canonical %s", reference))
	}

	refToUrl := reference
	refToUrl.GetUrl().Fragment = ""

	var spd *schemaPoolDocument

	for k := range p.schemaPoolDocuments {
		if k == refToUrl.String() {
			spd = p.schemaPoolDocuments[k]
			fmt.Printf("Found in pool %s\n", refToUrl.String())
		}
	}

	if spd != nil {
		return spd, nil
	}

	var document interface{}

	if reference.HasFileScheme {

		document, err = GetFileJson(refToUrl.String())
		if err != nil {
			return nil, err
		}

	} else {

		document, err = GetHttpJson(refToUrl.String())
		if err != nil {
			return nil, err
		}

	}

	spd = &schemaPoolDocument{Document: document}
	p.schemaPoolDocuments[refToUrl.String()] = spd

	fmt.Printf("Added to pool %s\n", refToUrl.String())

	return spd, nil
}

type schemaPoolDocument struct {
	Document interface{}
}

func GetHttpJson(url string) (interface{}, error) {

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var document interface{}
	err = json.Unmarshal(bodyBuff, &document)
	if err != nil {
		return nil, err
	}

	return document, nil
}

func GetFileJson(filename string) (interface{}, error) {

	bodyBuff, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	var document interface{}
	err = json.Unmarshal(bodyBuff, &document)
	if err != nil {
		return nil, err
	}

	return document, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tally

import (
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

type testStatsReporter struct {
	sync.RWMutex

	scope Scope

	counters map[string]int64
	gauges   map[string]int64
	timers   map[string]time.Duration
}

func (r *testStatsReporter) ReportCounter(name string, tags map[string]string, value int64) {
	r.counters[name] = value
}

func (r *testStatsReporter) ReportGauge(name string, tags map[string]string, value int64) {
	r.gauges[name] = value
}

func (r *testStatsReporter) ReportTimer(name string, tags map[string]string, interval time.Duration) {
	r.timers[name] = interval
}

func (r *testStatsReporter) Flush() {}

// newTestStatsReporter returns a new TestStatsReporter
func newTestStatsReporter() *testStatsReporter {
	return &testStatsReporter{
		counters: make(map[string]int64),
		gauges:   make(map[string]int64),
		timers:   make(map[string]time.Duration),
	}
}

func TestWriteOnce(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("", nil, r, 0)
	scope.Counter("bar").Inc(1)
	scope.Gauge("zed").Update(1)
	scope.Timer("ticky").Record(time.Millisecond * 175)

	scope.Report(r)
	assert.EqualValues(t, 1, r.counters["bar"])
	assert.EqualValues(t, 1, r.gauges["zed"])
	assert.EqualValues(t, time.Millisecond*175, r.timers["ticky"])

	r = newTestStatsReporter()
	scope.Report(r)
	assert.EqualValues(t, 0, r.counters["bar"])
	assert.EqualValues(t, 0, r.gauges["zed"])
	assert.EqualValues(t, 0, r.timers["ticky"])
}

func TestRootScopeWithoutPrefix(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("", nil, r, 0)
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	scope.Gauge("zed").Update(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	assert.EqualValues(t, 21, r.counters["bar"])
	assert.EqualValues(t, 1, r.gauges["zed"])
	assert.EqualValues(t, time.Millisecond*175, r.timers["blork"])
}

func TestRootScopeWithPrefix(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("foo", nil, r, 0)
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	scope.Gauge("zed").Update(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	assert.EqualValues(t, 21, r.counters["foo.bar"])
	assert.EqualValues(t, 1, r.gauges["foo.zed"])
	assert.EqualValues(t, time.Millisecond*175, r.timers["foo.blork"])
}

func TestSubScope(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("foo", nil, r, 0).SubScope("mork")
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	scope.Gauge("zed").Update(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	assert.EqualValues(t, 21, r.counters["foo.mork.bar"])
	assert.EqualValues(t, 1, r.gauges["foo.mork.zed"])
	assert.EqualValues(t, time.Millisecond*175, r.timers["foo.mork.blork"])
}
<commit_msg>Better unit tests (#3)<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tally

import (
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

type testValue struct {
	val  int64
	tags map[string]string
}

type testStatsReporter struct {
	cg sync.WaitGroup
	gg sync.WaitGroup
	tg sync.WaitGroup

	scope Scope

	counters map[string]*testValue
	gauges   map[string]*testValue
	timers   map[string]*testValue
}

func (r *testStatsReporter) ReportCounter(name string, tags map[string]string, value int64) {
	r.counters[name] = &testValue{
		val:  value,
		tags: tags,
	}
	r.cg.Done()
}

func (r *testStatsReporter) ReportGauge(name string, tags map[string]string, value int64) {
	r.gauges[name] = &testValue{
		val:  value,
		tags: tags,
	}
	r.gg.Done()
}

func (r *testStatsReporter) ReportTimer(name string, tags map[string]string, interval time.Duration) {
	r.timers[name] = &testValue{
		val:  int64(interval),
		tags: tags,
	}
	r.tg.Done()
}

func (r *testStatsReporter) Flush() {}

// newTestStatsReporter returns a new TestStatsReporter
func newTestStatsReporter() *testStatsReporter {
	return &testStatsReporter{
		counters: make(map[string]*testValue),
		gauges:   make(map[string]*testValue),
		timers:   make(map[string]*testValue),
	}
}

func TestWriteTimerImmediately(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("", nil, r, 0)
	r.tg.Add(1)
	scope.Timer("ticky").Record(time.Millisecond * 175)
	r.tg.Wait()
}

func TestWriteTimerClosureImmediately(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("", nil, r, 0)
	r.tg.Add(1)
	scope.Timer("ticky").Begin()()
	r.tg.Wait()
}

func TestWriteReportLoop(t *testing.T) {
	r := newTestStatsReporter()
	scope := NewRootScope("", nil, r, 10)
	defer scope.Close()

	r.cg.Add(1)
	scope.Counter("bar").Inc(1)
	r.gg.Add(1)
	scope.Gauge("zed").Update(1)
	r.tg.Add(1)
	scope.Timer("ticky").Record(time.Millisecond * 175)

	r.cg.Wait()
	r.gg.Wait()
	r.tg.Wait()
}

func TestWriteOnce(t *testing.T) {
	r := newTestStatsReporter()

	scope := NewRootScope("", nil, r, 0)

	r.cg.Add(1)
	scope.Counter("bar").Inc(1)
	r.gg.Add(1)
	scope.Gauge("zed").Update(1)
	r.tg.Add(1)
	scope.Timer("ticky").Record(time.Millisecond * 175)

	scope.Report(r)
	r.cg.Wait()
	r.gg.Wait()
	r.tg.Wait()

	assert.EqualValues(t, 1, r.counters["bar"].val)
	assert.EqualValues(t, 1, r.gauges["zed"].val)
	assert.EqualValues(t, time.Millisecond*175, r.timers["ticky"].val)

	r = newTestStatsReporter()
	scope.Report(r)

	assert.Nil(t, r.counters["bar"])
	assert.Nil(t, r.gauges["zed"])
	assert.Nil(t, r.timers["ticky"])
}

func TestRootScopeWithoutPrefix(t *testing.T) {
	r := newTestStatsReporter()

	scope := NewRootScope("", nil, r, 0)
	r.cg.Add(1)
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	r.gg.Add(1)
	scope.Gauge("zed").Update(1)
	r.tg.Add(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	r.cg.Wait()
	r.gg.Wait()
	r.tg.Wait()

	assert.EqualValues(t, 21, r.counters["bar"].val)
	assert.EqualValues(t, 1, r.gauges["zed"].val)
	assert.EqualValues(t, time.Millisecond*175, r.timers["blork"].val)
}

func TestRootScopeWithPrefix(t *testing.T) {
	r := newTestStatsReporter()

	scope := NewRootScope("foo", nil, r, 0)
	r.cg.Add(1)
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	r.gg.Add(1)
	scope.Gauge("zed").Update(1)
	r.tg.Add(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	r.cg.Wait()
	r.gg.Wait()
	r.tg.Wait()

	assert.EqualValues(t, 21, r.counters["foo.bar"].val)
	assert.EqualValues(t, 1, r.gauges["foo.zed"].val)
	assert.EqualValues(t, time.Millisecond*175, r.timers["foo.blork"].val)
}

func TestSubScope(t *testing.T) {
	r := newTestStatsReporter()

	scope := NewRootScope("foo", nil, r, 0).SubScope("mork")
	r.cg.Add(1)
	scope.Counter("bar").Inc(1)
	scope.Counter("bar").Inc(20)
	r.gg.Add(1)
	scope.Gauge("zed").Update(1)
	r.tg.Add(1)
	scope.Timer("blork").Record(time.Millisecond * 175)

	scope.Report(r)
	r.cg.Wait()
	r.gg.Wait()
	r.tg.Wait()

	assert.EqualValues(t, 21, r.counters["foo.mork.bar"].val)
	assert.EqualValues(t, 1, r.gauges["foo.mork.zed"].val)
	assert.EqualValues(t, time.Millisecond*175, r.timers["foo.mork.blork"].val)
}

func TestTaggedSubScope(t *testing.T) {
	r := newTestStatsReporter()

	ts := map[string]string{"env": "test"}
	scope := NewRootScope("foo", ts, r, 0)

	tscope := scope.Tagged(map[string]string{"service": "test"})

	r.cg.Add(1)
	scope.Counter("beep").Inc(1)
	r.cg.Add(1)
	tscope.Counter("boop").Inc(1)

	scope.Report(r)
	tscope.Report(r)
	r.cg.Wait()

	assert.EqualValues(t, 1, r.counters["foo.beep"].val)
	assert.EqualValues(t, ts, r.counters["foo.beep"].tags)

	assert.EqualValues(t, 1, r.counters["foo.boop"].val)
	assert.EqualValues(t, map[string]string{
		"env":     "test",
		"service": "test",
	}, r.counters["foo.boop"].tags)
}

func TestNilTagMerge(t *testing.T) {
	assert.Nil(t, nil, mergeRightTags(nil, nil))
}
<|endoftext|>


<commit_before>package types

import (
	"bufio"
	"io"
	"net"

	"github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/filters"
	"github.com/docker/go-units"
)

// ContainerAttachOptions holds parameters to attach to a container.
type ContainerAttachOptions struct {
	ContainerID string
	Stream      bool
	Stdin       bool
	Stdout      bool
	Stderr      bool
	DetachKeys  string
}

// ContainerCommitOptions holds parameters to commit changes into a container.
type ContainerCommitOptions struct {
	ContainerID    string
	RepositoryName string
	Tag            string
	Comment        string
	Author         string
	Changes        []string
	Pause          bool
	Config         *container.Config
}

// ContainerExecInspect holds information returned by exec inspect.
type ContainerExecInspect struct {
	ExecID      string
	ContainerID string
	Running     bool
	ExitCode    int
}

// ContainerListOptions holds parameters to list containers with.
type ContainerListOptions struct {
	Quiet  bool
	Size   bool
	All    bool
	Latest bool
	Since  string
	Before string
	Limit  int
	Filter filters.Args
}

// ContainerLogsOptions holds parameters to filter logs with.
type ContainerLogsOptions struct {
	ContainerID string
	ShowStdout  bool
	ShowStderr  bool
	Since       string
	Timestamps  bool
	Follow      bool
	Tail        string
}

// ContainerRemoveOptions holds parameters to remove containers.
type ContainerRemoveOptions struct {
	ContainerID   string
	RemoveVolumes bool
	RemoveLinks   bool
	Force         bool
}

// CopyToContainerOptions holds information
// about files to copy into a container
type CopyToContainerOptions struct {
	ContainerID               string
	Path                      string
	Content                   io.Reader
	AllowOverwriteDirWithFile bool
}

// EventsOptions hold parameters to filter events with.
type EventsOptions struct {
	Since   string
	Until   string
	Filters filters.Args
}

// NetworkListOptions holds parameters to filter the list of networks with.
type NetworkListOptions struct {
	Filters filters.Args
}

// HijackedResponse holds connection information for a hijacked request.
type HijackedResponse struct {
	Conn   net.Conn
	Reader *bufio.Reader
}

// Close closes the hijacked connection and reader.
func (h *HijackedResponse) Close() {
	h.Conn.Close()
}

// CloseWriter is an interface that implement structs
// that close input streams to prevent from writing.
type CloseWriter interface {
	CloseWrite() error
}

// CloseWrite closes a readWriter for writing.
func (h *HijackedResponse) CloseWrite() error {
	if conn, ok := h.Conn.(CloseWriter); ok {
		return conn.CloseWrite()
	}
	return nil
}

// ImageBuildOptions holds the information
// necessary to build images.
type ImageBuildOptions struct {
	Tags           []string
	SuppressOutput bool
	RemoteContext  string
	NoCache        bool
	Remove         bool
	ForceRemove    bool
	PullParent     bool
	IsolationLevel container.IsolationLevel
	CPUSetCPUs     string
	CPUSetMems     string
	CPUShares      int64
	CPUQuota       int64
	CPUPeriod      int64
	Memory         int64
	MemorySwap     int64
	CgroupParent   string
	ShmSize        int64
	Dockerfile     string
	Ulimits        []*units.Ulimit
	BuildArgs      map[string]string
	AuthConfigs    map[string]AuthConfig
	Context        io.Reader
}

// ImageBuildResponse holds information
// returned by a server after building
// an image.
type ImageBuildResponse struct {
	Body   io.ReadCloser
	OSType string
}

// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
	// Parent is the image to create this image from
	Parent string
	// Tag is the name to tag this image
	Tag string
	// RegistryAuth is the base64 encoded credentials for this server
	RegistryAuth string
}

// ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct {
	// Source is the data to send to the server to create this image from
	Source io.Reader
	// Source is the name of the source to import this image from
	SourceName string
	// RepositoryName is the name of the repository to import this image
	RepositoryName string
	// Message is the message to tag the image with
	Message string
	// Tag is the name to tag this image
	Tag string
	// Changes are the raw changes to apply to the image
	Changes []string
}

// ImageListOptions holds parameters to filter the list of images with.
type ImageListOptions struct {
	MatchName string
	All       bool
	Filters   filters.Args
}

// ImageLoadResponse returns information to the client about a load process.
type ImageLoadResponse struct {
	Body io.ReadCloser
	JSON bool
}

// ImagePullOptions holds information to pull images.
type ImagePullOptions struct {
	ImageID string
	Tag     string
	// RegistryAuth is the base64 encoded credentials for this server
	RegistryAuth string
}

//ImagePushOptions holds information to push images.
type ImagePushOptions ImagePullOptions

// ImageRemoveOptions holds parameters to remove images.
type ImageRemoveOptions struct {
	ImageID       string
	Force         bool
	PruneChildren bool
}

// ImageSearchOptions holds parameters to search images with.
type ImageSearchOptions struct {
	Term         string
	RegistryAuth string
}

// ImageTagOptions holds parameters to tag an image
type ImageTagOptions struct {
	ImageID        string
	RepositoryName string
	Tag            string
	Force          bool
}

// ResizeOptions holds parameters to resize a tty.
// It can be used to resize container ttys and
// exec process ttys too.
type ResizeOptions struct {
	ID     string
	Height int
	Width  int
}

// VersionResponse holds version information for the client and the server
type VersionResponse struct {
	Client *Version
	Server *Version
}

// ServerOK return true when the client could connect to the docker server
// and parse the information received. It returns false otherwise.
func (v VersionResponse) ServerOK() bool {
	return v.Server != nil
}
<commit_msg>Improve formatting of types.ImageCreateOptions, ImageImportOptions and ImagePullOptions.<commit_after>package types

import (
	"bufio"
	"io"
	"net"

	"github.com/docker/engine-api/types/container"
	"github.com/docker/engine-api/types/filters"
	"github.com/docker/go-units"
)

// ContainerAttachOptions holds parameters to attach to a container.
type ContainerAttachOptions struct {
	ContainerID string
	Stream      bool
	Stdin       bool
	Stdout      bool
	Stderr      bool
	DetachKeys  string
}

// ContainerCommitOptions holds parameters to commit changes into a container.
type ContainerCommitOptions struct {
	ContainerID    string
	RepositoryName string
	Tag            string
	Comment        string
	Author         string
	Changes        []string
	Pause          bool
	Config         *container.Config
}

// ContainerExecInspect holds information returned by exec inspect.
type ContainerExecInspect struct {
	ExecID      string
	ContainerID string
	Running     bool
	ExitCode    int
}

// ContainerListOptions holds parameters to list containers with.
type ContainerListOptions struct {
	Quiet  bool
	Size   bool
	All    bool
	Latest bool
	Since  string
	Before string
	Limit  int
	Filter filters.Args
}

// ContainerLogsOptions holds parameters to filter logs with.
type ContainerLogsOptions struct {
	ContainerID string
	ShowStdout  bool
	ShowStderr  bool
	Since       string
	Timestamps  bool
	Follow      bool
	Tail        string
}

// ContainerRemoveOptions holds parameters to remove containers.
type ContainerRemoveOptions struct {
	ContainerID   string
	RemoveVolumes bool
	RemoveLinks   bool
	Force         bool
}

// CopyToContainerOptions holds information
// about files to copy into a container
type CopyToContainerOptions struct {
	ContainerID               string
	Path                      string
	Content                   io.Reader
	AllowOverwriteDirWithFile bool
}

// EventsOptions hold parameters to filter events with.
type EventsOptions struct {
	Since   string
	Until   string
	Filters filters.Args
}

// NetworkListOptions holds parameters to filter the list of networks with.
type NetworkListOptions struct {
	Filters filters.Args
}

// HijackedResponse holds connection information for a hijacked request.
type HijackedResponse struct {
	Conn   net.Conn
	Reader *bufio.Reader
}

// Close closes the hijacked connection and reader.
func (h *HijackedResponse) Close() {
	h.Conn.Close()
}

// CloseWriter is an interface that implement structs
// that close input streams to prevent from writing.
type CloseWriter interface {
	CloseWrite() error
}

// CloseWrite closes a readWriter for writing.
func (h *HijackedResponse) CloseWrite() error {
	if conn, ok := h.Conn.(CloseWriter); ok {
		return conn.CloseWrite()
	}
	return nil
}

// ImageBuildOptions holds the information
// necessary to build images.
type ImageBuildOptions struct {
	Tags           []string
	SuppressOutput bool
	RemoteContext  string
	NoCache        bool
	Remove         bool
	ForceRemove    bool
	PullParent     bool
	IsolationLevel container.IsolationLevel
	CPUSetCPUs     string
	CPUSetMems     string
	CPUShares      int64
	CPUQuota       int64
	CPUPeriod      int64
	Memory         int64
	MemorySwap     int64
	CgroupParent   string
	ShmSize        int64
	Dockerfile     string
	Ulimits        []*units.Ulimit
	BuildArgs      map[string]string
	AuthConfigs    map[string]AuthConfig
	Context        io.Reader
}

// ImageBuildResponse holds information
// returned by a server after building
// an image.
type ImageBuildResponse struct {
	Body   io.ReadCloser
	OSType string
}

// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
	Parent       string // Parent is the name of the image to pull
	Tag          string // Tag is the name to tag this image with
	RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
}

// ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct {
	Source         io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName)
	SourceName     string    // SourceName is the name of the image to pull (mutually exclusive with Source)
	RepositoryName string    // RepositoryName is the name of the repository to import this image into
	Message        string    // Message is the message to tag the image with
	Tag            string    // Tag is the name to tag this image with
	Changes        []string  // Changes are the raw changes to apply to this image
}

// ImageListOptions holds parameters to filter the list of images with.
type ImageListOptions struct {
	MatchName string
	All       bool
	Filters   filters.Args
}

// ImageLoadResponse returns information to the client about a load process.
type ImageLoadResponse struct {
	Body io.ReadCloser
	JSON bool
}

// ImagePullOptions holds information to pull images.
type ImagePullOptions struct {
	ImageID      string // ImageID is the name of the image to pull
	Tag          string // Tag is the name of the tag to be pulled
	RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
}

//ImagePushOptions holds information to push images.
type ImagePushOptions ImagePullOptions

// ImageRemoveOptions holds parameters to remove images.
type ImageRemoveOptions struct {
	ImageID       string
	Force         bool
	PruneChildren bool
}

// ImageSearchOptions holds parameters to search images with.
type ImageSearchOptions struct {
	Term         string
	RegistryAuth string
}

// ImageTagOptions holds parameters to tag an image
type ImageTagOptions struct {
	ImageID        string
	RepositoryName string
	Tag            string
	Force          bool
}

// ResizeOptions holds parameters to resize a tty.
// It can be used to resize container ttys and
// exec process ttys too.
type ResizeOptions struct {
	ID     string
	Height int
	Width  int
}

// VersionResponse holds version information for the client and the server
type VersionResponse struct {
	Client *Version
	Server *Version
}

// ServerOK return true when the client could connect to the docker server
// and parse the information received. It returns false otherwise.
func (v VersionResponse) ServerOK() bool {
	return v.Server != nil
}
<|endoftext|>


<commit_before>package hybrid

import (
	"math"

	"github.com/ready-steady/adapt/algorithm"
	"github.com/ready-steady/adapt/algorithm/internal"
	"github.com/ready-steady/adapt/grid"
)

const (
	none = ^uint(0)
)

var (
	infinity = math.Inf(1.0)
)

// Strategy is a basic strategy.
type Strategy struct {
	ni uint
	no uint

	guide Guide

	lmin uint
	lmax uint
	εl   float64
	εt   float64

	active *internal.Active
	hash   *internal.Hash
	unique *internal.Unique

	lndices []lndex
	indices []index

	lcursor map[string]uint
	icursor map[string]uint
}

// Guide is a grid-refinement tool of a basic strategy.
type Guide interface {
	grid.Indexer
	grid.RefinerToward
}

type lndex struct {
	score float64
	scope []uint
}

type index struct {
	score float64
}

// NewStrategy creates a basic strategy.
func NewStrategy(inputs, outputs uint, guide Guide, minLevel, maxLevel uint,
	localError, totalError float64) *Strategy {

	return &Strategy{
		ni: inputs,
		no: outputs,

		guide: guide,

		lmin: minLevel,
		lmax: maxLevel,
		εl:   localError,
		εt:   totalError,

		active: internal.NewActive(inputs),
		hash:   internal.NewHash(inputs),
		unique: internal.NewUnique(inputs),

		lcursor: make(map[string]uint),
		icursor: make(map[string]uint),
	}
}

func (self *Strategy) First(surrogate *algorithm.Surrogate) *algorithm.State {
	return self.initiate(self.active.First(), surrogate)
}

func (self *Strategy) Next(state *algorithm.State,
	surrogate *algorithm.Surrogate) *algorithm.State {

	for {
		self.consume(state)
		if self.check() {
			return nil
		}
		k := self.choose()
		if k == none {
			return nil
		}
		state = self.initiate(self.active.Next(k), surrogate)
		if len(state.Indices) > 0 {
			return state
		}
	}
}

func (self *Strategy) Score(element *algorithm.Element) float64 {
	return internal.MaxAbsolute(element.Surplus) * element.Volume
}

func (self *Strategy) check() bool {
	total := 0.0
	for i := range self.active.Positions {
		total += self.lndices[i].score
		if total > self.εt {
			return false
		}
	}
	return true
}

func (self *Strategy) choose() uint {
	if len(self.active.Positions) == 0 {
		return none
	}
	k, max := none, 0.0
	for i := range self.active.Positions {
		value := self.lndices[i].score
		if k == none || value > max || (value == max && k > i) {
			k, max = i, value
		}
	}
	if max <= 0.0 {
		return none
	}
	return k
}

func (self *Strategy) consume(state *algorithm.State) {
	ni := self.ni
	nol, noi := uint(len(self.lndices)), uint(len(self.indices))
	nnl, nni := uint(len(state.Counts)), uint(len(state.Scores))

	levels := internal.Levelize(state.Lndices, ni)

	groups := state.Data.([][]uint64)

	self.lndices = append(self.lndices, make([]lndex, nnl)...)
	lndices := self.lndices[nol:]

	self.indices = append(self.indices, make([]index, nni)...)
	indices := self.indices[noi:]

	for i, offset := uint(0), uint(0); i < nnl; i++ {
		count := state.Counts[i]
		if levels[i] < uint64(self.lmin) {
			for j := uint(0); j < count; j++ {
				indices[offset+j].score = infinity
			}
		} else if levels[i] < uint64(self.lmax) {
			for j := uint(0); j < count; j++ {
				indices[offset+j].score = state.Scores[offset+j]
			}
		}
		for j := uint(0); j < count; j++ {
			index := state.Indices[(offset+j)*ni : (offset+j+1)*ni]
			self.icursor[self.hash.Key(index)] = noi + offset + j
		}
		offset += count
	}

	for i := uint(0); i < nnl; i++ {
		count := uint(len(groups[i])) / ni
		scope := make([]uint, count)
		for j := uint(0); j < count; j++ {
			index := groups[i][j*ni : (j+1)*ni]
			k, ok := self.icursor[self.hash.Key(index)]
			if !ok {
				panic("something went wrong")
			}
			scope[j] = k
		}
		lndices[i].scope = scope
		for _, j := range scope {
			lndices[i].score = math.Max(lndices[i].score, self.indices[j].score)
		}
		lndex := state.Lndices[i*ni : (i+1)*ni]
		self.lcursor[self.hash.Key(lndex)] = nol + i
	}
}

func (self *Strategy) index(lndices []uint64, surrogate *algorithm.Surrogate) [][]uint64 {
	ni := self.ni
	nn := uint(len(lndices)) / ni
	groups := make([][]uint64, nn)
	for i := uint(0); i < nn; i++ {
		root, lndex := true, lndices[i*ni:(i+1)*ni]
		for j := uint(0); j < ni; j++ {
			level := lndex[j]
			if level == 0 {
				continue
			}
			lndex[j] = level - 1
			k, ok := self.lcursor[self.hash.Key(lndex)]
			lndex[j] = level
			if !ok {
				panic("something went wrong")
			}
			for _, l := range self.lndices[k].scope {
				if self.indices[l].score >= self.εl {
					index := surrogate.Indices[l*ni : (l+1)*ni]
					groups[i] = append(groups[i], self.guide.RefineToward(index, j)...)
				}
			}
			root = false
		}
		if root {
			groups[i] = append(groups[i], self.guide.Index(lndex)...)
		}
	}
	return groups
}

func (self *Strategy) initiate(lndices []uint64,
	surrogate *algorithm.Surrogate) (state *algorithm.State) {

	groups := self.index(lndices, surrogate)
	nn := uint(len(groups))
	state = &algorithm.State{
		Lndices: lndices,
		Counts:  make([]uint, nn),
		Data:    groups,
	}
	for i := uint(0); i < nn; i++ {
		indices := self.unique.Distil(groups[i])
		state.Indices = append(state.Indices, indices...)
		state.Counts[i] = uint(len(indices)) / self.ni
	}
	return
}
<commit_msg>a/hybrid: get rid of the index struct<commit_after>package hybrid

import (
	"math"

	"github.com/ready-steady/adapt/algorithm"
	"github.com/ready-steady/adapt/algorithm/internal"
	"github.com/ready-steady/adapt/grid"
)

const (
	none = ^uint(0)
)

var (
	infinity = math.Inf(1.0)
)

// Strategy is a basic strategy.
type Strategy struct {
	ni uint
	no uint

	guide Guide

	lmin uint
	lmax uint
	εl   float64
	εt   float64

	active *internal.Active
	hash   *internal.Hash
	unique *internal.Unique

	lndices []lndex
	scores  []float64

	lcursor map[string]uint
	icursor map[string]uint
}

// Guide is a grid-refinement tool of a basic strategy.
type Guide interface {
	grid.Indexer
	grid.RefinerToward
}

type lndex struct {
	score float64
	scope []uint
}

// NewStrategy creates a basic strategy.
func NewStrategy(inputs, outputs uint, guide Guide, minLevel, maxLevel uint,
	localError, totalError float64) *Strategy {

	return &Strategy{
		ni: inputs,
		no: outputs,

		guide: guide,

		lmin: minLevel,
		lmax: maxLevel,
		εl:   localError,
		εt:   totalError,

		active: internal.NewActive(inputs),
		hash:   internal.NewHash(inputs),
		unique: internal.NewUnique(inputs),

		lcursor: make(map[string]uint),
		icursor: make(map[string]uint),
	}
}

func (self *Strategy) First(surrogate *algorithm.Surrogate) *algorithm.State {
	return self.initiate(self.active.First(), surrogate)
}

func (self *Strategy) Next(state *algorithm.State,
	surrogate *algorithm.Surrogate) *algorithm.State {

	for {
		self.consume(state)
		if self.check() {
			return nil
		}
		k := self.choose()
		if k == none {
			return nil
		}
		state = self.initiate(self.active.Next(k), surrogate)
		if len(state.Indices) > 0 {
			return state
		}
	}
}

func (self *Strategy) Score(element *algorithm.Element) float64 {
	return internal.MaxAbsolute(element.Surplus) * element.Volume
}

func (self *Strategy) check() bool {
	total := 0.0
	for i := range self.active.Positions {
		total += self.lndices[i].score
		if total > self.εt {
			return false
		}
	}
	return true
}

func (self *Strategy) choose() uint {
	if len(self.active.Positions) == 0 {
		return none
	}
	k, max := none, 0.0
	for i := range self.active.Positions {
		value := self.lndices[i].score
		if k == none || value > max || (value == max && k > i) {
			k, max = i, value
		}
	}
	if max <= 0.0 {
		return none
	}
	return k
}

func (self *Strategy) consume(state *algorithm.State) {
	ni := self.ni
	nl := uint(len(self.lndices))
	nn := uint(len(state.Counts))
	ns := uint(len(self.scores))

	levels := internal.Levelize(state.Lndices, ni)

	groups := state.Data.([][]uint64)

	self.lndices = append(self.lndices, make([]lndex, nn)...)
	lndices := self.lndices[nl:]

	self.scores = append(self.scores, state.Scores...)
	scores := self.scores[ns:]

	for i, offset := uint(0), uint(0); i < nn; i++ {
		count := state.Counts[i]
		if levels[i] < uint64(self.lmin) {
			for j := uint(0); j < count; j++ {
				scores[offset+j] = infinity
			}
		} else if levels[i] >= uint64(self.lmax) {
			for j := uint(0); j < count; j++ {
				scores[offset+j] = 0.0
			}
		}
		for j := uint(0); j < count; j++ {
			index := state.Indices[(offset+j)*ni : (offset+j+1)*ni]
			self.icursor[self.hash.Key(index)] = ns + offset + j
		}
		offset += count
	}

	for i := uint(0); i < nn; i++ {
		count := uint(len(groups[i])) / ni
		scope := make([]uint, count)
		for j := uint(0); j < count; j++ {
			index := groups[i][j*ni : (j+1)*ni]
			k, ok := self.icursor[self.hash.Key(index)]
			if !ok {
				panic("something went wrong")
			}
			scope[j] = k
		}
		lndices[i].scope = scope
		for _, j := range scope {
			lndices[i].score = math.Max(lndices[i].score, self.scores[j])
		}
		lndex := state.Lndices[i*ni : (i+1)*ni]
		self.lcursor[self.hash.Key(lndex)] = nl + i
	}
}

func (self *Strategy) index(lndices []uint64, surrogate *algorithm.Surrogate) [][]uint64 {
	ni := self.ni
	nn := uint(len(lndices)) / ni
	groups := make([][]uint64, nn)
	for i := uint(0); i < nn; i++ {
		root, lndex := true, lndices[i*ni:(i+1)*ni]
		for j := uint(0); j < ni; j++ {
			level := lndex[j]
			if level == 0 {
				continue
			}
			lndex[j] = level - 1
			k, ok := self.lcursor[self.hash.Key(lndex)]
			lndex[j] = level
			if !ok {
				panic("something went wrong")
			}
			for _, l := range self.lndices[k].scope {
				if self.scores[l] >= self.εl {
					index := surrogate.Indices[l*ni : (l+1)*ni]
					groups[i] = append(groups[i], self.guide.RefineToward(index, j)...)
				}
			}
			root = false
		}
		if root {
			groups[i] = append(groups[i], self.guide.Index(lndex)...)
		}
	}
	return groups
}

func (self *Strategy) initiate(lndices []uint64,
	surrogate *algorithm.Surrogate) (state *algorithm.State) {

	groups := self.index(lndices, surrogate)
	nn := uint(len(groups))
	state = &algorithm.State{
		Lndices: lndices,
		Counts:  make([]uint, nn),
		Data:    groups,
	}
	for i := uint(0); i < nn; i++ {
		indices := self.unique.Distil(groups[i])
		state.Indices = append(state.Indices, indices...)
		state.Counts[i] = uint(len(indices)) / self.ni
	}
	return
}
<|endoftext|>


<commit_before>package internal

// Active is a book-keeper of active level indices.
type Active struct {
	Indices   []uint64      // Level indices considered so far
	Positions map[uint]bool // Positions of active level indices

	ni   uint
	nn   uint
	lmax uint

	forward  reference
	backward reference
}

type reference map[uint]uint

// NewActive creates a book-keeper.
func NewActive(ni, lmax uint) *Active {
	return &Active{
		ni:   ni,
		lmax: lmax,
	}
}

// Next identifies, activates, and returns admissible level indices from the
// forward neighborhood of a level index.
func (self *Active) Next(k uint) (indices []uint64) {
	if self.Indices == nil {
		self.Indices, self.Positions = make([]uint64, 1*self.ni), map[uint]bool{0: true}
		self.nn, self.forward, self.backward = 1, make(reference), make(reference)
		return self.Indices
	}

	ni, nn := self.ni, self.nn
	positions, forward, backward := self.Positions, self.forward, self.backward

	index := self.Indices[k*ni : (k+1)*ni]

outer:
	for i := uint(0); i < ni; i++ {
		if index[i] >= uint64(self.lmax) {
			continue
		}

		newBackward := make(reference)
		for j := uint(0); j < ni; j++ {
			if i == j || index[j] == 0 {
				continue
			}
			if l, ok := forward[backward[k*ni+j]*ni+i]; !ok || positions[l] {
				continue outer
			} else {
				newBackward[j] = l
			}
		}
		newBackward[i] = k
		for j, l := range newBackward {
			forward[l*ni+j] = nn
			backward[nn*ni+j] = l
		}

		self.Indices = append(self.Indices, index...)
		self.Indices[nn*ni+i]++

		positions[nn] = true

		nn++
	}

	indices = self.Indices[self.nn*ni:]
	self.nn = nn

	return
}

// Drop deactivates a level index.
func (self *Active) Drop(k uint) {
	delete(self.Positions, k)
}
<commit_msg>a/internal: add Norms to Active<commit_after>package internal

// Active is a book-keeper of active level indices.
type Active struct {
	Indices   []uint64      // Level indices considered so far
	Norms     []uint64      // Manhattan norms of level indices
	Positions map[uint]bool // Positions of active level indices

	ni   uint
	lmax uint

	forward  reference
	backward reference
}

type reference map[uint]uint

// NewActive creates a book-keeper.
func NewActive(ni, lmax uint) *Active {
	return &Active{
		ni:   ni,
		lmax: lmax,
	}
}

// Next identifies, activates, and returns admissible level indices from the
// forward neighborhood of a level index.
func (self *Active) Next(k uint) (indices []uint64) {
	if self.Indices == nil {
		self.Indices, self.Norms = make([]uint64, 1*self.ni), []uint64{0}
		self.Positions = map[uint]bool{0: true}
		self.forward, self.backward = make(reference), make(reference)
		return self.Indices
	}

	ni, no := self.ni, uint(len(self.Norms))
	positions, forward, backward := self.Positions, self.forward, self.backward

	index, norm := self.Indices[k*ni:(k+1)*ni], self.Norms[k]

outer:
	for i, nn := uint(0), no; i < ni; i++ {
		if index[i] >= uint64(self.lmax) {
			continue
		}

		newBackward := make(reference)
		for j := uint(0); j < ni; j++ {
			if i == j || index[j] == 0 {
				continue
			}
			if l, ok := forward[backward[k*ni+j]*ni+i]; !ok || positions[l] {
				continue outer
			} else {
				newBackward[j] = l
			}
		}
		newBackward[i] = k
		for j, l := range newBackward {
			forward[l*ni+j] = nn
			backward[nn*ni+j] = l
		}

		self.Indices = append(self.Indices, index...)
		self.Indices[nn*ni+i]++
		self.Norms = append(self.Norms, norm+1)

		positions[nn] = true

		nn++
	}

	indices = self.Indices[no*ni:]
	return
}

// Drop deactivates a level index.
func (self *Active) Drop(k uint) {
	delete(self.Positions, k)
}
<|endoftext|>


<commit_before>// +build win32

package signals

import (
	"os"
	"os/signal"
)

func Handle() {
	// TODO: Something about SIGHUP for Windows, stdin could be used
	chnl := make(chan os.Signal)
	signal.Notify(chnl, os.Interrupt)
	go func(chnl chan os.Signal) {
		for sig := chnl {
			switch sig {
			case os.Interrupt:
				// this also closes listeners
				interrupted()
				// XXX: put any win32 specific cleanup here as needed
				return
			}
		}
	}(chnl)
}
<commit_msg>Fixing win32.go<commit_after>// +build win32

package signals

import (
	"os"
	"os/signal"
)

func Handle() {
	// TODO: Something about SIGHUP for Windows, stdin could be used
	chnl := make(chan os.Signal)
	signal.Notify(chnl, os.Interrupt)
	go func(chnl chan os.Signal) {
		for sig := range chnl {
			switch sig {
			case os.Interrupt:
				// this also closes listeners
				interrupted()
				// XXX: put any win32 specific cleanup here as needed
				return
			}
		}
	}(chnl)
}
<|endoftext|>


<commit_before>package main

import (

	// _ "ruby/hooks"
	"os"
	"path/filepath"
	"ruby/cache"
	"ruby/supply"
	"ruby/versions"
	"time"

	"github.com/cloudfoundry/libbuildpack"
)

func main() {
	logger := libbuildpack.NewLogger(os.Stdout)

	buildpackDir, err := libbuildpack.GetBuildpackDir()
	if err != nil {
		logger.Error("Unable to determine buildpack directory: %s", err.Error())
		os.Exit(9)
	}

	manifest, err := libbuildpack.NewManifest(buildpackDir, logger, time.Now())
	if err != nil {
		logger.Error("Unable to load buildpack manifest: %s", err.Error())
		os.Exit(10)
	}

	installer := libbuildpack.NewInstaller(manifest)

	stager := libbuildpack.NewStager(os.Args[1:], logger, manifest)
	if err := stager.CheckBuildpackValid(); err != nil {
		os.Exit(11)
	}

	if err = installer.SetAppCacheDir(stager.CacheDir()); err != nil {
		logger.Error("Unable to setup app cache dir: %s", err)
		os.Exit(18)
	}

	if err = manifest.ApplyOverride(stager.DepsDir()); err != nil {
		logger.Error("Unable to apply override.yml files: %s", err)
		os.Exit(17)
	}

	err = libbuildpack.RunBeforeCompile(stager)
	if err != nil {
		logger.Error("Before Compile: %s", err.Error())
		os.Exit(12)
	}

	if err := os.MkdirAll(filepath.Join(stager.DepDir(), "bin"), 0755); err != nil {
		logger.Error("Unable to create bin directory: %s", err.Error())
		os.Exit(13)
	}

	err = stager.SetStagingEnvironment()
	if err != nil {
		logger.Error("Unable to setup environment variables: %s", err.Error())
		os.Exit(14)
	}

	cacher, err := cache.New(stager, logger, libbuildpack.NewYAML())
	if err != nil {
		logger.Error("Unable to create cacher: %s", err.Error())
		os.Exit(14)
	}

	s := supply.Supplier{
		Stager:    stager,
		Manifest:  manifest,
		Installer: installer,
		Log:       logger,
		Versions:  versions.New(stager.BuildDir(), manifest),
		Cache:     cacher,
		Command:   &libbuildpack.Command{},
	}

	err = supply.Run(&s)
	if err != nil {
		os.Exit(15)
	}

	if err := stager.WriteConfigYml(nil); err != nil {
		logger.Error("Error writing config.yml: %s", err.Error())
		os.Exit(16)
	}

	if err = installer.CleanupAppCache(); err != nil {
		logger.Error("Unable to clean up app cache: %s", err)
		os.Exit(19)
	}
}
<commit_msg>Also, create the Supplier with a TempDir.<commit_after>package main

import (

	// _ "ruby/hooks"
	"os"
	"path/filepath"
	"ruby/cache"
	"ruby/supply"
	"ruby/versions"
	"time"

	"github.com/cloudfoundry/libbuildpack"
)

func main() {
	logger := libbuildpack.NewLogger(os.Stdout)

	buildpackDir, err := libbuildpack.GetBuildpackDir()
	if err != nil {
		logger.Error("Unable to determine buildpack directory: %s", err.Error())
		os.Exit(9)
	}

	manifest, err := libbuildpack.NewManifest(buildpackDir, logger, time.Now())
	if err != nil {
		logger.Error("Unable to load buildpack manifest: %s", err.Error())
		os.Exit(10)
	}

	installer := libbuildpack.NewInstaller(manifest)

	stager := libbuildpack.NewStager(os.Args[1:], logger, manifest)
	if err := stager.CheckBuildpackValid(); err != nil {
		os.Exit(11)
	}

	if err = installer.SetAppCacheDir(stager.CacheDir()); err != nil {
		logger.Error("Unable to setup app cache dir: %s", err)
		os.Exit(18)
	}

	if err = manifest.ApplyOverride(stager.DepsDir()); err != nil {
		logger.Error("Unable to apply override.yml files: %s", err)
		os.Exit(17)
	}

	err = libbuildpack.RunBeforeCompile(stager)
	if err != nil {
		logger.Error("Before Compile: %s", err.Error())
		os.Exit(12)
	}

	if err := os.MkdirAll(filepath.Join(stager.DepDir(), "bin"), 0755); err != nil {
		logger.Error("Unable to create bin directory: %s", err.Error())
		os.Exit(13)
	}

	err = stager.SetStagingEnvironment()
	if err != nil {
		logger.Error("Unable to setup environment variables: %s", err.Error())
		os.Exit(14)
	}

	cacher, err := cache.New(stager, logger, libbuildpack.NewYAML())
	if err != nil {
		logger.Error("Unable to create cacher: %s", err.Error())
		os.Exit(14)
	}

	s := supply.Supplier{
		Stager:    stager,
		Manifest:  manifest,
		Installer: installer,
		Log:       logger,
		Versions:  versions.New(stager.BuildDir(), manifest),
		Cache:     cacher,
		Command:   &libbuildpack.Command{},
		TempDir:   &supply.LinuxTempDir{Log: logger},
	}

	err = supply.Run(&s)
	if err != nil {
		os.Exit(15)
	}

	if err := stager.WriteConfigYml(nil); err != nil {
		logger.Error("Error writing config.yml: %s", err.Error())
		os.Exit(16)
	}

	if err = installer.CleanupAppCache(); err != nil {
		logger.Error("Unable to clean up app cache: %s", err)
		os.Exit(19)
	}
}
<|endoftext|>


<commit_before>package resourcepool

import (
	"container/list"
	"errors"
	"log"
	"net"
	"sync"
	"syscall"
	"time"
)

const DefaultPoolSize = 32
const DefaultGetTimeoutSecond = 3

type ResourcePool struct {
	lock         sync.Mutex
	host         string
	port         string
	creationFunc ClientCreationFunc
	closeFunc    ClientCloseFunc
	maxSize      int
	getTimeout   int
	busyList     list.List
	idleList     chan interface{}
}

// ClientCreationFunc is the function used for creating new client.
type ClientCreationFunc func(host, port string) (interface{}, error)

// ClientCloseFunc is the function used for closing client.
type ClientCloseFunc func(interface{}) error

// AddServer adds a new server to the pool.
func NewResourcePool(host, port string, fnCreation ClientCreationFunc, fnClose ClientCloseFunc, maxSize, getTimeout int) (*ResourcePool, error) {
	pool := ResourcePool{
		maxSize:      maxSize,
		host:         host,
		port:         port,
		creationFunc: fnCreation,
		closeFunc:    fnClose,
		getTimeout:   getTimeout,
		idleList:     make(chan interface{}, maxSize),
	}
	return &pool, nil
}

// Get retrives a connection from the pool.
func (pool *ResourcePool) Get() (interface{}, error) {
	var res interface{}
	var err error
	select {
	// try get without block to see if resource is already available
	case res = <-pool.idleList:
	default:
		res = nil
	}

	if res != nil {
		pool.lock.Lock()
		defer pool.lock.Unlock()
		pool.busyList.PushBack(res)
		return res, nil
	} else if pool.Count() < pool.maxSize {
		res, err = pool.creationFunc(pool.host, pool.port)
		if err != nil {
			log.Println("resource creation failed: ", err)
		} else {
			pool.idleList <- res
		}
	}

	if pool.getTimeout != 0 {
		select {
		case res = <-pool.idleList:
		case <-time.After(time.Second * time.Duration(pool.getTimeout)):
			res = nil
			err = errors.New("get resource timed out")
		}
	} else {
		select {
		case res = <-pool.idleList:
		}
	}
	if err == nil {
		pool.lock.Lock()
		defer pool.lock.Unlock()
		pool.busyList.PushBack(res)
	}
	return res, err
}

// Release puts the connection back to the pool.
func (pool *ResourcePool) Release(c interface{}) error {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	element := pool.busyList.Front()
	for {
		if element == nil {
			return errors.New("the resource isn't found in the pool, is it a managed resource?")
		}
		if c == element.Value {
			select {
			case pool.idleList <- c:
				pool.busyList.Remove(element)
				return nil
			default:
				pool.closeFunc(c)
				return errors.New("the resource can't be put to idle list")
			}
		}
		element = element.Next()
	}
}

// CheckError destroies the connection when necessary by checking error.
func (pool *ResourcePool) CheckError(c interface{}, err error) error {
	if err == nil {
		return nil
	}
	switch err.(type) {
	case net.Error, syscall.EPIPE:
		pool.lock.Lock()
		defer pool.lock.Unlock()
		element := pool.busyList.Front()
		for {
			if element == nil {
				return errors.New("the resource isn't found in the pool, is it a managed resource?")
			}
			if c == element.Value {
				log.Println("encountered a network error, destory the connection now")
				pool.busyList.Remove(element)
				pool.closeFunc(c)
				return nil
			}
			element = element.Next()
		}
	default:
		return nil
	}
}

// Destroy disconnects all connectsions.
func (pool *ResourcePool) Destroy() error {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	if pool.busyList.Len() < 1 {
		return errors.New("not all managed resources are free, can't destory now")
	}
	close(pool.idleList)
	for res := range pool.idleList {
		pool.closeFunc(res)
	}
	return nil
}

// Replace replaces existing connections to oldServer with connections to newServer.
func (pool *ResourcePool) Replace(oldHost, oldPort, newHost, newPort string) {
	pool.lock.Lock()
	defer pool.lock.Unlock()
}

// Count returns total number of connections in the pool.
func (pool *ResourcePool) Count() int {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	return len(pool.idleList) + pool.busyList.Len()
}
<commit_msg>be aggresive at CheckError<commit_after>package resourcepool

import (
	"container/list"
	"errors"
	"log"
	"sync"
	"time"
)

const DefaultPoolSize = 32
const DefaultGetTimeoutSecond = 3

type ResourcePool struct {
	lock         sync.Mutex
	host         string
	port         string
	creationFunc ClientCreationFunc
	closeFunc    ClientCloseFunc
	maxSize      int
	getTimeout   int
	busyList     list.List
	idleList     chan interface{}
}

// ClientCreationFunc is the function used for creating new client.
type ClientCreationFunc func(host, port string) (interface{}, error)

// ClientCloseFunc is the function used for closing client.
type ClientCloseFunc func(interface{}) error

// AddServer adds a new server to the pool.
func NewResourcePool(host, port string, fnCreation ClientCreationFunc, fnClose ClientCloseFunc, maxSize, getTimeout int) (*ResourcePool, error) {
	pool := ResourcePool{
		maxSize:      maxSize,
		host:         host,
		port:         port,
		creationFunc: fnCreation,
		closeFunc:    fnClose,
		getTimeout:   getTimeout,
		idleList:     make(chan interface{}, maxSize),
	}
	return &pool, nil
}

// Get retrives a connection from the pool.
func (pool *ResourcePool) Get() (interface{}, error) {
	var res interface{}
	var err error
	select {
	// try get without block to see if resource is already available
	case res = <-pool.idleList:
	default:
		res = nil
	}

	if res != nil {
		pool.lock.Lock()
		defer pool.lock.Unlock()
		pool.busyList.PushBack(res)
		return res, nil
	} else if pool.Count() < pool.maxSize {
		res, err = pool.creationFunc(pool.host, pool.port)
		if err != nil {
			log.Println("resource creation failed: ", err)
		} else {
			pool.idleList <- res
		}
	}

	if pool.getTimeout != 0 {
		select {
		case res = <-pool.idleList:
		case <-time.After(time.Second * time.Duration(pool.getTimeout)):
			res = nil
			err = errors.New("get resource timed out")
		}
	} else {
		select {
		case res = <-pool.idleList:
		}
	}
	if err == nil {
		pool.lock.Lock()
		defer pool.lock.Unlock()
		pool.busyList.PushBack(res)
	}
	return res, err
}

// Release puts the connection back to the pool.
func (pool *ResourcePool) Release(c interface{}) error {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	element := pool.busyList.Front()
	for {
		if element == nil {
			return errors.New("the resource isn't found in the pool, is it a managed resource?")
		}
		if c == element.Value {
			select {
			case pool.idleList <- c:
				pool.busyList.Remove(element)
				return nil
			default:
				pool.closeFunc(c)
				return errors.New("the resource can't be put to idle list")
			}
		}
		element = element.Next()
	}
}

// CheckError destroies the connection when necessary by checking error.
func (pool *ResourcePool) CheckError(c interface{}, err error) error {
	if err == nil {
		return nil
	}
	pool.lock.Lock()
	defer pool.lock.Unlock()
	element := pool.busyList.Front()
	for {
		if element == nil {
			return errors.New("the resource isn't found in the pool, is it a managed resource?")
		}
		if c == element.Value {
			log.Println("encountered an error, destory the connection now")
			pool.busyList.Remove(element)
			pool.closeFunc(c)
			return nil
		}
		element = element.Next()
	}
	return nil
}

// Destroy disconnects all connectsions.
func (pool *ResourcePool) Destroy() error {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	if pool.busyList.Len() < 1 {
		return errors.New("not all managed resources are free, can't destory now")
	}
	close(pool.idleList)
	for res := range pool.idleList {
		pool.closeFunc(res)
	}
	return nil
}

// Replace replaces existing connections to oldServer with connections to newServer.
func (pool *ResourcePool) Replace(oldHost, oldPort, newHost, newPort string) {
	pool.lock.Lock()
	defer pool.lock.Unlock()
}

// Count returns total number of connections in the pool.
func (pool *ResourcePool) Count() int {
	pool.lock.Lock()
	defer pool.lock.Unlock()
	return len(pool.idleList) + pool.busyList.Len()
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 errors_test

import (
	"bytes"
	goerr "errors"
	"fmt"
	"strings"
	"testing"

	"github.com/corestoreio/csfw/util/errors"
	"github.com/stretchr/testify/assert"
)

var _ error = (*errors.MultiErr)(nil)

func TestMultiErrors(t *testing.T) {
	errStr := errors.NewMultiErr(
		errors.New("Err1"),
		errors.New("Err2"),
		errors.New("Err3"),
	).Error()

	assert.Regexp(t,
		"Err1\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:32\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:610\nErr2\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:33\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:610\nErr3\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:34\ntesting.tRunner\n\t.+/testing/testing.go:610\n",
		errStr,
	)
}

func TestMultiAppend(t *testing.T) {

	e := errors.NewMultiErr().AppendErrors(
		errors.New("Err5"),
		nil,
		errors.New("Err6"),
		errors.New("Err7"),
	)
	assert.True(t, e.HasErrors())
	assert.Regexp(t,
		"Err5\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:46\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:610\nErr6\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:48\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:610\nErr7\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:49\ntesting.tRunner\n\t.+/testing/testing.go:610\n",
		e.Error(),
	)
}

func TestMultiEmpty(t *testing.T) {

	assert.False(t, errors.NewMultiErr(nil, nil).HasErrors())
	assert.Equal(t, "", errors.NewMultiErr(nil).Error())
}

func TestHasErrorsNil(t *testing.T) {

	var e *errors.MultiErr
	assert.False(t, e.HasErrors())

	e = &errors.MultiErr{}
	assert.False(t, e.HasErrors())
}

func TestMultiAppendToNil(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors(errors.New("Err74"))

	assert.True(t, e.HasErrors())
	assert.Regexp(t, "Err74\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppendToNil\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:76\ntesting.tRunner\n\t.+/testing/testing.go:610\n", e.Error())
}

func xxxTestMultiErr_CustomFormatter(t *testing.T) {

	m1 := errors.NewMultiErr(errors.New("Hello1"))
	m1.AppendErrors(
		errors.NewMultiErr(errors.NewAlreadyClosedf("Brain"),
			errors.NewNotFoundf("Mind"),
		),
		errors.New("Hello2"),
	)

	assert.Regexp(t,
		"Hello1\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErr_CustomFormatter\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:84\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:610\nAlready closed\ngithub.com/corestoreio/csfw/util/errors.NewAlreadyClosedf\n\t.+/github.com/corestoreio/csfw/util/errors/behaviour.go:414: Brain\nNot found\ngithub.com/corestoreio/csfw/util/errors.NewNotFoundf\n\t.+/github.com/corestoreio/csfw/util/errors/behaviour.go:234: Mind\nHello2\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErr_CustomFormatter\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:89\ntesting.tRunner\n\t.+/testing/testing.go:610\n",
		m1.Error())

	m1.Formatter = func(errs []error) string {
		var buf bytes.Buffer
		for _, err := range errs {
			buf.WriteString(`* `)
			buf.WriteString(err.Error())
			buf.WriteRune('\n')
		}
		return buf.String()
	}
	assert.Exactly(t,
		"* Hello1\n* Brain: Already closed\n* Mind: Not found\n* Hello2\n",
		m1.Error())
}

func TestMultiAppendNilToNil1(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors()
	assert.False(t, e.HasErrors())
	assert.Nil(t, e)
}

func TestMultiAppendNilToNil2(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors(nil, nil)
	assert.False(t, e.HasErrors())
	assert.Nil(t, e)
}

func TestMultiAppendRecursive(t *testing.T) {

	me := errors.NewMultiErr(goerr.New("Err1")).
		AppendErrors(errors.NewMultiErr(goerr.New("Err2"), errors.NewMultiErr(goerr.New("Err3"))))
	assert.Exactly(t, "Err1\nErr2\nErr3\n", me.Error())
	fmtd := fmt.Sprintf("%#v", me)
	// "&errors.MultiErr{errs:[]error{(*errors.errorString)(0xc82000f590), (*errors.errorString)(0xc82000f5b0), (*errors.errorString)(0xc82000f5c0)}, details:false}" (actual)
	assert.Exactly(t, 1, strings.Count(fmtd, "MultiErr"))
	assert.Exactly(t, 3, strings.Count(fmtd, "*errors.errorString"))
}

var _ error = (*errors.Error)(nil)

func TestError(t *testing.T) {
	const err errors.Error = "I'm a constant Error"
	assert.EqualError(t, err, "I'm a constant Error")
}

func TestMultiErrContainsAll(t *testing.T) {
	tests := []struct {
		me   error
		vf   []errors.BehaviourFunc
		want bool
	}{
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.New("random"), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{nil, []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound}, true}, // 5
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsTemporary}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid, errors.IsAlreadyExists}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsAlreadyClosed, errors.IsNotValid, errors.IsAlreadyExists}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), nil, false},
		{errors.NewMultiErr(nil), nil, false},
		{nil, nil, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2"), errors.NewMultiErr(errors.Error("r3"), errors.NewMultiErr(errors.Error("r4"), errors.NewNotImplementedf("r5")))),
			[]errors.BehaviourFunc{errors.IsNotImplemented},
			true},
	}
	for i, test := range tests {
		if have, want := errors.MultiErrContainsAll(test.me, test.vf...), test.want; have != want {
			t.Errorf("Index %d: Have %t Want %t", i, have, want)
		}
	}
}

func TestMultiErrContainsAny(t *testing.T) {
	tests := []struct {
		me   error
		vf   []errors.BehaviourFunc
		want bool
	}{
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.New("random"), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{nil, []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound}, true},                     // 5
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsTemporary}, true}, // 6 different to All
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid, errors.IsAlreadyExists}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsAlreadyClosed, errors.IsNotValid, errors.IsAlreadyExists}, true}, // 9 different to All
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), nil, false},
		{errors.NewMultiErr(nil), nil, false},
		{nil, nil, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2"), errors.NewMultiErr(errors.Error("r3"), errors.NewMultiErr(errors.Error("r4"), errors.NewNotImplementedf("r5")))),
			[]errors.BehaviourFunc{errors.IsNotImplemented},
			true},
	}
	for i, test := range tests {
		if have, want := errors.MultiErrContainsAny(test.me, test.vf...), test.want; have != want {
			t.Errorf("Index %d: Have %t Want %t", i, have, want)
		}
	}
}
<commit_msg>util/errors: Fix tests<commit_after>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 errors_test

import (
	"bytes"
	goerr "errors"
	"fmt"
	"strings"
	"testing"

	"github.com/corestoreio/csfw/util/errors"
	"github.com/stretchr/testify/assert"
)

var _ error = (*errors.MultiErr)(nil)

func TestMultiErrors(t *testing.T) {
	errStr := errors.NewMultiErr(
		errors.New("Err1"),
		errors.New("Err2"),
		errors.New("Err3"),
	).Error()

	assert.Regexp(t,
		"Err1\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:32\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:[0-9]+\nErr2\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:33\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:[0-9]+\nErr3\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErrors\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:34\ntesting.tRunner\n\t.+/testing/testing.go:[0-9]+\n",
		errStr,
	)
}

func TestMultiAppend(t *testing.T) {

	e := errors.NewMultiErr().AppendErrors(
		errors.New("Err5"),
		nil,
		errors.New("Err6"),
		errors.New("Err7"),
	)
	assert.True(t, e.HasErrors())
	assert.Regexp(t,
		"Err5\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:46\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:[0-9]+\nErr6\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:48\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:[0-9]+\nErr7\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppend\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:49\ntesting.tRunner\n\t.+/testing/testing.go:[0-9]+\n",
		e.Error(),
	)
}

func TestMultiEmpty(t *testing.T) {

	assert.False(t, errors.NewMultiErr(nil, nil).HasErrors())
	assert.Equal(t, "", errors.NewMultiErr(nil).Error())
}

func TestHasErrorsNil(t *testing.T) {

	var e *errors.MultiErr
	assert.False(t, e.HasErrors())

	e = &errors.MultiErr{}
	assert.False(t, e.HasErrors())
}

func TestMultiAppendToNil(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors(errors.New("Err74"))

	assert.True(t, e.HasErrors())
	assert.Regexp(t, "Err74\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiAppendToNil\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:76\ntesting.tRunner\n\t.+/testing/testing.go:[0-9]+\n", e.Error())
}

func xxxTestMultiErr_CustomFormatter(t *testing.T) {

	m1 := errors.NewMultiErr(errors.New("Hello1"))
	m1.AppendErrors(
		errors.NewMultiErr(errors.NewAlreadyClosedf("Brain"),
			errors.NewNotFoundf("Mind"),
		),
		errors.New("Hello2"),
	)

	assert.Regexp(t,
		"Hello1\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErr_CustomFormatter\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:84\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:[0-9]+\nAlready closed\ngithub.com/corestoreio/csfw/util/errors.NewAlreadyClosedf\n\t.+/github.com/corestoreio/csfw/util/errors/behaviour.go:414: Brain\nNot found\ngithub.com/corestoreio/csfw/util/errors.NewNotFoundf\n\t.+/github.com/corestoreio/csfw/util/errors/behaviour.go:234: Mind\nHello2\ngithub.com/corestoreio/csfw/util/errors_test.TestMultiErr_CustomFormatter\n\t.+/github.com/corestoreio/csfw/util/errors/multierr_test.go:89\ntesting.tRunner\n\t.+/testing/testing.go:[0-9]+\n",
		m1.Error())

	m1.Formatter = func(errs []error) string {
		var buf bytes.Buffer
		for _, err := range errs {
			buf.WriteString(`* `)
			buf.WriteString(err.Error())
			buf.WriteRune('\n')
		}
		return buf.String()
	}
	assert.Exactly(t,
		"* Hello1\n* Brain: Already closed\n* Mind: Not found\n* Hello2\n",
		m1.Error())
}

func TestMultiAppendNilToNil1(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors()
	assert.False(t, e.HasErrors())
	assert.Nil(t, e)
}

func TestMultiAppendNilToNil2(t *testing.T) {

	var e *errors.MultiErr
	e = e.AppendErrors(nil, nil)
	assert.False(t, e.HasErrors())
	assert.Nil(t, e)
}

func TestMultiAppendRecursive(t *testing.T) {

	me := errors.NewMultiErr(goerr.New("Err1")).
		AppendErrors(errors.NewMultiErr(goerr.New("Err2"), errors.NewMultiErr(goerr.New("Err3"))))
	assert.Exactly(t, "Err1\nErr2\nErr3\n", me.Error())
	fmtd := fmt.Sprintf("%#v", me)
	// "&errors.MultiErr{errs:[]error{(*errors.errorString)(0xc82000f590), (*errors.errorString)(0xc82000f5b0), (*errors.errorString)(0xc82000f5c0)}, details:false}" (actual)
	assert.Exactly(t, 1, strings.Count(fmtd, "MultiErr"))
	assert.Exactly(t, 3, strings.Count(fmtd, "*errors.errorString"))
}

var _ error = (*errors.Error)(nil)

func TestError(t *testing.T) {
	const err errors.Error = "I'm a constant Error"
	assert.EqualError(t, err, "I'm a constant Error")
}

func TestMultiErrContainsAll(t *testing.T) {
	tests := []struct {
		me   error
		vf   []errors.BehaviourFunc
		want bool
	}{
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.New("random"), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{nil, []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound}, true}, // 5
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsTemporary}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid, errors.IsAlreadyExists}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsAlreadyClosed, errors.IsNotValid, errors.IsAlreadyExists}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), nil, false},
		{errors.NewMultiErr(nil), nil, false},
		{nil, nil, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2"), errors.NewMultiErr(errors.Error("r3"), errors.NewMultiErr(errors.Error("r4"), errors.NewNotImplementedf("r5")))),
			[]errors.BehaviourFunc{errors.IsNotImplemented},
			true},
	}
	for i, test := range tests {
		if have, want := errors.MultiErrContainsAll(test.me, test.vf...), test.want; have != want {
			t.Errorf("Index %d: Have %t Want %t", i, have, want)
		}
	}
}

func TestMultiErrContainsAny(t *testing.T) {
	tests := []struct {
		me   error
		vf   []errors.BehaviourFunc
		want bool
	}{
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1")), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.New("random"), []errors.BehaviourFunc{errors.IsNotFound}, false},
		{nil, []errors.BehaviourFunc{errors.IsNotFound}, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound}, true},                     // 5
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsTemporary}, true}, // 6 different to All
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsNotFound, errors.IsNotValid, errors.IsAlreadyExists}, true},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), []errors.BehaviourFunc{errors.IsAlreadyClosed, errors.IsNotValid, errors.IsAlreadyExists}, true}, // 9 different to All
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2")), nil, false},
		{errors.NewMultiErr(nil), nil, false},
		{nil, nil, false},
		{errors.NewMultiErr(nil, errors.NewNotValidf("r1"), errors.NewNotFoundf("r2"), errors.NewMultiErr(errors.Error("r3"), errors.NewMultiErr(errors.Error("r4"), errors.NewNotImplementedf("r5")))),
			[]errors.BehaviourFunc{errors.IsNotImplemented},
			true},
	}
	for i, test := range tests {
		if have, want := errors.MultiErrContainsAny(test.me, test.vf...), test.want; have != want {
			t.Errorf("Index %d: Have %t Want %t", i, have, want)
		}
	}
}
<|endoftext|>