<commit_before>// Copyright 2015 Kazuhisa TAKEI<xtakei@me.com>. All rights reserved.
// Use of this source code is governed by MPL-2.0 license tha can be
// found in the LICENSE file

// Package buffer_list implements a double linked list with sequencial buffer data.
//
// To Get New First Data from buffer_list(l is a *List)
//		type Hoge Struct {
//			a int
//			b int
//		}
//		l := buffer_list.New(Hoge{})
//		hoge := l.GetElement(),Value().(*Hoge)
//		hoge.a = 1
//		hoge.b = 2
// To iterate over a list
//		for e := l.Front(); e != nil ; e = e.Next() {
//			a := (*Hoge)(e.Value())  // Hoge is Value type
//			// do something
//		}

package buffer_list

import (
	"fmt" // FIXME remove
	"reflect"
	"sync"
	"unsafe"
)

const (
	DEFAULT_BUF_SIZE = 1024
)

type Element struct {
	list      *List
	next      *Element
	prev      *Element
	old_value unsafe.Pointer
	value     interface{}
}

type List struct {
	Used      *Element
	Freed     *Element
	SizeElm   int64
	SizeData  int64
	Used_idx  int64
	Value_inf interface{}
	elms      []byte
	datas     []byte
	Len       int
	m         sync.Mutex
	cast_f    func(interface{}) interface{}
	pointers  map[uintptr]map[int]unsafe.Pointer
}

func New(first_value interface{}, buf_cnt int) (l *List) {
	l = new(List).Init(first_value, buf_cnt)
	l.pointers = make(map[uintptr]map[int]unsafe.Pointer)
	return l
}

func (e *Element) Commit() {
	e.List().Pick_ptr(e)
}
func (e *Element) DumpPicks() string {
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	return fmt.Sprintf("%#v", e.list.pointers[uintptr(v_ptr)])
}
func (e *Element) IsPicked(i interface{}) bool {
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	f_ptr := unsafe.Pointer(reflect.ValueOf(i).Pointer())

	l := e.list

	if l.pointers[uintptr(v_ptr)] == nil {
		return false
	}
	for i := 0; i < f_num; i++ {
		if l.pointers[uintptr(v_ptr)][i] == f_ptr {
			return true
		}
	}
	return false
}

func (e *Element) free_pick_ptr() {
	l := e.list
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()

	if l.pointers[uintptr(v_ptr)] == nil {
		return
	}

	for i := 0; i < f_num; i++ {
		if l.pointers[uintptr(v_ptr)][i] != nil {
			//			fmt.Println("free value.member", i, l.pointers[uintptr(v_ptr)][i])

			delete(l.pointers[uintptr(v_ptr)], i)
		}
	}
}

func (l *List) Pick_ptr(e *Element) {
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	if l.pointers[uintptr(v_ptr)] == nil {
		l.pointers[uintptr(v_ptr)] = make(map[int]unsafe.Pointer)
	}

	for i := 0; i < f_num; i++ {
		m := reflect.ValueOf(e.Value()).Elem().Field(i)
		switch m.Kind() {
		case reflect.UnsafePointer:
			fallthrough
		case reflect.String:
			fallthrough
		case reflect.Slice:
			fallthrough
		case reflect.Map:
			fallthrough
		case reflect.Chan:
			fallthrough
		case reflect.Array:
			fallthrough
		case reflect.Func:
			fallthrough
		case reflect.Ptr:
			l.pointers[uintptr(v_ptr)][i] = unsafe.Pointer(m.Pointer())
		case reflect.Interface:
			if m.Elem().Kind() == reflect.Ptr {
				l.pointers[uintptr(v_ptr)][i] = unsafe.Pointer(m.Elem().Pointer())
			}
		default:
		}

	}
}

func (l *List) GetDataPtr() uintptr {
	return uintptr(unsafe.Pointer(&l.datas[0]))
}
func (l *List) getElemData(idx int64) *Element {
	elm := (*Element)(unsafe.Pointer(&l.elms[int(l.SizeElm)*int(idx)]))
	elm.value = reflect.NewAt(l.TypeOfValue_inf(), unsafe.Pointer(&l.datas[int(l.SizeData)*int(idx)])).Interface()
	return elm
}
func (l *List) GetElement() *Element {
	return l.Used
}
func (e *Element) Next() *Element {
	e.list.m.Lock()
	defer e.list.m.Unlock()

	if e.next != nil {
		return e.next
	} else {
		return nil
	}
}

func (e *Element) Prev() *Element {
	e.list.m.Lock()
	defer e.list.m.Unlock()

	if e.prev != nil {
		return e.prev
	} else {
		return nil
	}
}

func (e *Element) Value() interface{} {
	return e.value
}

func (e *Element) Free() {

	e.list.m.Lock()
	defer e.list.m.Unlock()

	for ee := e.list.Used; ee != nil; ee = ee.next {
		if e == ee {
			goto DO_FREE
		}
	}

	//	fmt.Println("dont Free() e is not used ")
	return

DO_FREE:
	//	fmt.Println("do Free()")

	at := e.prev
	n := e.next
	if at.next == e {
		at.next = n
	}
	if n != nil {
		n.prev = at
	}

	e.list.Len -= 1

	if e.list.Used == e {
		e.list.Used = n
	}
	// move to free buffer
	if e.list.Freed == nil {
		e.prev = nil
		e.next = nil
		e.list.Freed = e
	} else {
		f_at := e.list.Freed
		e.next = f_at
		e.prev = nil
		f_at.prev = e
		e.list.Freed = e
	}
	e.free_pick_ptr()
}

func (e *Element) InitValue() {

	e.free_pick_ptr()

	diff := int(uint64(reflect.ValueOf(e.value).Pointer()) - uint64(uintptr(unsafe.Pointer(&e.list.datas[0]))))

	for i := range e.list.datas[diff : diff+int(e.list.SizeData)-1] {
		e.list.datas[diff+i] = 0
	}

	return
	//	fmt.Println(ref_byte, databyte)
}
func (l *List) newFirstElem() *Element {
	var e *Element

	//	l.m.Lock()
	//	defer l.m.Unlock()

	if l.Freed == nil {
		e = l.getElemData(l.Used_idx)
		l.Used_idx += 1
	} else {
		e = l.Freed
		if l.Freed.next == nil {
			l.Freed = nil
		} else {
			l.Freed = l.Freed.next
			l.Freed.prev = nil
		}
	}
	e.prev = e
	e.next = nil
	e.list = l
	if l.Used == nil {
		l.Used = e
	}
	l.Len++
	return e
}
func (l *list) InsertLast() *Element {
	return l.InsertNewElem(l.Back())
}

func (l *List) InsertNewElem(at *Element) *Element {
	var e *Element

	l.m.Lock()
	defer l.m.Unlock()

	if l.Len == 0 && at == nil {
		return l.newFirstElem()
	}

	if l != at.list {
		return nil
	}

	if l.Freed == nil {
		e = l.getElemData(l.Used_idx)
		l.Used_idx += 1
	} else {
		e = l.Freed
		e.prev = nil
		e.next = nil
		if l.Freed.next == nil {
			l.Freed = nil
		} else {
			l.Freed = l.Freed.next
			l.Freed.prev = nil
		}
	}
	e.list = l
	n := at.next
	at.next = e
	e.prev = at
	if n != nil {
		n.prev = e
		e.next = n
	} else {
		e.list.Used.prev = e
	}

	l.Len++
	return e
}

func (l *List) TypeOfValue_inf() reflect.Type {
	if reflect.TypeOf(l.Value_inf).Kind() == reflect.Ptr {
		return reflect.ValueOf(l.Value_inf).Elem().Type()
	} else {
		return reflect.TypeOf(l.Value_inf)
	}
}
func (l *List) Cap() int {
	return len(l.elms) / int(l.SizeElm)
}

func (l *List) Init(first_value interface{}, value_len int) *List {
	l.m.Lock()
	defer l.m.Unlock()
	if l.Used == nil {
		var buf_len int64
		if value_len < 1024 {
			buf_len = int64(DEFAULT_BUF_SIZE)
		} else {
			buf_len = int64(value_len)
		}
		l.Value_inf = first_value
		l.SizeData = int64(l.TypeOfValue_inf().Size())
		l.SizeElm = int64(reflect.TypeOf(Element{}).Size())
		l.elms = make([]byte, buf_len*l.SizeElm,
			buf_len*l.SizeElm)
		l.datas = make([]byte, buf_len*l.SizeData,
			buf_len*l.SizeData)
		elm := (*Element)(unsafe.Pointer(&l.elms[0]))
		elm.value = reflect.NewAt(l.TypeOfValue_inf(), unsafe.Pointer(&l.datas[0])).Interface()
		elm.prev = elm
		elm.next = nil
		elm.list = l
		l.Used = elm
		l.Freed = nil
		l.Used_idx = 1
		l.Len = 1
	}
	return l
}

func (l *List) Front() *Element {
	l.m.Lock()
	defer l.m.Unlock()

	return l.Used
}

func (l *List) Back() *Element {
	l.m.Lock()
	defer l.m.Unlock()

	if l.Used == nil {
		return nil
	} else {
		return l.Used.prev
	}
}

func (l *List) Inf() interface{} {
	return l.Value_inf
}

func (l *List) Value() interface{} {
	return l.Used.value
}
func (l *List) SetCastFunc(f func(val interface{}) interface{}) {
	l.cast_f = f
}

func (e *Element) List() *List {
	return e.list
}

func (e *Element) ValueWithCast() interface{} {
	return e.list.cast_f(e.Value())
}
<commit_msg>fix typo<commit_after>// Copyright 2015 Kazuhisa TAKEI<xtakei@me.com>. All rights reserved.
// Use of this source code is governed by MPL-2.0 license tha can be
// found in the LICENSE file

// Package buffer_list implements a double linked list with sequencial buffer data.
//
// To Get New First Data from buffer_list(l is a *List)
//		type Hoge Struct {
//			a int
//			b int
//		}
//		l := buffer_list.New(Hoge{})
//		hoge := l.GetElement(),Value().(*Hoge)
//		hoge.a = 1
//		hoge.b = 2
// To iterate over a list
//		for e := l.Front(); e != nil ; e = e.Next() {
//			a := (*Hoge)(e.Value())  // Hoge is Value type
//			// do something
//		}

package buffer_list

import (
	"fmt" // FIXME remove
	"reflect"
	"sync"
	"unsafe"
)

const (
	DEFAULT_BUF_SIZE = 1024
)

type Element struct {
	list      *List
	next      *Element
	prev      *Element
	old_value unsafe.Pointer
	value     interface{}
}

type List struct {
	Used      *Element
	Freed     *Element
	SizeElm   int64
	SizeData  int64
	Used_idx  int64
	Value_inf interface{}
	elms      []byte
	datas     []byte
	Len       int
	m         sync.Mutex
	cast_f    func(interface{}) interface{}
	pointers  map[uintptr]map[int]unsafe.Pointer
}

func New(first_value interface{}, buf_cnt int) (l *List) {
	l = new(List).Init(first_value, buf_cnt)
	l.pointers = make(map[uintptr]map[int]unsafe.Pointer)
	return l
}

func (e *Element) Commit() {
	e.List().Pick_ptr(e)
}
func (e *Element) DumpPicks() string {
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	return fmt.Sprintf("%#v", e.list.pointers[uintptr(v_ptr)])
}
func (e *Element) IsPicked(i interface{}) bool {
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	f_ptr := unsafe.Pointer(reflect.ValueOf(i).Pointer())

	l := e.list

	if l.pointers[uintptr(v_ptr)] == nil {
		return false
	}
	for i := 0; i < f_num; i++ {
		if l.pointers[uintptr(v_ptr)][i] == f_ptr {
			return true
		}
	}
	return false
}

func (e *Element) free_pick_ptr() {
	l := e.list
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()

	if l.pointers[uintptr(v_ptr)] == nil {
		return
	}

	for i := 0; i < f_num; i++ {
		if l.pointers[uintptr(v_ptr)][i] != nil {
			//			fmt.Println("free value.member", i, l.pointers[uintptr(v_ptr)][i])

			delete(l.pointers[uintptr(v_ptr)], i)
		}
	}
}

func (l *List) Pick_ptr(e *Element) {
	f_num := reflect.ValueOf(e.Value()).Elem().NumField()
	v_ptr := reflect.ValueOf(e.Value()).Pointer()
	if l.pointers[uintptr(v_ptr)] == nil {
		l.pointers[uintptr(v_ptr)] = make(map[int]unsafe.Pointer)
	}

	for i := 0; i < f_num; i++ {
		m := reflect.ValueOf(e.Value()).Elem().Field(i)
		switch m.Kind() {
		case reflect.UnsafePointer:
			fallthrough
		case reflect.String:
			fallthrough
		case reflect.Slice:
			fallthrough
		case reflect.Map:
			fallthrough
		case reflect.Chan:
			fallthrough
		case reflect.Array:
			fallthrough
		case reflect.Func:
			fallthrough
		case reflect.Ptr:
			l.pointers[uintptr(v_ptr)][i] = unsafe.Pointer(m.Pointer())
		case reflect.Interface:
			if m.Elem().Kind() == reflect.Ptr {
				l.pointers[uintptr(v_ptr)][i] = unsafe.Pointer(m.Elem().Pointer())
			}
		default:
		}

	}
}

func (l *List) GetDataPtr() uintptr {
	return uintptr(unsafe.Pointer(&l.datas[0]))
}
func (l *List) getElemData(idx int64) *Element {
	elm := (*Element)(unsafe.Pointer(&l.elms[int(l.SizeElm)*int(idx)]))
	elm.value = reflect.NewAt(l.TypeOfValue_inf(), unsafe.Pointer(&l.datas[int(l.SizeData)*int(idx)])).Interface()
	return elm
}
func (l *List) GetElement() *Element {
	return l.Used
}
func (e *Element) Next() *Element {
	e.list.m.Lock()
	defer e.list.m.Unlock()

	if e.next != nil {
		return e.next
	} else {
		return nil
	}
}

func (e *Element) Prev() *Element {
	e.list.m.Lock()
	defer e.list.m.Unlock()

	if e.prev != nil {
		return e.prev
	} else {
		return nil
	}
}

func (e *Element) Value() interface{} {
	return e.value
}

func (e *Element) Free() {

	e.list.m.Lock()
	defer e.list.m.Unlock()

	for ee := e.list.Used; ee != nil; ee = ee.next {
		if e == ee {
			goto DO_FREE
		}
	}

	//	fmt.Println("dont Free() e is not used ")
	return

DO_FREE:
	//	fmt.Println("do Free()")

	at := e.prev
	n := e.next
	if at.next == e {
		at.next = n
	}
	if n != nil {
		n.prev = at
	}

	e.list.Len -= 1

	if e.list.Used == e {
		e.list.Used = n
	}
	// move to free buffer
	if e.list.Freed == nil {
		e.prev = nil
		e.next = nil
		e.list.Freed = e
	} else {
		f_at := e.list.Freed
		e.next = f_at
		e.prev = nil
		f_at.prev = e
		e.list.Freed = e
	}
	e.free_pick_ptr()
}

func (e *Element) InitValue() {

	e.free_pick_ptr()

	diff := int(uint64(reflect.ValueOf(e.value).Pointer()) - uint64(uintptr(unsafe.Pointer(&e.list.datas[0]))))

	for i := range e.list.datas[diff : diff+int(e.list.SizeData)-1] {
		e.list.datas[diff+i] = 0
	}

	return
	//	fmt.Println(ref_byte, databyte)
}
func (l *List) newFirstElem() *Element {
	var e *Element

	//	l.m.Lock()
	//	defer l.m.Unlock()

	if l.Freed == nil {
		e = l.getElemData(l.Used_idx)
		l.Used_idx += 1
	} else {
		e = l.Freed
		if l.Freed.next == nil {
			l.Freed = nil
		} else {
			l.Freed = l.Freed.next
			l.Freed.prev = nil
		}
	}
	e.prev = e
	e.next = nil
	e.list = l
	if l.Used == nil {
		l.Used = e
	}
	l.Len++
	return e
}
func (l *List) InsertLast() *Element {
	return l.InsertNewElem(l.Back())
}

func (l *List) InsertNewElem(at *Element) *Element {
	var e *Element

	l.m.Lock()
	defer l.m.Unlock()

	if l.Len == 0 && at == nil {
		return l.newFirstElem()
	}

	if l != at.list {
		return nil
	}

	if l.Freed == nil {
		e = l.getElemData(l.Used_idx)
		l.Used_idx += 1
	} else {
		e = l.Freed
		e.prev = nil
		e.next = nil
		if l.Freed.next == nil {
			l.Freed = nil
		} else {
			l.Freed = l.Freed.next
			l.Freed.prev = nil
		}
	}
	e.list = l
	n := at.next
	at.next = e
	e.prev = at
	if n != nil {
		n.prev = e
		e.next = n
	} else {
		e.list.Used.prev = e
	}

	l.Len++
	return e
}

func (l *List) TypeOfValue_inf() reflect.Type {
	if reflect.TypeOf(l.Value_inf).Kind() == reflect.Ptr {
		return reflect.ValueOf(l.Value_inf).Elem().Type()
	} else {
		return reflect.TypeOf(l.Value_inf)
	}
}
func (l *List) Cap() int {
	return len(l.elms) / int(l.SizeElm)
}

func (l *List) Init(first_value interface{}, value_len int) *List {
	l.m.Lock()
	defer l.m.Unlock()
	if l.Used == nil {
		var buf_len int64
		if value_len < 1024 {
			buf_len = int64(DEFAULT_BUF_SIZE)
		} else {
			buf_len = int64(value_len)
		}
		l.Value_inf = first_value
		l.SizeData = int64(l.TypeOfValue_inf().Size())
		l.SizeElm = int64(reflect.TypeOf(Element{}).Size())
		l.elms = make([]byte, buf_len*l.SizeElm,
			buf_len*l.SizeElm)
		l.datas = make([]byte, buf_len*l.SizeData,
			buf_len*l.SizeData)
		elm := (*Element)(unsafe.Pointer(&l.elms[0]))
		elm.value = reflect.NewAt(l.TypeOfValue_inf(), unsafe.Pointer(&l.datas[0])).Interface()
		elm.prev = elm
		elm.next = nil
		elm.list = l
		l.Used = elm
		l.Freed = nil
		l.Used_idx = 1
		l.Len = 1
	}
	return l
}

func (l *List) Front() *Element {
	l.m.Lock()
	defer l.m.Unlock()

	return l.Used
}

func (l *List) Back() *Element {
	l.m.Lock()
	defer l.m.Unlock()

	if l.Used == nil {
		return nil
	} else {
		return l.Used.prev
	}
}

func (l *List) Inf() interface{} {
	return l.Value_inf
}

func (l *List) Value() interface{} {
	return l.Used.value
}
func (l *List) SetCastFunc(f func(val interface{}) interface{}) {
	l.cast_f = f
}

func (e *Element) List() *List {
	return e.list
}

func (e *Element) ValueWithCast() interface{} {
	return e.list.cast_f(e.Value())
}
<|endoftext|>


<commit_before>package cl11

import (
	"math/rand"
	"reflect"
	"testing"
)

func TestBuffer(t *testing.T) {
	allDevices := getDevices(t)
	for _, device := range allDevices {

		var toRelease []Object
		size := int64(1024 * 1024)

		ctx, err := CreateContext([]*Device{device}, []ContextProperties{}, nil, nil)
		if err != nil {
			t.Error(err)
			continue
		}
		toRelease = append(toRelease, ctx)

		cq, err := ctx.CreateCommandQueue(device, 0)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, cq)

		host0, err := ctx.CreateHostBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, host0)

		host1, err := ctx.CreateHostBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, host1)

		device0, err := ctx.CreateDeviceBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, device0)

		map0, err := cq.EnqueueMapBuffer(host0, Blocking, MapWrite, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		values := map0.Float32Slice()
		for i := range values {
			values[i] = rand.Float32()
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(host0, device0, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(device0, host1, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		map0, err = cq.EnqueueMapBuffer(host0, Blocking, MapRead, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		map1, err := cq.EnqueueMapBuffer(host1, Blocking, MapRead, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		want := map0.Float32Slice()
		got := map1.Float32Slice()
		if !reflect.DeepEqual(want, got) {
			t.Error("values mismatch")
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueUnmapBuffer(map1, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		want = make([]float32, int(size)/int(float32Size))
		got = make([]float32, int(size)/int(float32Size))
		for i := range want {
			want[i] = rand.Float32()
		}

		err = cq.EnqueueWriteBuffer(host0, NonBlocking, 0, want, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(host0, device0, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(device0, host1, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueReadBuffer(host1, Blocking, 0, got, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		if !reflect.DeepEqual(want, got) {
			t.Error("values mismatch")
		}

		releaseAll(toRelease, t)
	}
}
<commit_msg>Fixed test on mac.<commit_after>package cl11

import (
	"math/rand"
	"reflect"
	"testing"
)

func TestBuffer(t *testing.T) {
	allDevices := getDevices(t)
	for _, device := range allDevices {

		var toRelease []Object
		size := int64(1024 * 1024)

		ctx, err := CreateContext([]*Device{device}, nil, nil, nil)
		if err != nil {
			t.Error(err)
			continue
		}
		toRelease = append(toRelease, ctx)

		cq, err := ctx.CreateCommandQueue(device, 0)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, cq)

		host0, err := ctx.CreateHostBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, host0)

		host1, err := ctx.CreateHostBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, host1)

		device0, err := ctx.CreateDeviceBuffer(size, MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, device0)

		map0, err := cq.EnqueueMapBuffer(host0, Blocking, MapWrite, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		values := map0.Float32Slice()
		for i := range values {
			values[i] = rand.Float32()
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(host0, device0, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(device0, host1, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		map0, err = cq.EnqueueMapBuffer(host0, Blocking, MapRead, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		map1, err := cq.EnqueueMapBuffer(host1, Blocking, MapRead, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		want := map0.Float32Slice()
		got := map1.Float32Slice()
		if !reflect.DeepEqual(want, got) {
			t.Error("values mismatch")
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueUnmapBuffer(map1, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		want = make([]float32, int(size)/int(float32Size))
		got = make([]float32, int(size)/int(float32Size))
		for i := range want {
			want[i] = rand.Float32()
		}

		err = cq.EnqueueWriteBuffer(host0, NonBlocking, 0, want, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(host0, device0, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueCopyBuffer(device0, host1, 0, 0, size, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueReadBuffer(host1, Blocking, 0, got, nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		if !reflect.DeepEqual(want, got) {
			t.Error("values mismatch")
		}

		releaseAll(toRelease, t)
	}
}
<|endoftext|>


<commit_before>package buffstreams

import ()

import (
	"encoding/binary"
	"errors"
	"log"
	"net"
	"sync"
)

type BuffManager struct {
	dialedConnections map[string]*net.TCPConn
	listeningSockets  map[string]*net.TCPListener
	// TODO find a way to sanely provide this to a Dialer or a Receiver on a per-connection basis
	MaxMessageSizeBitLength int
	EnableLogging           bool
	// TODO I could control access to the maps better if I centralized how they got accessed - less locking code littered around
	sync.RWMutex
}

type BuffManagerConfig struct {
	MaxMessageSize int
	EnableLogging  bool
}

func New(cfg BuffManagerConfig) *BuffManager {
	bm := &BuffManager{
		dialedConnections: make(map[string]*net.TCPConn),
		listeningSockets:  make(map[string]*net.TCPListener),
		EnableLogging:     cfg.EnableLogging,
	}
	maxMessageSize := 4096
	// 0 is the default, and the message must be atleast 1 byte large
	if cfg.MaxMessageSize != 0 {
		maxMessageSize = cfg.MaxMessageSize
	}
	bm.MaxMessageSizeBitLength = MessageSizeToBitLength(maxMessageSize)
	return bm
}

type ListenCallback func([]byte) error

// Incase someone wants a programmtically correct way to format an address/port
// for use with StartListening or WriteTo
func FormatAddress(address string, port string) string {
	return address + ":" + port
}

func (bm *BuffManager) StartListening(port string, cb ListenCallback) error {
	address := FormatAddress("", port)
	tcpAddr, err := net.ResolveTCPAddr("tcp", address)
	receiveSocket, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return err
	}
	bm.startListening(address, receiveSocket, cb)
	return nil
}

func (bm *BuffManager) startListening(address string, socket *net.TCPListener, cb ListenCallback) {
	bm.Lock()
	bm.listeningSockets[address] = socket
	bm.Unlock()

	go func(address string, maxMessageSizeBitLength int, enableLogging bool, listener net.Listener) {
		for {
			// Wait for someone to connect
			conn, err := listener.Accept()
			if err != nil {
				if enableLogging == true {
					log.Print("Error attempting to accept connection")
					log.Print(err)
				}
			} else {
				// Hand this off and immediately listen for more
				go handleListenedConn(address, conn, bm.MaxMessageSizeBitLength, enableLogging, cb)
			}
		}
	}(address, bm.MaxMessageSizeBitLength, bm.EnableLogging, socket)
}

func handleListenedConn(address string, conn net.Conn, maxMessageSize int, enableLogging bool, cb ListenCallback) {
	for {
		// Handle getting the data header
		headerByteSize := maxMessageSize
		headerBuffer := make([]byte, headerByteSize)
		// First, read the number of bytes required to determine the message length
		_, err := readFromConnection(conn, headerBuffer)
		if err != nil && err.Error() == "EOF" {
			// Log the error we got from the call to read
			if enableLogging == true {
				log.Printf("Address %s: Client closed connection", address)
				log.Print(err)
			}
			conn.Close()
			return
		}

		// Now turn that buffer of bytes into an integer - represnts size of message body
		msgLength, bytesParsed := binary.Uvarint(headerBuffer)
		// Not sure what the correct way to handle these errors are. For now, bomb out
		if bytesParsed == 0 {
			// "Buffer too small"
			if enableLogging == true {
				log.Printf("Address %s: 0 Bytes parsed from header", address)
				log.Print(err)
			}
			conn.Close()
			return
		} else if bytesParsed < 0 {
			// "Buffer overflow"
			if enableLogging == true {
				log.Printf("Address %s: Buffer Less than zero bytes parsed from header", address)
				log.Print(err)
			}
			conn.Close()
			return
		}
		dataBuffer := make([]byte, msgLength)
		bytesLen, err := readFromConnection(conn, dataBuffer)
		if err != nil && err.Error() == "EOF" {
			// log the error from the call to read
			if enableLogging == true {
				log.Printf("Address %s: Failure to read from connection", address)
				log.Print(err)
			}
			conn.Close()
			return
		}

		// If we read bytes, there wasn't an error, or if there was it was only EOF
		// And readbytes + EOF is normal, just as readbytes + no err, next read 0 bytes EOF
		// So... we take action on the actual message data
		if bytesLen > 0 && (err == nil || (err != nil && err.Error() == "EOF")) {
			// I ultimately have some design choices here
			// Currently, I am invoking a delegate thats been passed down the stack
			// I could...
			// Just push it onto a queue (not a slow ass channel, but a queue)
			// which has a reference passed down to it, and the main process
			// spawns a goroutine to reap off the queue and handle those in parallel

			// Callback, atm
			err = cb(dataBuffer)
			if err != nil && enableLogging == true {
				log.Printf("Error in Callback")
				log.Print(err)
			}
		}
	}
}

func readFromConnection(reader net.Conn, buffer []byte) (int, error) {
	// This fills the buffer
	bytesLen, err := reader.Read(buffer)
	// Output the content of the bytes to the queue
	if bytesLen == 0 {
		if err != nil && err.Error() == "EOF" {
			// "End of individual transmission"
			// We're just done reading from that conn
			return bytesLen, err
		}
	}

	if err != nil {
		//"Underlying network failure?"
		// Not sure what this error would be, but it could exist and i've seen it handled
		// as a general case in other networking code. Following in the footsteps of (greatness|madness)
	}
	// Read some bytes, return the length
	return bytesLen, nil
}

func (bm *BuffManager) dialOut(address string) (*net.TCPConn, error) {
	bm.RLock()
	if _, ok := bm.dialedConnections[address]; ok == true {
		bm.RUnlock()
		// Need to clean it out on any error...
		return nil, errors.New("You have a connection to this ip and port open already")
	}
	bm.RUnlock()
	tcpAddr, err := net.ResolveTCPAddr("tcp", address)
	if err != nil {
		return nil, err
	}
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return nil, err
	} else {
		// Store the connection, it's valid
		bm.Lock()
		bm.dialedConnections[address] = conn
		bm.Unlock()
	}
	return conn, nil
}

// closeDialer uses explicit lock semantics vs defers to better control
// when the lock gets released to reduce contention
func (bm *BuffManager) closeDialer(address string) error {
	// Get a read lock to look up that the connection exists
	bm.RLock()
	if conn, ok := bm.dialedConnections[address]; ok != true {
		// Release immediately
		bm.RUnlock()
		err := conn.Close()
		// Grab lock to delete from the map
		bm.Lock()
		delete(bm.dialedConnections, address)
		// Release immediately
		bm.Unlock()
		return err
	}
	// Release the lock incase it didn't exist
	bm.RUnlock()
	return nil
}

// Write data and dial out if the conn isn't open
func (bm *BuffManager) WriteTo(address string, data []byte, persist bool) (int, error) {
	var conn net.Conn
	var err error
	var ok bool

	// Get the connection if it's cached, or open a new one
	bm.RLock()
	conn, ok = bm.dialedConnections[address]
	bm.RUnlock()
	if ok != true {
		conn, err = bm.dialOut(address)
		if err != nil {
			// Error dialing out, cannot write
			// bail
			return 0, err
		}
	}
	// Calculate how big the message is, using a consistent header size.
	toWriteLen := UInt16ToByteArray(uint16(len(data)), bm.MaxMessageSizeBitLength)
	// Append the size to the message, so now it has a header
	toWrite := append(toWriteLen, data...)
	// Writes are threadsafe in net.Conns
	written, err := conn.Write(toWrite)

	if err != nil || persist == false {
		if err != nil && bm.EnableLogging == true {
			log.Printf("Error while writing data to %s", address)
			log.Print(err)
		}
		err = bm.closeDialer(address)
		conn = nil
		if err != nil {
			// TODO ponder the following:
			// Error closing the dialer, should we still return 0 written?
			// What if some bytes written, then failure, then also the close throws an error
			// []error is a better return type, but not sure if thats a thing you're supposed to do...
			// Possibilities for error not as complicated as i'm thinking?
			if bm.EnableLogging == true {
				// The error will get returned up the stack, no need to log it here?
				log.Print("There was a subsequent error cleaning up the connection to %s")
			}
			return 0, err
		}
	}
	// Return the bytes written, any error
	return written, err
}
<commit_msg>Better logging on write failures<commit_after>package buffstreams

import ()

import (
	"encoding/binary"
	"errors"
	"log"
	"net"
	"sync"
)

type BuffManager struct {
	dialedConnections map[string]*net.TCPConn
	listeningSockets  map[string]*net.TCPListener
	// TODO find a way to sanely provide this to a Dialer or a Receiver on a per-connection basis
	MaxMessageSizeBitLength int
	EnableLogging           bool
	// TODO I could control access to the maps better if I centralized how they got accessed - less locking code littered around
	sync.RWMutex
}

type BuffManagerConfig struct {
	MaxMessageSize int
	EnableLogging  bool
}

func New(cfg BuffManagerConfig) *BuffManager {
	bm := &BuffManager{
		dialedConnections: make(map[string]*net.TCPConn),
		listeningSockets:  make(map[string]*net.TCPListener),
		EnableLogging:     cfg.EnableLogging,
	}
	maxMessageSize := 4096
	// 0 is the default, and the message must be atleast 1 byte large
	if cfg.MaxMessageSize != 0 {
		maxMessageSize = cfg.MaxMessageSize
	}
	bm.MaxMessageSizeBitLength = MessageSizeToBitLength(maxMessageSize)
	return bm
}

type ListenCallback func([]byte) error

// Incase someone wants a programmtically correct way to format an address/port
// for use with StartListening or WriteTo
func FormatAddress(address string, port string) string {
	return address + ":" + port
}

func (bm *BuffManager) StartListening(port string, cb ListenCallback) error {
	address := FormatAddress("", port)
	tcpAddr, err := net.ResolveTCPAddr("tcp", address)
	receiveSocket, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return err
	}
	bm.startListening(address, receiveSocket, cb)
	return nil
}

func (bm *BuffManager) startListening(address string, socket *net.TCPListener, cb ListenCallback) {
	bm.Lock()
	bm.listeningSockets[address] = socket
	bm.Unlock()

	go func(address string, maxMessageSizeBitLength int, enableLogging bool, listener net.Listener) {
		for {
			// Wait for someone to connect
			conn, err := listener.Accept()
			if err != nil {
				if enableLogging == true {
					log.Print("Error attempting to accept connection")
					log.Print(err)
				}
			} else {
				// Hand this off and immediately listen for more
				go handleListenedConn(address, conn, bm.MaxMessageSizeBitLength, enableLogging, cb)
			}
		}
	}(address, bm.MaxMessageSizeBitLength, bm.EnableLogging, socket)
}

func handleListenedConn(address string, conn net.Conn, maxMessageSize int, enableLogging bool, cb ListenCallback) {
	for {
		// Handle getting the data header
		headerByteSize := maxMessageSize
		headerBuffer := make([]byte, headerByteSize)
		// First, read the number of bytes required to determine the message length
		_, err := readFromConnection(conn, headerBuffer)
		if err != nil && err.Error() == "EOF" {
			// Log the error we got from the call to read
			if enableLogging == true {
				log.Printf("Address %s: Client closed connection", address)
				log.Print(err)
			}
			conn.Close()
			return
		}

		// Now turn that buffer of bytes into an integer - represnts size of message body
		msgLength, bytesParsed := binary.Uvarint(headerBuffer)
		// Not sure what the correct way to handle these errors are. For now, bomb out
		if bytesParsed == 0 {
			// "Buffer too small"
			if enableLogging == true {
				log.Printf("Address %s: 0 Bytes parsed from header", address)
				log.Print(err)
			}
			conn.Close()
			return
		} else if bytesParsed < 0 {
			// "Buffer overflow"
			if enableLogging == true {
				log.Printf("Address %s: Buffer Less than zero bytes parsed from header", address)
				log.Print(err)
			}
			conn.Close()
			return
		}
		dataBuffer := make([]byte, msgLength)
		bytesLen, err := readFromConnection(conn, dataBuffer)
		if err != nil && err.Error() == "EOF" {
			// log the error from the call to read
			if enableLogging == true {
				log.Printf("Address %s: Failure to read from connection", address)
				log.Print(err)
			}
			conn.Close()
			return
		}

		// If we read bytes, there wasn't an error, or if there was it was only EOF
		// And readbytes + EOF is normal, just as readbytes + no err, next read 0 bytes EOF
		// So... we take action on the actual message data
		if bytesLen > 0 && (err == nil || (err != nil && err.Error() == "EOF")) {
			// I ultimately have some design choices here
			// Currently, I am invoking a delegate thats been passed down the stack
			// I could...
			// Just push it onto a queue (not a slow ass channel, but a queue)
			// which has a reference passed down to it, and the main process
			// spawns a goroutine to reap off the queue and handle those in parallel

			// Callback, atm
			err = cb(dataBuffer)
			if err != nil && enableLogging == true {
				log.Printf("Error in Callback")
				log.Print(err)
			}
		}
	}
}

func readFromConnection(reader net.Conn, buffer []byte) (int, error) {
	// This fills the buffer
	bytesLen, err := reader.Read(buffer)
	// Output the content of the bytes to the queue
	if bytesLen == 0 {
		if err != nil && err.Error() == "EOF" {
			// "End of individual transmission"
			// We're just done reading from that conn
			return bytesLen, err
		}
	}

	if err != nil {
		//"Underlying network failure?"
		// Not sure what this error would be, but it could exist and i've seen it handled
		// as a general case in other networking code. Following in the footsteps of (greatness|madness)
	}
	// Read some bytes, return the length
	return bytesLen, nil
}

func (bm *BuffManager) dialOut(address string) (*net.TCPConn, error) {
	bm.RLock()
	if _, ok := bm.dialedConnections[address]; ok == true {
		bm.RUnlock()
		// Need to clean it out on any error...
		return nil, errors.New("You have a connection to this ip and port open already")
	}
	bm.RUnlock()
	tcpAddr, err := net.ResolveTCPAddr("tcp", address)
	if err != nil {
		return nil, err
	}
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return nil, err
	} else {
		// Store the connection, it's valid
		bm.Lock()
		bm.dialedConnections[address] = conn
		bm.Unlock()
	}
	return conn, nil
}

// closeDialer uses explicit lock semantics vs defers to better control
// when the lock gets released to reduce contention
func (bm *BuffManager) closeDialer(address string) error {
	// Get a read lock to look up that the connection exists
	bm.RLock()
	if conn, ok := bm.dialedConnections[address]; ok != true {
		// Release immediately
		bm.RUnlock()
		err := conn.Close()
		// Grab lock to delete from the map
		bm.Lock()
		delete(bm.dialedConnections, address)
		// Release immediately
		bm.Unlock()
		return err
	}
	// Release the lock incase it didn't exist
	bm.RUnlock()
	return nil
}

// Write data and dial out if the conn isn't open
func (bm *BuffManager) WriteTo(address string, data []byte, persist bool) (int, error) {
	var conn net.Conn
	var err error
	var ok bool

	// Get the connection if it's cached, or open a new one
	bm.RLock()
	conn, ok = bm.dialedConnections[address]
	bm.RUnlock()
	if ok != true {
		conn, err = bm.dialOut(address)
		if err != nil {
			// Error dialing out, cannot write
			// bail
			return 0, err
		}
	}
	// Calculate how big the message is, using a consistent header size.
	toWriteLen := UInt16ToByteArray(uint16(len(data)), bm.MaxMessageSizeBitLength)
	// Append the size to the message, so now it has a header
	toWrite := append(toWriteLen, data...)
	// Writes are threadsafe in net.Conns
	written, err := conn.Write(toWrite)

	if err != nil || persist == false {
		if err != nil && bm.EnableLogging == true {
			log.Printf("Error while writing data to %s. Expected to write %d, actually wrote %d", address, len(toWrite), written)
			log.Print(err)
		}
		err = bm.closeDialer(address)
		conn = nil
		if err != nil {
			// TODO ponder the following:
			// Error closing the dialer, should we still return 0 written?
			// What if some bytes written, then failure, then also the close throws an error
			// []error is a better return type, but not sure if thats a thing you're supposed to do...
			// Possibilities for error not as complicated as i'm thinking?
			if bm.EnableLogging == true {
				// The error will get returned up the stack, no need to log it here?
				log.Print("There was a subsequent error cleaning up the connection to %s")
			}
			return 0, err
		}
	}
	// Return the bytes written, any error
	return written, err
}
<|endoftext|>


<commit_before>package admin

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

type Meta struct {
	base            *Resource
	Name            string
	FieldName       string
	Label           string
	Type            string
	FormattedValuer func(interface{}, *qor.Context) interface{}
	Valuer          func(interface{}, *qor.Context) interface{}
	Setter          func(resource interface{}, metaValue *resource.MetaValue, context *qor.Context)
	Metas           []resource.Metaor
	Resource        resource.Resourcer
	Collection      interface{}
	GetCollection   func(interface{}, *qor.Context) [][]string
	Permission      *roles.Permission
	resource.Meta
}

func (meta *Meta) GetMetas() []resource.Metaor {
	if len(meta.Metas) > 0 {
		return meta.Metas
	} else if meta.Resource == nil {
		return []resource.Metaor{}
	} else {
		return meta.Resource.GetMetas([]string{})
	}
}

func (meta *Meta) GetResource() resource.Resourcer {
	return meta.Resource
}

func (meta *Meta) DBName() string {
	if meta.FieldStruct != nil {
		return meta.FieldStruct.DBName
	}
	return ""
}

func getField(fields []*gorm.StructField, name string) (*gorm.StructField, bool) {
	for _, field := range fields {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

func (meta *Meta) updateMeta() {
	meta.Meta = resource.Meta{
		Name:            meta.Name,
		FieldName:       meta.FieldName,
		Setter:          meta.Setter,
		FormattedValuer: meta.FormattedValuer,
		Valuer:          meta.Valuer,
		Permission:      meta.Permission,
		Resource:        meta.base,
	}

	meta.PreInitialize()
	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaBeforeInitializeInterface); ok {
			injector.ConfigureQorMetaBeforeInitialize(meta)
		}
	}

	meta.Initialize()

	if meta.Label == "" {
		meta.Label = utils.HumanizeString(meta.Name)
	}

	var fieldType reflect.Type
	var hasColumn = meta.FieldStruct != nil

	if hasColumn {
		fieldType = meta.FieldStruct.Struct.Type
		for fieldType.Kind() == reflect.Ptr {
			fieldType = fieldType.Elem()
		}
	}

	// Set Meta Type
	if meta.Type == "" && hasColumn {
		if relationship := meta.FieldStruct.Relationship; relationship != nil {
			if relationship.Kind == "has_one" {
				meta.Type = "single_edit"
			} else if relationship.Kind == "has_many" {
				meta.Type = "collection_edit"
			} else if relationship.Kind == "belongs_to" {
				meta.Type = "select_one"
			} else if relationship.Kind == "many_to_many" {
				meta.Type = "select_many"
			}
		} else {
			switch fieldType.Kind().String() {
			case "string":
				var tag = meta.FieldStruct.Tag
				if size, ok := utils.ParseTagOption(tag.Get("sql"))["SIZE"]; ok {
					if i, _ := strconv.Atoi(size); i > 255 {
						meta.Type = "text"
					} else {
						meta.Type = "string"
					}
				} else if text, ok := utils.ParseTagOption(tag.Get("sql"))["TYPE"]; ok && text == "text" {
					meta.Type = "text"
				} else {
					meta.Type = "string"
				}
			case "bool":
				meta.Type = "checkbox"
			default:
				if regexp.MustCompile(`^(.*)?(u)?(int)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "number"
				} else if regexp.MustCompile(`^(.*)?(float)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "float"
				} else if _, ok := reflect.New(fieldType).Interface().(*time.Time); ok {
					meta.Type = "datetime"
				}
			}
		}
	}

	// Set Meta Resource
	if meta.Resource == nil {
		if hasColumn && (meta.FieldStruct.Relationship != nil) {
			var result interface{}
			if fieldType.Kind() == reflect.Struct {
				result = reflect.New(fieldType).Interface()
			} else if fieldType.Kind() == reflect.Slice {
				refelectType := fieldType.Elem()
				for refelectType.Kind() == reflect.Ptr {
					refelectType = refelectType.Elem()
				}
				result = reflect.New(refelectType).Interface()
			}

			res := meta.base.GetAdmin().NewResource(result)
			res.configure()
			meta.Resource = res
		}
	}

	scope := &gorm.Scope{Value: meta.base.Value}
	scopeField, _ := scope.FieldByName(meta.GetFieldName())

	{ // Format Meta FormattedValueOf
		if meta.FormattedValuer == nil {
			if meta.Type == "select_one" {
				meta.SetFormattedValuer(func(value interface{}, context *qor.Context) interface{} {
					return utils.Stringify(meta.GetValuer()(value, context))
				})
			}
		}
	}

	{ // Format Meta Collection
		if meta.Collection != nil {
			if maps, ok := meta.Collection.([]string); ok {
				meta.GetCollection = func(interface{}, *qor.Context) (results [][]string) {
					for _, value := range maps {
						results = append(results, []string{value, value})
					}
					return
				}
			} else if maps, ok := meta.Collection.([][]string); ok {
				meta.GetCollection = func(interface{}, *qor.Context) [][]string {
					return maps
				}
			} else if f, ok := meta.Collection.(func(interface{}, *qor.Context) [][]string); ok {
				meta.GetCollection = f
			} else {
				utils.ExitWithMsg("Unsupported Collection format for meta %v of resource %v", meta.Name, reflect.TypeOf(meta.base.Value))
			}
		} else if meta.Type == "select_one" || meta.Type == "select_many" {
			if scopeField.Relationship != nil {
				fieldType := scopeField.StructField.Struct.Type
				if fieldType.Kind() == reflect.Slice {
					fieldType = fieldType.Elem()
				}

				meta.GetCollection = func(value interface{}, context *qor.Context) (results [][]string) {
					values := reflect.New(reflect.SliceOf(fieldType)).Interface()
					context.GetDB().Find(values)
					reflectValues := reflect.Indirect(reflect.ValueOf(values))
					for i := 0; i < reflectValues.Len(); i++ {
						scope := scope.New(reflectValues.Index(i).Interface())
						primaryKey := fmt.Sprintf("%v", scope.PrimaryKeyValue())
						results = append(results, []string{primaryKey, utils.Stringify(reflectValues.Index(i).Interface())})
					}
					return
				}
			} else {
				utils.ExitWithMsg("%v meta type %v needs Collection", meta.Name, meta.Type)
			}
		}
	}

	meta.FieldName = meta.GetFieldName()

	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaInterface); ok {
			injector.ConfigureQorMeta(meta)
		}
	}
}
<commit_msg>Add FormattedValuer for select many<commit_after>package admin

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

type Meta struct {
	base            *Resource
	Name            string
	FieldName       string
	Label           string
	Type            string
	FormattedValuer func(interface{}, *qor.Context) interface{}
	Valuer          func(interface{}, *qor.Context) interface{}
	Setter          func(resource interface{}, metaValue *resource.MetaValue, context *qor.Context)
	Metas           []resource.Metaor
	Resource        resource.Resourcer
	Collection      interface{}
	GetCollection   func(interface{}, *qor.Context) [][]string
	Permission      *roles.Permission
	resource.Meta
}

func (meta *Meta) GetMetas() []resource.Metaor {
	if len(meta.Metas) > 0 {
		return meta.Metas
	} else if meta.Resource == nil {
		return []resource.Metaor{}
	} else {
		return meta.Resource.GetMetas([]string{})
	}
}

func (meta *Meta) GetResource() resource.Resourcer {
	return meta.Resource
}

func (meta *Meta) DBName() string {
	if meta.FieldStruct != nil {
		return meta.FieldStruct.DBName
	}
	return ""
}

func getField(fields []*gorm.StructField, name string) (*gorm.StructField, bool) {
	for _, field := range fields {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

func (meta *Meta) updateMeta() {
	meta.Meta = resource.Meta{
		Name:            meta.Name,
		FieldName:       meta.FieldName,
		Setter:          meta.Setter,
		FormattedValuer: meta.FormattedValuer,
		Valuer:          meta.Valuer,
		Permission:      meta.Permission,
		Resource:        meta.base,
	}

	meta.PreInitialize()
	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaBeforeInitializeInterface); ok {
			injector.ConfigureQorMetaBeforeInitialize(meta)
		}
	}

	meta.Initialize()

	if meta.Label == "" {
		meta.Label = utils.HumanizeString(meta.Name)
	}

	var fieldType reflect.Type
	var hasColumn = meta.FieldStruct != nil

	if hasColumn {
		fieldType = meta.FieldStruct.Struct.Type
		for fieldType.Kind() == reflect.Ptr {
			fieldType = fieldType.Elem()
		}
	}

	// Set Meta Type
	if meta.Type == "" && hasColumn {
		if relationship := meta.FieldStruct.Relationship; relationship != nil {
			if relationship.Kind == "has_one" {
				meta.Type = "single_edit"
			} else if relationship.Kind == "has_many" {
				meta.Type = "collection_edit"
			} else if relationship.Kind == "belongs_to" {
				meta.Type = "select_one"
			} else if relationship.Kind == "many_to_many" {
				meta.Type = "select_many"
			}
		} else {
			switch fieldType.Kind().String() {
			case "string":
				var tag = meta.FieldStruct.Tag
				if size, ok := utils.ParseTagOption(tag.Get("sql"))["SIZE"]; ok {
					if i, _ := strconv.Atoi(size); i > 255 {
						meta.Type = "text"
					} else {
						meta.Type = "string"
					}
				} else if text, ok := utils.ParseTagOption(tag.Get("sql"))["TYPE"]; ok && text == "text" {
					meta.Type = "text"
				} else {
					meta.Type = "string"
				}
			case "bool":
				meta.Type = "checkbox"
			default:
				if regexp.MustCompile(`^(.*)?(u)?(int)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "number"
				} else if regexp.MustCompile(`^(.*)?(float)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "float"
				} else if _, ok := reflect.New(fieldType).Interface().(*time.Time); ok {
					meta.Type = "datetime"
				}
			}
		}
	}

	// Set Meta Resource
	if meta.Resource == nil {
		if hasColumn && (meta.FieldStruct.Relationship != nil) {
			var result interface{}
			if fieldType.Kind() == reflect.Struct {
				result = reflect.New(fieldType).Interface()
			} else if fieldType.Kind() == reflect.Slice {
				refelectType := fieldType.Elem()
				for refelectType.Kind() == reflect.Ptr {
					refelectType = refelectType.Elem()
				}
				result = reflect.New(refelectType).Interface()
			}

			res := meta.base.GetAdmin().NewResource(result)
			res.configure()
			meta.Resource = res
		}
	}

	scope := &gorm.Scope{Value: meta.base.Value}
	scopeField, _ := scope.FieldByName(meta.GetFieldName())

	{ // Format Meta FormattedValueOf
		if meta.FormattedValuer == nil {
			if meta.Type == "select_one" {
				meta.SetFormattedValuer(func(value interface{}, context *qor.Context) interface{} {
					return utils.Stringify(meta.GetValuer()(value, context))
				})
			} else if meta.Type == "select_many" {
				meta.SetFormattedValuer(func(value interface{}, context *qor.Context) interface{} {
					reflectValue := reflect.Indirect(reflect.ValueOf(meta.GetValuer()(value, context)))
					var results []string
					for i := 0; i < reflectValue.Len(); i++ {
						results = append(results, utils.Stringify(reflectValue.Index(i).Interface()))
					}
					return results
				})
			}
		}
	}

	{ // Format Meta Collection
		if meta.Collection != nil {
			if maps, ok := meta.Collection.([]string); ok {
				meta.GetCollection = func(interface{}, *qor.Context) (results [][]string) {
					for _, value := range maps {
						results = append(results, []string{value, value})
					}
					return
				}
			} else if maps, ok := meta.Collection.([][]string); ok {
				meta.GetCollection = func(interface{}, *qor.Context) [][]string {
					return maps
				}
			} else if f, ok := meta.Collection.(func(interface{}, *qor.Context) [][]string); ok {
				meta.GetCollection = f
			} else {
				utils.ExitWithMsg("Unsupported Collection format for meta %v of resource %v", meta.Name, reflect.TypeOf(meta.base.Value))
			}
		} else if meta.Type == "select_one" || meta.Type == "select_many" {
			if scopeField.Relationship != nil {
				fieldType := scopeField.StructField.Struct.Type
				if fieldType.Kind() == reflect.Slice {
					fieldType = fieldType.Elem()
				}

				meta.GetCollection = func(value interface{}, context *qor.Context) (results [][]string) {
					values := reflect.New(reflect.SliceOf(fieldType)).Interface()
					context.GetDB().Find(values)
					reflectValues := reflect.Indirect(reflect.ValueOf(values))
					for i := 0; i < reflectValues.Len(); i++ {
						scope := scope.New(reflectValues.Index(i).Interface())
						primaryKey := fmt.Sprintf("%v", scope.PrimaryKeyValue())
						results = append(results, []string{primaryKey, utils.Stringify(reflectValues.Index(i).Interface())})
					}
					return
				}
			} else {
				utils.ExitWithMsg("%v meta type %v needs Collection", meta.Name, meta.Type)
			}
		}
	}

	meta.FieldName = meta.GetFieldName()

	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaInterface); ok {
			injector.ConfigureQorMeta(meta)
		}
	}
}
<|endoftext|>


<commit_before>package admin

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

type Meta struct {
	base            *Resource
	Name            string
	FieldName       string
	DBName          string
	Label           string
	Type            string
	FormattedValuer func(interface{}, *qor.Context) interface{}
	Valuer          func(interface{}, *qor.Context) interface{}
	Setter          func(resource interface{}, metaValue *resource.MetaValue, context *qor.Context)
	Metas           []resource.Metaor
	Resource        resource.Resourcer
	Collection      interface{}
	GetCollection   func(interface{}, *qor.Context) [][]string
	Permission      *roles.Permission
	resource.Meta
}

func (meta *Meta) GetMetas() []resource.Metaor {
	if len(meta.Metas) > 0 {
		return meta.Metas
	} else if meta.Resource == nil {
		return []resource.Metaor{}
	} else {
		return meta.Resource.GetMetas([]string{})
	}
}

func (meta *Meta) GetResource() resource.Resourcer {
	return meta.Resource
}

func getField(fields []*gorm.StructField, name string) (*gorm.StructField, bool) {
	for _, field := range fields {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

func (meta *Meta) updateMeta() {
	meta.Meta = resource.Meta{
		Name:            meta.Name,
		FieldName:       meta.FieldName,
		Setter:          meta.Setter,
		FormattedValuer: meta.FormattedValuer,
		Valuer:          meta.Valuer,
		Permission:      meta.Permission,
		Resource:        meta.base,
	}

	meta.PreInitialize()
	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaBeforeInitializeInterface); ok {
			injector.ConfigureQorMetaBeforeInitialize(meta)
		}
	}

	meta.Initialize()

	if meta.Label == "" {
		meta.Label = utils.HumanizeString(meta.Name)
	}

	var fieldType reflect.Type
	var hasColumn = meta.FieldStruct != nil

	if hasColumn {
		fieldType = meta.FieldStruct.Struct.Type
		for fieldType.Kind() == reflect.Ptr {
			fieldType = fieldType.Elem()
		}
	}

	// Set Meta Type
	if meta.Type == "" && hasColumn {
		if relationship := meta.FieldStruct.Relationship; relationship != nil {
			if relationship.Kind == "has_one" {
				meta.Type = "single_edit"
			} else if relationship.Kind == "has_many" {
				meta.Type = "collection_edit"
			} else if relationship.Kind == "belongs_to" {
				meta.Type = "select_one"
			} else if relationship.Kind == "many_to_many" {
				meta.Type = "select_many"
			}
		} else {
			switch fieldType.Kind().String() {
			case "string":
				var tag = meta.FieldStruct.Tag
				if size, ok := utils.ParseTagOption(tag.Get("sql"))["SIZE"]; ok {
					if i, _ := strconv.Atoi(size); i > 255 {
						meta.Type = "text"
					} else {
						meta.Type = "string"
					}
				} else if text, ok := utils.ParseTagOption(tag.Get("sql"))["TYPE"]; ok && text == "text" {
					meta.Type = "text"
				} else {
					meta.Type = "string"
				}
			case "bool":
				meta.Type = "checkbox"
			default:
				if regexp.MustCompile(`^(.*)?(u)?(int)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "number"
				} else if regexp.MustCompile(`^(.*)?(float)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "float"
				} else if _, ok := reflect.New(fieldType).Interface().(*time.Time); ok {
					meta.Type = "datetime"
				}
			}
		}
	}

	// Set Meta Resource
	if meta.Resource == nil {
		if hasColumn && (meta.FieldStruct.Relationship != nil) {
			var result interface{}
			if fieldType.Kind() == reflect.Struct {
				result = reflect.New(fieldType).Interface()
			} else if fieldType.Kind() == reflect.Slice {
				refelectType := fieldType.Elem()
				for refelectType.Kind() == reflect.Ptr {
					refelectType = refelectType.Elem()
				}
				result = reflect.New(refelectType).Interface()
			}

			res := meta.base.GetAdmin().NewResource(result)
			res.configure()
			meta.Resource = res
		}
	}

	scope := &gorm.Scope{Value: meta.base.Value}
	scopeField, _ := scope.FieldByName(meta.GetFieldName())

	// Set Meta Collection
	if meta.Collection != nil {
		if maps, ok := meta.Collection.([]string); ok {
			meta.GetCollection = func(interface{}, *qor.Context) (results [][]string) {
				for _, value := range maps {
					results = append(results, []string{value, value})
				}
				return
			}
		} else if maps, ok := meta.Collection.([][]string); ok {
			meta.GetCollection = func(interface{}, *qor.Context) [][]string {
				return maps
			}
		} else if f, ok := meta.Collection.(func(interface{}, *qor.Context) [][]string); ok {
			meta.GetCollection = f
		} else {
			utils.ExitWithMsg("Unsupported Collection format for meta %v of resource %v", meta.Name, reflect.TypeOf(meta.base.Value))
		}
	} else if meta.Type == "select_one" || meta.Type == "select_many" {
		if scopeField.Relationship != nil {
			fieldType := scopeField.StructField.Struct.Type
			if fieldType.Kind() == reflect.Slice {
				fieldType = fieldType.Elem()
			}

			meta.GetCollection = func(value interface{}, context *qor.Context) (results [][]string) {
				values := reflect.New(reflect.SliceOf(fieldType)).Interface()
				context.GetDB().Find(values)
				reflectValues := reflect.Indirect(reflect.ValueOf(values))
				for i := 0; i < reflectValues.Len(); i++ {
					scope := scope.New(reflectValues.Index(i).Interface())
					primaryKey := fmt.Sprintf("%v", scope.PrimaryKeyValue())
					results = append(results, []string{primaryKey, utils.Stringify(reflectValues.Index(i).Interface())})
				}
				return
			}
		} else {
			utils.ExitWithMsg("%v meta type %v needs Collection", meta.Name, meta.Type)
		}
	}

	meta.FieldName = meta.GetFieldName()

	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaInterface); ok {
			injector.ConfigureQorMeta(meta)
		}
	}
}
<commit_msg>Fix can't sort by column<commit_after>package admin

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/roles"
	"github.com/qor/qor/utils"
)

type Meta struct {
	base            *Resource
	Name            string
	FieldName       string
	DBName          string
	Label           string
	Type            string
	FormattedValuer func(interface{}, *qor.Context) interface{}
	Valuer          func(interface{}, *qor.Context) interface{}
	Setter          func(resource interface{}, metaValue *resource.MetaValue, context *qor.Context)
	Metas           []resource.Metaor
	Resource        resource.Resourcer
	Collection      interface{}
	GetCollection   func(interface{}, *qor.Context) [][]string
	Permission      *roles.Permission
	resource.Meta
}

func (meta *Meta) GetMetas() []resource.Metaor {
	if len(meta.Metas) > 0 {
		return meta.Metas
	} else if meta.Resource == nil {
		return []resource.Metaor{}
	} else {
		return meta.Resource.GetMetas([]string{})
	}
}

func (meta *Meta) GetResource() resource.Resourcer {
	return meta.Resource
}

func getField(fields []*gorm.StructField, name string) (*gorm.StructField, bool) {
	for _, field := range fields {
		if field.Name == name || field.DBName == name {
			return field, true
		}
	}
	return nil, false
}

func (meta *Meta) updateMeta() {
	meta.Meta = resource.Meta{
		Name:            meta.Name,
		FieldName:       meta.FieldName,
		Setter:          meta.Setter,
		FormattedValuer: meta.FormattedValuer,
		Valuer:          meta.Valuer,
		Permission:      meta.Permission,
		Resource:        meta.base,
	}

	meta.PreInitialize()
	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaBeforeInitializeInterface); ok {
			injector.ConfigureQorMetaBeforeInitialize(meta)
		}
	}

	meta.Initialize()

	if meta.Label == "" {
		meta.Label = utils.HumanizeString(meta.Name)
	}

	var fieldType reflect.Type
	var hasColumn = meta.FieldStruct != nil

	if hasColumn {
		meta.DBName = meta.FieldStruct.DBName

		fieldType = meta.FieldStruct.Struct.Type
		for fieldType.Kind() == reflect.Ptr {
			fieldType = fieldType.Elem()
		}
	}

	// Set Meta Type
	if meta.Type == "" && hasColumn {
		if relationship := meta.FieldStruct.Relationship; relationship != nil {
			if relationship.Kind == "has_one" {
				meta.Type = "single_edit"
			} else if relationship.Kind == "has_many" {
				meta.Type = "collection_edit"
			} else if relationship.Kind == "belongs_to" {
				meta.Type = "select_one"
			} else if relationship.Kind == "many_to_many" {
				meta.Type = "select_many"
			}
		} else {
			switch fieldType.Kind().String() {
			case "string":
				var tag = meta.FieldStruct.Tag
				if size, ok := utils.ParseTagOption(tag.Get("sql"))["SIZE"]; ok {
					if i, _ := strconv.Atoi(size); i > 255 {
						meta.Type = "text"
					} else {
						meta.Type = "string"
					}
				} else if text, ok := utils.ParseTagOption(tag.Get("sql"))["TYPE"]; ok && text == "text" {
					meta.Type = "text"
				} else {
					meta.Type = "string"
				}
			case "bool":
				meta.Type = "checkbox"
			default:
				if regexp.MustCompile(`^(.*)?(u)?(int)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "number"
				} else if regexp.MustCompile(`^(.*)?(float)(\d+)?`).MatchString(fieldType.Kind().String()) {
					meta.Type = "float"
				} else if _, ok := reflect.New(fieldType).Interface().(*time.Time); ok {
					meta.Type = "datetime"
				}
			}
		}
	}

	// Set Meta Resource
	if meta.Resource == nil {
		if hasColumn && (meta.FieldStruct.Relationship != nil) {
			var result interface{}
			if fieldType.Kind() == reflect.Struct {
				result = reflect.New(fieldType).Interface()
			} else if fieldType.Kind() == reflect.Slice {
				refelectType := fieldType.Elem()
				for refelectType.Kind() == reflect.Ptr {
					refelectType = refelectType.Elem()
				}
				result = reflect.New(refelectType).Interface()
			}

			res := meta.base.GetAdmin().NewResource(result)
			res.configure()
			meta.Resource = res
		}
	}

	scope := &gorm.Scope{Value: meta.base.Value}
	scopeField, _ := scope.FieldByName(meta.GetFieldName())

	// Set Meta Collection
	if meta.Collection != nil {
		if maps, ok := meta.Collection.([]string); ok {
			meta.GetCollection = func(interface{}, *qor.Context) (results [][]string) {
				for _, value := range maps {
					results = append(results, []string{value, value})
				}
				return
			}
		} else if maps, ok := meta.Collection.([][]string); ok {
			meta.GetCollection = func(interface{}, *qor.Context) [][]string {
				return maps
			}
		} else if f, ok := meta.Collection.(func(interface{}, *qor.Context) [][]string); ok {
			meta.GetCollection = f
		} else {
			utils.ExitWithMsg("Unsupported Collection format for meta %v of resource %v", meta.Name, reflect.TypeOf(meta.base.Value))
		}
	} else if meta.Type == "select_one" || meta.Type == "select_many" {
		if scopeField.Relationship != nil {
			fieldType := scopeField.StructField.Struct.Type
			if fieldType.Kind() == reflect.Slice {
				fieldType = fieldType.Elem()
			}

			meta.GetCollection = func(value interface{}, context *qor.Context) (results [][]string) {
				values := reflect.New(reflect.SliceOf(fieldType)).Interface()
				context.GetDB().Find(values)
				reflectValues := reflect.Indirect(reflect.ValueOf(values))
				for i := 0; i < reflectValues.Len(); i++ {
					scope := scope.New(reflectValues.Index(i).Interface())
					primaryKey := fmt.Sprintf("%v", scope.PrimaryKeyValue())
					results = append(results, []string{primaryKey, utils.Stringify(reflectValues.Index(i).Interface())})
				}
				return
			}
		} else {
			utils.ExitWithMsg("%v meta type %v needs Collection", meta.Name, meta.Type)
		}
	}

	meta.FieldName = meta.GetFieldName()

	if meta.FieldStruct != nil {
		if injector, ok := reflect.New(meta.FieldStruct.Struct.Type).Interface().(resource.ConfigureMetaInterface); ok {
			injector.ConfigureQorMeta(meta)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google, Inc. All rights reserved.

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 util

import (
	"archive/tar"
	"github.com/sirupsen/logrus"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// Map of target:linkname
var hardlinks = make(map[string]string)

func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
	for {
		header, err := tr.Next()
		if err == io.EOF {
			// end of tar archive
			break
		}
		if err != nil {
			logrus.Error("Error getting next tar header")
			return err
		}
		if strings.Contains(header.Name, ".wh.") {
			rmPath := filepath.Join(path, header.Name)
			// Remove the .wh file if it was extracted.
			if _, err := os.Stat(rmPath); !os.IsNotExist(err) {
				if err := os.Remove(rmPath); err != nil {
					logrus.Error(err)
				}
			}

			// Remove the whited-out path.
			newName := strings.Replace(rmPath, ".wh.", "", 1)
			if err = os.RemoveAll(newName); err != nil {
				logrus.Error(err)
			}
			continue
		}
		target := filepath.Join(path, header.Name)
		// Make sure the target isn't part of the whitelist
		if checkWhitelist(target, whitelist) {
			continue
		}
		mode := header.FileInfo().Mode()
		switch header.Typeflag {

		// if its a dir and it doesn't exist create it
		case tar.TypeDir:
			if _, err := os.Stat(target); os.IsNotExist(err) {
				if err := os.MkdirAll(target, mode); err != nil {
					return err
				}
				// In some cases, MkdirAll doesn't change the permissions, so run Chmod
				if err := os.Chmod(target, mode); err != nil {
					return err
				}
			}

		// if it's a file create it
		case tar.TypeReg:
			// It's possible for a file to be included before the directory it's in is created.
			baseDir := filepath.Dir(target)
			if _, err := os.Stat(baseDir); os.IsNotExist(err) {
				logrus.Debugf("baseDir %s for file %s does not exist. Creating.", baseDir, target)
				if err := os.MkdirAll(baseDir, 0755); err != nil {
					return err
				}
			}
			// It's possible we end up creating files that can't be overwritten based on their permissions.
			// Explicitly delete an existing file before continuing.
			if _, err := os.Stat(target); !os.IsNotExist(err) {
				logrus.Debugf("Removing %s for overwrite.", target)
				if err := os.Remove(target); err != nil {
					return err
				}
			}

			currFile, err := os.Create(target)
			if err != nil {
				logrus.Errorf("Error creating file %s %s", target, err)
				return err
			}
			// manually set permissions on file, since the default umask (022) will interfere
			if err = os.Chmod(target, mode); err != nil {
				logrus.Errorf("Error updating file permissions on %s", target)
				return err
			}
			_, err = io.Copy(currFile, tr)
			if err != nil {
				return err
			}
			currFile.Close()
		case tar.TypeSymlink:
			// It's possible we end up creating files that can't be overwritten based on their permissions.
			// Explicitly delete an existing file before continuing.
			if _, err := os.Stat(target); !os.IsNotExist(err) {
				logrus.Debugf("Removing %s to create symlink.", target)
				if err := os.RemoveAll(target); err != nil {
					logrus.Debugf("Unable to remove %s: %s", target, err)
				}
			}

			if err = os.Symlink(header.Linkname, target); err != nil {
				logrus.Errorf("Failed to create symlink between %s and %s: %s", header.Linkname, target, err)
			}
		case tar.TypeLink:
			linkname := filepath.Join(path, header.Linkname)
			// Check if the linkname already exists
			if _, err := os.Stat(linkname); !os.IsNotExist(err) {
				// If it exists, create the hard link
				if err := os.Link(linkname, target); err != nil {
					logrus.Warnf("Failed to create hard link between %s and %s: %v", linkname, target, err)
				}
				logrus.Debugf("Created hard link from %s to %s", linkname, target)
			} else {
				hardlinks[target] = linkname
			}
		}
	}

	for target, linkname := range hardlinks {
		logrus.Info("Resolving hard links.")
		if _, err := os.Stat(linkname); !os.IsNotExist(err) {
			// If it exists, create the hard link
			if err := os.Link(linkname, target); err != nil {
				logrus.Warnf("Unable to create hard link from %s to %s: %v", linkname, target, err)
			}
			logrus.Debugf("Created hard link from %s to %s", linkname, target)
		} else {
			logrus.Warnf("Unable to create hard link from %s to %s", linkname, target)
		}
	}
	return nil
}

func checkWhitelist(target string, whitelist []string) bool {
	for _, w := range whitelist {
		if HasFilepathPrefix(target, w) {
			logrus.Debugf("Not extracting %s, as it has prefix %s which is whitelisted", target, w)
			return true
		}
	}
	return false
}

// UnTar takes in a path to a tar file and writes the untarred version to the provided target.
// Only untars one level, does not untar nested tars.
func UnTar(r io.Reader, target string, whitelist []string) error {
	if _, ok := os.Stat(target); ok != nil {
		os.MkdirAll(target, 0775)
	}

	tr := tar.NewReader(r)
	if err := unpackTar(tr, target, whitelist); err != nil {
		return err
	}
	return nil
}

func IsTar(path string) bool {
	return filepath.Ext(path) == ".tar" ||
		filepath.Ext(path) == ".tar.gz" ||
		filepath.Ext(path) == ".tgz"
}

func CheckTar(image string) bool {
	if strings.TrimSuffix(image, ".tar") == image {
		return false
	}
	if _, err := os.Stat(image); err != nil {
		logrus.Errorf("%s does not exist", image)
		return false
	}
	return true
}
<commit_msg>Moved hard link logic into helper function<commit_after>/*
Copyright 2017 Google, Inc. All rights reserved.

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 util

import (
	"archive/tar"
	"github.com/sirupsen/logrus"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// Map of target:linkname
var hardlinks = make(map[string]string)

func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
	for {
		header, err := tr.Next()
		if err == io.EOF {
			// end of tar archive
			break
		}
		if err != nil {
			logrus.Error("Error getting next tar header")
			return err
		}
		if strings.Contains(header.Name, ".wh.") {
			rmPath := filepath.Join(path, header.Name)
			// Remove the .wh file if it was extracted.
			if _, err := os.Stat(rmPath); !os.IsNotExist(err) {
				if err := os.Remove(rmPath); err != nil {
					logrus.Error(err)
				}
			}

			// Remove the whited-out path.
			newName := strings.Replace(rmPath, ".wh.", "", 1)
			if err = os.RemoveAll(newName); err != nil {
				logrus.Error(err)
			}
			continue
		}
		target := filepath.Join(path, header.Name)
		// Make sure the target isn't part of the whitelist
		if checkWhitelist(target, whitelist) {
			continue
		}
		mode := header.FileInfo().Mode()
		switch header.Typeflag {

		// if its a dir and it doesn't exist create it
		case tar.TypeDir:
			if _, err := os.Stat(target); os.IsNotExist(err) {
				if err := os.MkdirAll(target, mode); err != nil {
					return err
				}
				// In some cases, MkdirAll doesn't change the permissions, so run Chmod
				if err := os.Chmod(target, mode); err != nil {
					return err
				}
			}

		// if it's a file create it
		case tar.TypeReg:
			// It's possible for a file to be included before the directory it's in is created.
			baseDir := filepath.Dir(target)
			if _, err := os.Stat(baseDir); os.IsNotExist(err) {
				logrus.Debugf("baseDir %s for file %s does not exist. Creating.", baseDir, target)
				if err := os.MkdirAll(baseDir, 0755); err != nil {
					return err
				}
			}
			// It's possible we end up creating files that can't be overwritten based on their permissions.
			// Explicitly delete an existing file before continuing.
			if _, err := os.Stat(target); !os.IsNotExist(err) {
				logrus.Debugf("Removing %s for overwrite.", target)
				if err := os.Remove(target); err != nil {
					return err
				}
			}

			currFile, err := os.Create(target)
			if err != nil {
				logrus.Errorf("Error creating file %s %s", target, err)
				return err
			}
			// manually set permissions on file, since the default umask (022) will interfere
			if err = os.Chmod(target, mode); err != nil {
				logrus.Errorf("Error updating file permissions on %s", target)
				return err
			}
			_, err = io.Copy(currFile, tr)
			if err != nil {
				return err
			}
			currFile.Close()
		case tar.TypeSymlink:
			// It's possible we end up creating files that can't be overwritten based on their permissions.
			// Explicitly delete an existing file before continuing.
			if _, err := os.Stat(target); !os.IsNotExist(err) {
				logrus.Debugf("Removing %s to create symlink.", target)
				if err := os.RemoveAll(target); err != nil {
					logrus.Debugf("Unable to remove %s: %s", target, err)
				}
			}

			if err = os.Symlink(header.Linkname, target); err != nil {
				logrus.Errorf("Failed to create symlink between %s and %s: %s", header.Linkname, target, err)
			}
		case tar.TypeLink:
			linkname := filepath.Join(path, header.Linkname)
			// Check if the linkname already exists
			if _, err := os.Stat(linkname); !os.IsNotExist(err) {
				// If it exists, create the hard link
				resolveHardlink(linkname, target)
			} else {
				hardlinks[target] = linkname
			}
		}
	}

	for target, linkname := range hardlinks {
		logrus.Info("Resolving hard links.")
		if _, err := os.Stat(linkname); !os.IsNotExist(err) {
			// If it exists, create the hard link
			resolveHardlink(linkname, target)
		} else {
			logrus.Errorf("Unable to create hard link from %s to %s", linkname, target)
		}
	}
	return nil
}

func resolveHardlink(linkname, target string) {
	if err := os.Link(linkname, target); err != nil {
		logrus.Warnf("Unable to create hard link from %s to %s: %v", linkname, target, err)
	} else {
		logrus.Debugf("Created hard link from %s to %s", linkname, target)
	}
}

func checkWhitelist(target string, whitelist []string) bool {
	for _, w := range whitelist {
		if HasFilepathPrefix(target, w) {
			logrus.Debugf("Not extracting %s, as it has prefix %s which is whitelisted", target, w)
			return true
		}
	}
	return false
}

// UnTar takes in a path to a tar file and writes the untarred version to the provided target.
// Only untars one level, does not untar nested tars.
func UnTar(r io.Reader, target string, whitelist []string) error {
	if _, ok := os.Stat(target); ok != nil {
		os.MkdirAll(target, 0775)
	}

	tr := tar.NewReader(r)
	if err := unpackTar(tr, target, whitelist); err != nil {
		return err
	}
	return nil
}

func IsTar(path string) bool {
	return filepath.Ext(path) == ".tar" ||
		filepath.Ext(path) == ".tar.gz" ||
		filepath.Ext(path) == ".tgz"
}

func CheckTar(image string) bool {
	if strings.TrimSuffix(image, ".tar") == image {
		return false
	}
	if _, err := os.Stat(image); err != nil {
		logrus.Errorf("%s does not exist", image)
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/subutai-io/base/agent/agent"
	"github.com/subutai-io/base/agent/cli"
	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/log"

	"github.com/codegangsta/cli"
)

var TIMESTAMP string = "-unknown"

func init() {
	if os.Getuid() != 0 {
		log.Error("Please run as root")
	}
	os.Setenv("PATH", "/apps/subutai/current/bin:"+os.Getenv("PATH"))
	if len(os.Args) > 1 {
		if os.Args[1] == "-d" {
			log.Level(log.DebugLevel)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "Subutai"
	app.Version = "4.0.0-RC10"
	app.Usage = "daemon and command line interface binary"

	app.Flags = []cli.Flag{cli.BoolFlag{
		Name:  "d",
		Usage: "debug mode"}}

	app.Commands = []cli.Command{{
		Name: "attach", Usage: "attach to container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "clear environment"},
			cli.BoolFlag{Name: "x", Usage: "use x86 personality"},
			cli.BoolFlag{Name: "r", Usage: "connect as regular user"}},
		Action: func(c *cli.Context) {
			lib.LxcAttach(c.Args().Get(0), c.Bool("c"), c.Bool("x"), c.Bool("r"))
		}}, {

		Name: "backup", Usage: "backup Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "full", Usage: "make full backup"},
			cli.BoolFlag{Name: "stop", Usage: "stop container at the time of backup"}},
		Action: func(c *cli.Context) {
			lib.BackupContainer(c.Args().Get(0), c.Bool("full"), c.Bool("stop"))
		}}, {

		Name: "batch", Usage: "batch commands execution",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "json", Usage: "JSON string with commands"}},
		Action: func(c *cli.Context) {
			lib.Batch(c.String("json"))
		}}, {

		Name: "clone", Usage: "clone Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "e", Usage: "set environment id for container"},
			cli.StringFlag{Name: "i", Usage: "set container IP address and VLAN"},
			cli.StringFlag{Name: "t", Usage: "token to verify with MH"}},
		Action: func(c *cli.Context) {
			lib.LxcClone(c.Args().Get(0), c.Args().Get(1), c.String("e"), c.String("i"), c.String("t"))
		}}, {

		Name: "cleanup", Usage: "clean Subutai environment",
		Action: func(c *cli.Context) {
			lib.Cleanup(c.Args().Get(0))
		}}, {

		Name: "config", Usage: "containerName add/del key value",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "o", Usage: "add/del key value"},
			cli.StringFlag{Name: "k", Usage: "add/del key value"},
			cli.StringFlag{Name: "v", Usage: "add/del key value"},
		},
		Action: func(c *cli.Context) {
			lib.LxcConfig(c.Args().Get(0), c.String("o"), c.String("k"), c.String("v"))
		}}, {

		Name: "daemon", Usage: "start an agent",
		Action: func(c *cli.Context) {
			config.InitAgentDebug()
			agent.Start(c)
		}}, {

		Name: "demote", Usage: "demote Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "i", Usage: "network value ie 192.168.1.1/24"},
			cli.StringFlag{Name: "v", Usage: "vlan id"},
		},
		Action: func(c *cli.Context) {
			lib.LxcDemote(c.Args().Get(0), c.String("i"), c.String("v"))
		}}, {

		Name: "destroy", Usage: "destroy Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcDestroy(c.Args().Get(0))
		}}, {

		Name: "export", Usage: "export Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"}},
		Action: func(c *cli.Context) {
			lib.LxcExport(c.Args().Get(0), c.String("v"))
		}}, {

		Name: "import", Usage: "import Subutai template",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"},
			cli.StringFlag{Name: "t", Usage: "token to access kurjun repo"}},
		Action: func(c *cli.Context) {
			lib.LxcImport(c.Args().Get(0), c.String("v"), c.String("t"))
		}}, {

		Name: "list", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "containers only"},
			cli.BoolFlag{Name: "t", Usage: "templates only"},
			cli.BoolFlag{Name: "i", Usage: "detailed container info"},
			cli.BoolFlag{Name: "a", Usage: "with ancestors"},
			cli.BoolFlag{Name: "p", Usage: "with parent"}},
		Action: func(c *cli.Context) {
			lib.LxcList(c.Args().Get(0), c.Bool("c"), c.Bool("t"), c.Bool("i"), c.Bool("a"), c.Bool("p"))
		}}, {

		Name: "management_network", Usage: "configure management network",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "listtunnel, l", Usage: "-l"},
			cli.StringFlag{Name: "createtunnel, c", Usage: "-c TUNNELPORTNAME TUNNELIPADDRESS TUNNELTYPE"},

			cli.BoolFlag{Name: "listvnimap, v", Usage: "-v"},
			cli.StringFlag{Name: "createvnimap, m", Usage: "-m TUNNELPORTNAME VNI VLANID ENV_ID"},
		},

		Subcommands: []cli.Command{{
			Name:  "tunnel",
			Usage: "tunnels operation",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "create", Usage: "create tunnel (tunnel -c)"},
				cli.StringFlag{Name: "delete", Usage: "delete tunnel (tunnel -d)"},
				cli.BoolFlag{Name: "list", Usage: "list of tunnels (tunnel -l)"},

				cli.StringFlag{Name: "remoteip", Usage: "remote ip"},
				cli.StringFlag{Name: "vlan", Usage: "tunnel vlan"},
				cli.StringFlag{Name: "vni", Usage: "vni"},
			},
			Action: func(c *cli.Context) {
				lib.VxlanTunnel(c.String("create"), c.String("delete"), c.String("remoteip"), c.String("vlan"), c.String("vni"), c.Bool("list"))
			}}, {

			Name:  "p2p",
			Usage: "p2p network operation",
			Flags: []cli.Flag{
				cli.BoolFlag{Name: "c", Usage: "create p2p instance (p2p -c interfaceName hash key ttl localPeepIPAddr)"},
				cli.BoolFlag{Name: "d", Usage: "delete p2p instance (p2p -d hash)"},
				cli.BoolFlag{Name: "u", Usage: "update p2p instance encryption key (p2p -u hash newkey ttl)"},
				cli.BoolFlag{Name: "l", Usage: "list of p2p instances (p2p -l)"},
				cli.BoolFlag{Name: "p", Usage: "list of p2p participants (p2p -p hash)"}},
			Action: func(c *cli.Context) {
				lib.P2P(c.Bool("c"), c.Bool("d"), c.Bool("u"), c.Bool("l"), c.Bool("p"), os.Args)
			}}},

		Action: func(c *cli.Context) {
			lib.LxcManagementNetwork(os.Args)
		}}, {

		Name: "metrics", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "start time"},
			cli.StringFlag{Name: "e", Usage: "end time"}},
		Action: func(c *cli.Context) {
			lib.HostMetrics(c.Args().Get(0), c.String("s"), c.String("e"))
		}}, {

		Name: "network", Usage: "containerName set/remove/list network vlan id",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "set, s", Usage: "IPADDRESS/NETMASK"},
			cli.StringFlag{Name: "vlan, v", Usage: "vlanid"},
			cli.BoolFlag{Name: "remove, r", Usage: ""},
			cli.BoolFlag{Name: "list, l", Usage: ""},
		},
		Action: func(c *cli.Context) {
			lib.LxcNetwork(c.Args().Get(0), c.String("s"), c.String("vlan"), c.Bool("r"), c.Bool("l"))
		}}, {

		Name: "promote", Usage: "promote Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcPromote(c.Args().Get(0))
		}}, {

		Name: "proxy", Usage: "Subutai reverse proxy",
		Subcommands: []cli.Command{
			{
				Name:     "add",
				Usage:    "add reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.StringFlag{Name: "domain,d", Usage: "add domain to vlan"},
					cli.StringFlag{Name: "host, h", Usage: "add host to domain on vlan"},
					cli.StringFlag{Name: "policy, p", Usage: "set load balance policy (rr|lb|hash)"},
					cli.StringFlag{Name: "file, f", Usage: "specify pem certificate file"}},
				Action: func(c *cli.Context) {
					lib.ProxyAdd(c.Args().Get(0), c.String("d"), c.String("h"), c.String("p"), c.String("f"))
				},
			},
			{
				Name:     "del",
				Usage:    "del reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "delete domain from vlan"},
					cli.StringFlag{Name: "host, h", Usage: "delete host from domain on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyDel(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
			{
				Name:     "check",
				Usage:    "check existing domain or host",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "check domains on vlan"},
					cli.StringFlag{Name: "host, h", Usage: "check hosts on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyCheck(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
		}}, {

		Name: "quota", Usage: "set quotas for Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "set quota for the specified resource type"},
			cli.StringFlag{Name: "t", Usage: "set alert threshold"}},
		Action: func(c *cli.Context) {
			lib.LxcQuota(c.Args().Get(0), c.Args().Get(1), c.String("s"), c.String("t"))
		}}, {

		Name: "register", Usage: "register Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRegister(c.Args().Get(0))
		}}, {

		Name: "rename", Usage: "rename Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRename(c.Args().Get(0), c.Args().Get(1))
		}}, {

		Name: "restore", Usage: "restore Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "d", Usage: "date of backup snapshot"},
			cli.StringFlag{Name: "c", Usage: "name of new container"}},
		Action: func(c *cli.Context) {
			lib.RestoreContainer(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "stats", Usage: "statistics from host",
		Action: func(c *cli.Context) {
			lib.Stats(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "start", Usage: "start Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStart(c.Args().Get(0))
		}}, {

		Name: "stop", Usage: "stop Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStop(c.Args().Get(0))
		}}, {

		Name: "tunnel", Usage: "create SSH tunnel",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "g", Usage: "global accessible tunnel"}},
		Action: func(c *cli.Context) {
			lib.Tunnel(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2), c.Bool("g"))
		}}, {

		Name: "unregister", Usage: "unregister Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcUnregister(c.Args().Get(0))
		}}, {

		Name: "update", Usage: "update Subutai management, container or Resource host",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "check for updates without installation"}},
		Action: func(c *cli.Context) {
			lib.Update(c.Args().Get(0), c.Bool("c"))
		}},
	}

	app.Run(os.Args)
}
<commit_msg>Agent version RC11-SNAPSHOT<commit_after>package main

import (
	"os"

	"github.com/subutai-io/base/agent/agent"
	"github.com/subutai-io/base/agent/cli"
	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/log"

	"github.com/codegangsta/cli"
)

var TIMESTAMP string = "-unknown"

func init() {
	if os.Getuid() != 0 {
		log.Error("Please run as root")
	}
	os.Setenv("PATH", "/apps/subutai/current/bin:"+os.Getenv("PATH"))
	if len(os.Args) > 1 {
		if os.Args[1] == "-d" {
			log.Level(log.DebugLevel)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "Subutai"
	app.Version = "4.0.0-RC11-SNAPSHOT"
	app.Usage = "daemon and command line interface binary"

	app.Flags = []cli.Flag{cli.BoolFlag{
		Name:  "d",
		Usage: "debug mode"}}

	app.Commands = []cli.Command{{
		Name: "attach", Usage: "attach to container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "clear environment"},
			cli.BoolFlag{Name: "x", Usage: "use x86 personality"},
			cli.BoolFlag{Name: "r", Usage: "connect as regular user"}},
		Action: func(c *cli.Context) {
			lib.LxcAttach(c.Args().Get(0), c.Bool("c"), c.Bool("x"), c.Bool("r"))
		}}, {

		Name: "backup", Usage: "backup Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "full", Usage: "make full backup"},
			cli.BoolFlag{Name: "stop", Usage: "stop container at the time of backup"}},
		Action: func(c *cli.Context) {
			lib.BackupContainer(c.Args().Get(0), c.Bool("full"), c.Bool("stop"))
		}}, {

		Name: "batch", Usage: "batch commands execution",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "json", Usage: "JSON string with commands"}},
		Action: func(c *cli.Context) {
			lib.Batch(c.String("json"))
		}}, {

		Name: "clone", Usage: "clone Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "e", Usage: "set environment id for container"},
			cli.StringFlag{Name: "i", Usage: "set container IP address and VLAN"},
			cli.StringFlag{Name: "t", Usage: "token to verify with MH"}},
		Action: func(c *cli.Context) {
			lib.LxcClone(c.Args().Get(0), c.Args().Get(1), c.String("e"), c.String("i"), c.String("t"))
		}}, {

		Name: "cleanup", Usage: "clean Subutai environment",
		Action: func(c *cli.Context) {
			lib.Cleanup(c.Args().Get(0))
		}}, {

		Name: "config", Usage: "containerName add/del key value",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "o", Usage: "add/del key value"},
			cli.StringFlag{Name: "k", Usage: "add/del key value"},
			cli.StringFlag{Name: "v", Usage: "add/del key value"},
		},
		Action: func(c *cli.Context) {
			lib.LxcConfig(c.Args().Get(0), c.String("o"), c.String("k"), c.String("v"))
		}}, {

		Name: "daemon", Usage: "start an agent",
		Action: func(c *cli.Context) {
			config.InitAgentDebug()
			agent.Start(c)
		}}, {

		Name: "demote", Usage: "demote Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "i", Usage: "network value ie 192.168.1.1/24"},
			cli.StringFlag{Name: "v", Usage: "vlan id"},
		},
		Action: func(c *cli.Context) {
			lib.LxcDemote(c.Args().Get(0), c.String("i"), c.String("v"))
		}}, {

		Name: "destroy", Usage: "destroy Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcDestroy(c.Args().Get(0))
		}}, {

		Name: "export", Usage: "export Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"}},
		Action: func(c *cli.Context) {
			lib.LxcExport(c.Args().Get(0), c.String("v"))
		}}, {

		Name: "import", Usage: "import Subutai template",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "v", Usage: "template version"},
			cli.StringFlag{Name: "t", Usage: "token to access kurjun repo"}},
		Action: func(c *cli.Context) {
			lib.LxcImport(c.Args().Get(0), c.String("v"), c.String("t"))
		}}, {

		Name: "list", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "containers only"},
			cli.BoolFlag{Name: "t", Usage: "templates only"},
			cli.BoolFlag{Name: "i", Usage: "detailed container info"},
			cli.BoolFlag{Name: "a", Usage: "with ancestors"},
			cli.BoolFlag{Name: "p", Usage: "with parent"}},
		Action: func(c *cli.Context) {
			lib.LxcList(c.Args().Get(0), c.Bool("c"), c.Bool("t"), c.Bool("i"), c.Bool("a"), c.Bool("p"))
		}}, {

		Name: "management_network", Usage: "configure management network",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "listtunnel, l", Usage: "-l"},
			cli.StringFlag{Name: "createtunnel, c", Usage: "-c TUNNELPORTNAME TUNNELIPADDRESS TUNNELTYPE"},

			cli.BoolFlag{Name: "listvnimap, v", Usage: "-v"},
			cli.StringFlag{Name: "createvnimap, m", Usage: "-m TUNNELPORTNAME VNI VLANID ENV_ID"},
		},

		Subcommands: []cli.Command{{
			Name:  "tunnel",
			Usage: "tunnels operation",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "create", Usage: "create tunnel (tunnel -c)"},
				cli.StringFlag{Name: "delete", Usage: "delete tunnel (tunnel -d)"},
				cli.BoolFlag{Name: "list", Usage: "list of tunnels (tunnel -l)"},

				cli.StringFlag{Name: "remoteip", Usage: "remote ip"},
				cli.StringFlag{Name: "vlan", Usage: "tunnel vlan"},
				cli.StringFlag{Name: "vni", Usage: "vni"},
			},
			Action: func(c *cli.Context) {
				lib.VxlanTunnel(c.String("create"), c.String("delete"), c.String("remoteip"), c.String("vlan"), c.String("vni"), c.Bool("list"))
			}}, {

			Name:  "p2p",
			Usage: "p2p network operation",
			Flags: []cli.Flag{
				cli.BoolFlag{Name: "c", Usage: "create p2p instance (p2p -c interfaceName hash key ttl localPeepIPAddr)"},
				cli.BoolFlag{Name: "d", Usage: "delete p2p instance (p2p -d hash)"},
				cli.BoolFlag{Name: "u", Usage: "update p2p instance encryption key (p2p -u hash newkey ttl)"},
				cli.BoolFlag{Name: "l", Usage: "list of p2p instances (p2p -l)"},
				cli.BoolFlag{Name: "p", Usage: "list of p2p participants (p2p -p hash)"}},
			Action: func(c *cli.Context) {
				lib.P2P(c.Bool("c"), c.Bool("d"), c.Bool("u"), c.Bool("l"), c.Bool("p"), os.Args)
			}}},

		Action: func(c *cli.Context) {
			lib.LxcManagementNetwork(os.Args)
		}}, {

		Name: "metrics", Usage: "list Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "start time"},
			cli.StringFlag{Name: "e", Usage: "end time"}},
		Action: func(c *cli.Context) {
			lib.HostMetrics(c.Args().Get(0), c.String("s"), c.String("e"))
		}}, {

		Name: "network", Usage: "containerName set/remove/list network vlan id",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "set, s", Usage: "IPADDRESS/NETMASK"},
			cli.StringFlag{Name: "vlan, v", Usage: "vlanid"},
			cli.BoolFlag{Name: "remove, r", Usage: ""},
			cli.BoolFlag{Name: "list, l", Usage: ""},
		},
		Action: func(c *cli.Context) {
			lib.LxcNetwork(c.Args().Get(0), c.String("s"), c.String("vlan"), c.Bool("r"), c.Bool("l"))
		}}, {

		Name: "promote", Usage: "promote Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcPromote(c.Args().Get(0))
		}}, {

		Name: "proxy", Usage: "Subutai reverse proxy",
		Subcommands: []cli.Command{
			{
				Name:     "add",
				Usage:    "add reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.StringFlag{Name: "domain,d", Usage: "add domain to vlan"},
					cli.StringFlag{Name: "host, h", Usage: "add host to domain on vlan"},
					cli.StringFlag{Name: "policy, p", Usage: "set load balance policy (rr|lb|hash)"},
					cli.StringFlag{Name: "file, f", Usage: "specify pem certificate file"}},
				Action: func(c *cli.Context) {
					lib.ProxyAdd(c.Args().Get(0), c.String("d"), c.String("h"), c.String("p"), c.String("f"))
				},
			},
			{
				Name:     "del",
				Usage:    "del reverse proxy component",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "delete domain from vlan"},
					cli.StringFlag{Name: "host, h", Usage: "delete host from domain on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyDel(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
			{
				Name:     "check",
				Usage:    "check existing domain or host",
				HideHelp: true,
				Flags: []cli.Flag{
					cli.BoolFlag{Name: "domain, d", Usage: "check domains on vlan"},
					cli.StringFlag{Name: "host, h", Usage: "check hosts on vlan"}},
				Action: func(c *cli.Context) {
					lib.ProxyCheck(c.Args().Get(0), c.String("h"), c.Bool("d"))
				},
			},
		}}, {

		Name: "quota", Usage: "set quotas for Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "s", Usage: "set quota for the specified resource type"},
			cli.StringFlag{Name: "t", Usage: "set alert threshold"}},
		Action: func(c *cli.Context) {
			lib.LxcQuota(c.Args().Get(0), c.Args().Get(1), c.String("s"), c.String("t"))
		}}, {

		Name: "register", Usage: "register Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRegister(c.Args().Get(0))
		}}, {

		Name: "rename", Usage: "rename Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcRename(c.Args().Get(0), c.Args().Get(1))
		}}, {

		Name: "restore", Usage: "restore Subutai container",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "d", Usage: "date of backup snapshot"},
			cli.StringFlag{Name: "c", Usage: "name of new container"}},
		Action: func(c *cli.Context) {
			lib.RestoreContainer(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "stats", Usage: "statistics from host",
		Action: func(c *cli.Context) {
			lib.Stats(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2))
		}}, {

		Name: "start", Usage: "start Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStart(c.Args().Get(0))
		}}, {

		Name: "stop", Usage: "stop Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcStop(c.Args().Get(0))
		}}, {

		Name: "tunnel", Usage: "create SSH tunnel",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "g", Usage: "global accessible tunnel"}},
		Action: func(c *cli.Context) {
			lib.Tunnel(c.Args().Get(0), c.Args().Get(1), c.Args().Get(2), c.Bool("g"))
		}}, {

		Name: "unregister", Usage: "unregister Subutai container",
		Action: func(c *cli.Context) {
			lib.LxcUnregister(c.Args().Get(0))
		}}, {

		Name: "update", Usage: "update Subutai management, container or Resource host",
		Flags: []cli.Flag{
			cli.BoolFlag{Name: "c", Usage: "check for updates without installation"}},
		Action: func(c *cli.Context) {
			lib.Update(c.Args().Get(0), c.Bool("c"))
		}},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build nocgo

package user

import (
	"fmt"
	"runtime"
)

func Lookup(username string) (*User, error) {
	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

func LookupId(int) (*User, error) {
	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
<commit_msg>os/user: not on windows<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build nocgo windows

package user

import (
	"fmt"
	"runtime"
)

func Lookup(username string) (*User, error) {
	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

func LookupId(int) (*User, error) {
	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
<|endoftext|>