<commit_before>/*
Copyright 2014 Workiva, LLC

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 palm

import (
	"log"
	"runtime"
	"sync"
	"sync/atomic"
	//"time"

	"github.com/Workiva/go-datastructures/queue"
)

type operation int

const (
	get operation = iota
	add
	remove
)

type recursiveBuild struct {
	keys   Keys
	nodes  []*node
	parent *node
}

type ptree struct {
	root                      *node
	ary, number, cacheBuffer1 uint64
	actions                   *queue.RingBuffer
	bufferSize, cacheBuffer2  uint64
	cache                     []interface{}
	cacheBuffer3              uint64
	disposed, cacheBuffer4    uint64
	running, cacheBuffer5     uint64
}

func (ptree *ptree) checkAndRun(ifc interface{}) {
	if ptree.actions.Len() > 0 {
		if ifc != nil {
			ptree.actions.Put(ifc)
		}
		if atomic.CompareAndSwapUint64(&ptree.running, 0, 1) {
			var a interface{}
			var err error
			for ptree.actions.Len() > 0 {
				a, err = ptree.actions.Get()
				if err != nil {
					return
				}
				ptree.cache = append(ptree.cache, a)
				if uint64(len(ptree.cache)) >= ptree.bufferSize {
					break
				}
			}

			go ptree.runOperations(ptree.cache)
		}
	} else if ifc != nil {
		if atomic.CompareAndSwapUint64(&ptree.running, 0, 1) {
			switch ifc.(type) {
			case *getAction:
				ptree.read(ifc.(*getAction))
				ifc.(*getAction).complete()
				ptree.reset()
			default:
				ptree.runOperations([]interface{}{ifc})
			}
		} else {
			ptree.actions.Put(ifc)
			ptree.checkAndRun(nil)
		}
	}
}

func (ptree *ptree) init(bufferSize, ary uint64) {
	ptree.bufferSize = bufferSize
	ptree.ary = ary
	ptree.cache = make([]interface{}, 0, bufferSize)
	ptree.root = newNode(true, newKeys(), newNodes())
	ptree.actions = queue.NewRingBuffer(ptree.bufferSize)
}

func (ptree *ptree) read(action action) {
	for i, k := range action.keys() {
		n := getParent(ptree.root, k)
		if n == nil {
			action.keys()[i] = nil
		} else {
			key, _ := n.keys.withPosition(k)
			if key == nil {
				action.keys()[i] = nil
			} else {
				action.keys()[i] = key
			}
		}
	}
}

func (ptree *ptree) reset() {
	for i := range ptree.cache {
		ptree.cache[i] = nil
	}

	ptree.cache = ptree.cache[:0]
	atomic.StoreUint64(&ptree.running, 0)
	ptree.checkAndRun(nil)
}

func (ptree *ptree) runOperations(xns []interface{}) {
	i := int64(0)
	js := make([]int64, 0, len(xns))
	for j := 0; j < len(xns); j++ {
		js = append(js, -1)
	}
	numCPU := runtime.NumCPU()
	if numCPU > 1 {
		numCPU--
	}
	var wg sync.WaitGroup
	wg.Add(numCPU)

	for k := 0; k < numCPU; k++ {
		go func() {
			defer wg.Done()
			for {
				index := atomic.LoadInt64(&i)
				if index >= int64(len(xns)) {
					return
				}
				action := xns[index].(action)

				j := atomic.AddInt64(&js[index], 1)
				if j > int64(len(action.keys())) { // someone else is updating i
					continue
				} else if j == int64(len(action.keys())) {
					atomic.StoreInt64(&i, index+1)
					continue
				}

				n := getParent(ptree.root, action.keys()[j])
				switch action.operation() {
				case add:
					action.addNode(j, n)
				case get:
					if n == nil {
						action.keys()[j] = nil
					} else {
						k, _ := n.keys.withPosition(action.keys()[j])
						if k == nil {
							action.keys()[j] = nil
						} else {
							action.keys()[j] = k
						}
					}
				}
			}
		}()
	}

	wg.Wait()

	writeOperations := make(map[*node]Keys)
	toComplete := make(actions, 0, len(xns)/2)
	for _, ifc := range xns {
		action := ifc.(action)
		switch action.operation() {
		case add:
			for i, n := range action.nodes() {
				writeOperations[n] = append(writeOperations[n], action.keys()[i])
			}
			toComplete = append(toComplete, action)
		case get:
			action.complete()
		}
	}

	ptree.runAdds(writeOperations)
	for _, a := range toComplete {
		a.complete()
	}

	ptree.reset()
}

func (ptree *ptree) recursiveSplit(n, parent, left *node, nodes *[]*node, keys *Keys) {
	if !n.needsSplit(ptree.ary) {
		return
	}

	key, l, r := n.split()
	if left != nil {
		left.right = l
	}
	l.parent = parent
	r.parent = parent
	*keys = append(*keys, key)
	*nodes = append(*nodes, l, r)
	ptree.recursiveSplit(l, parent, left, nodes, keys)
	ptree.recursiveSplit(r, parent, l, nodes, keys)
}

func (ptree *ptree) recursiveAdd(layer map[*node][]*recursiveBuild, setRoot bool) {
	if len(layer) == 0 {
		return
	}

	if setRoot && len(layer) > 1 {
		panic(`SHOULD ONLY HAVE ONE ROOT`)
	}

	ifs := make(interfaces, 0, len(layer))
	for _, rbs := range layer {
		ifs = append(ifs, rbs)
	}

	var write sync.Mutex
	layer = make(map[*node][]*recursiveBuild, len(layer))
	dummyRoot := &node{
		keys:  newKeys(),
		nodes: newNodes(),
	}
	executeInterfacesInParallel(ifs, func(ifc interface{}) {
		rbs := ifc.([]*recursiveBuild)

		if len(rbs) == 0 {
			return
		}

		n := rbs[0].parent
		if setRoot {
			ptree.root = n
		}

		parent := n.parent
		if parent == nil {
			parent = dummyRoot
			setRoot = true
		}

		for _, rb := range rbs {
			for i, k := range rb.keys {
				if n.keys.len() == 0 {
					n.keys.insert(k)
					n.nodes.push(rb.nodes[i*2])
					n.nodes.push(rb.nodes[i*2+1])
					continue
				}

				n.keys.insert(k)
				index := n.search(k)
				n.nodes.replaceAt(index, rb.nodes[i*2])
				n.nodes.insertAt(index+1, rb.nodes[i*2+1])
			}
		}

		if n.needsSplit(ptree.ary) {
			keys := make(Keys, 0, n.keys.len())
			nodes := make([]*node, 0, n.nodes.len())
			ptree.recursiveSplit(n, parent, nil, &nodes, &keys)
			write.Lock()
			layer[parent] = append(
				layer[parent], &recursiveBuild{keys: keys, nodes: nodes, parent: parent},
			)
			write.Unlock()
		}
	})

	ptree.recursiveAdd(layer, setRoot)
}

func (ptree *ptree) runAdds(addOperations map[*node]Keys) {
	if len(addOperations) == 0 {
		return
	}

	ifs := make(interfaces, 0, len(addOperations))
	for n := range addOperations {
		ifs = append(ifs, n)
	}

	var write sync.Mutex
	nextLayer := make(map[*node][]*recursiveBuild)
	dummyRoot := &node{} // constructed in case we need it
	var needRoot uint64
	executeInterfacesInParallel(ifs, func(ifc interface{}) {
		n := ifc.(*node)
		keys := addOperations[n]

		if len(keys) == 0 {
			return
		}

		parent := n.parent
		if parent == nil {
			parent = dummyRoot
			atomic.AddUint64(&needRoot, 1)
		}

		for _, key := range keys {
			oldKey := n.keys.insert(key)
			if oldKey == nil {
				atomic.AddUint64(&ptree.number, 1)
			}
		}

		if n.needsSplit(ptree.ary) {
			keys := make(Keys, 0, n.keys.len())
			nodes := make([]*node, 0, n.nodes.len())
			ptree.recursiveSplit(n, parent, nil, &nodes, &keys)
			write.Lock()
			nextLayer[parent] = append(
				nextLayer[parent], &recursiveBuild{keys: keys, nodes: nodes, parent: parent},
			)
			write.Unlock()
		}
	})

	setRoot := needRoot > 0
	if setRoot {
		dummyRoot.keys = newKeys()
		dummyRoot.nodes = newNodes()
	}

	ptree.recursiveAdd(nextLayer, setRoot)
}

// Insert will add the provided keys to the tree.
func (ptree *ptree) Insert(keys ...Key) {
	ia := newInsertAction(keys)
	ptree.checkAndRun(ia)
	ia.completer.Wait()
}

// Get will retrieve a list of keys from the provided keys.
func (ptree *ptree) Get(keys ...Key) Keys {
	ga := newGetAction(keys)
	//t0 := time.Now()
	ptree.checkAndRun(ga)
	//log.Printf(`ALLOCATE TIME: %+v`, time.Since(t0).Nanoseconds())
	ga.completer.Wait()
	//log.Printf(`GET TIME: %+v`, time.Since(t0).Nanoseconds())
	return ga.result
}

// Len returns the number of items in the tree.
func (ptree *ptree) Len() uint64 {
	return atomic.LoadUint64(&ptree.number)
}

// Dispose will clean up any resources used by this tree.  This
// must be called to prevent a memory leak.
func (ptree *ptree) Dispose() {
	ptree.actions.Dispose()
	atomic.StoreUint64(&ptree.disposed, 1)
}

func (ptree *ptree) print(output *log.Logger) {
	println(`PRINTING TREE`)
	if ptree.root == nil {
		return
	}

	ptree.root.print(output)
}

func newTree(bufferSize, ary uint64) *ptree {
	ptree := &ptree{}
	ptree.init(bufferSize, ary)
	return ptree
}

// New will allocate, initialize, and return a new B-Tree based
// on PALM principles.  This type of tree is suited for in-memory
// indices in a multi-threaded environment.
func New(bufferSize, ary uint64) BTree {
	return newTree(bufferSize, ary)
}
<commit_msg>Synchronous add.<commit_after>/*
Copyright 2014 Workiva, LLC

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 palm

import (
	"log"
	"runtime"
	"sync"
	"sync/atomic"
	//"time"

	"github.com/Workiva/go-datastructures/queue"
)

type operation int

const (
	get operation = iota
	add
	remove
)

type recursiveBuild struct {
	keys   Keys
	nodes  []*node
	parent *node
}

type ptree struct {
	root                      *node
	ary, number, cacheBuffer1 uint64
	actions                   *queue.RingBuffer
	bufferSize, cacheBuffer2  uint64
	cache                     []interface{}
	cacheBuffer3              uint64
	disposed, cacheBuffer4    uint64
	running, cacheBuffer5     uint64
}

func (ptree *ptree) checkAndRun(ifc interface{}) {
	if ptree.actions.Len() > 0 {
		if ifc != nil {
			ptree.actions.Put(ifc)
		}
		if atomic.CompareAndSwapUint64(&ptree.running, 0, 1) {
			var a interface{}
			var err error
			for ptree.actions.Len() > 0 {
				a, err = ptree.actions.Get()
				if err != nil {
					return
				}
				ptree.cache = append(ptree.cache, a)
				if uint64(len(ptree.cache)) >= ptree.bufferSize {
					break
				}
			}

			go ptree.operationRunner(ptree.cache)
		}
	} else if ifc != nil {
		if atomic.CompareAndSwapUint64(&ptree.running, 0, 1) {
			switch ifc.(type) {
			case *getAction:
				ptree.read(ifc.(*getAction))
				ifc.(*getAction).complete()
				ptree.reset()
			default:
				ptree.operationRunner(interfaces{ifc})
			}
		} else {
			ptree.actions.Put(ifc)
			ptree.checkAndRun(nil)
		}
	}
}

func (ptree *ptree) init(bufferSize, ary uint64) {
	ptree.bufferSize = bufferSize
	ptree.ary = ary
	ptree.cache = make([]interface{}, 0, bufferSize)
	ptree.root = newNode(true, newKeys(), newNodes())
	ptree.actions = queue.NewRingBuffer(ptree.bufferSize)
}

func (ptree *ptree) operationRunner(xns interfaces) {
	writeOperations, toComplete := ptree.fetchKeys(xns)
	ptree.runAdds(writeOperations)
	for _, a := range toComplete {
		a.complete()
	}

	ptree.reset()
}

func (ptree *ptree) read(action action) {
	for i, k := range action.keys() {
		n := getParent(ptree.root, k)
		if n == nil {
			action.keys()[i] = nil
		} else {
			key, _ := n.keys.withPosition(k)
			if key == nil {
				action.keys()[i] = nil
			} else {
				action.keys()[i] = key
			}
		}
	}
}

func (ptree *ptree) reset() {
	for i := range ptree.cache {
		ptree.cache[i] = nil
	}

	ptree.cache = ptree.cache[:0]
	atomic.StoreUint64(&ptree.running, 0)
	ptree.checkAndRun(nil)
}

func (ptree *ptree) fetchKeys(xns []interface{}) (map[*node]Keys, actions) {
	i := int64(0)
	js := make([]int64, 0, len(xns))
	for j := 0; j < len(xns); j++ {
		js = append(js, -1)
	}
	numCPU := runtime.NumCPU()
	if numCPU > 1 {
		numCPU--
	}
	var wg sync.WaitGroup
	wg.Add(numCPU)

	for k := 0; k < numCPU; k++ {
		go func() {
			defer wg.Done()
			for {
				index := atomic.LoadInt64(&i)
				if index >= int64(len(xns)) {
					return
				}
				action := xns[index].(action)

				j := atomic.AddInt64(&js[index], 1)
				if j > int64(len(action.keys())) { // someone else is updating i
					continue
				} else if j == int64(len(action.keys())) {
					atomic.StoreInt64(&i, index+1)
					continue
				}

				n := getParent(ptree.root, action.keys()[j])
				switch action.operation() {
				case add:
					action.addNode(j, n)
				case get:
					if n == nil {
						action.keys()[j] = nil
					} else {
						k, _ := n.keys.withPosition(action.keys()[j])
						if k == nil {
							action.keys()[j] = nil
						} else {
							action.keys()[j] = k
						}
					}
				}
			}
		}()
	}

	wg.Wait()

	writeOperations := make(map[*node]Keys)
	toComplete := make(actions, 0, len(xns)/2)
	for _, ifc := range xns {
		action := ifc.(action)
		switch action.operation() {
		case add:
			for i, n := range action.nodes() {
				writeOperations[n] = append(writeOperations[n], action.keys()[i])
			}
			toComplete = append(toComplete, action)
		case get:
			action.complete()
		}
	}

	return writeOperations, toComplete
}

func (ptree *ptree) recursiveSplit(n, parent, left *node, nodes *[]*node, keys *Keys) {
	if !n.needsSplit(ptree.ary) {
		return
	}

	key, l, r := n.split()
	if left != nil {
		left.right = l
	}
	l.parent = parent
	r.parent = parent
	*keys = append(*keys, key)
	*nodes = append(*nodes, l, r)
	ptree.recursiveSplit(l, parent, left, nodes, keys)
	ptree.recursiveSplit(r, parent, l, nodes, keys)
}

func (ptree *ptree) recursiveAdd(layer map[*node][]*recursiveBuild, setRoot bool) {
	if len(layer) == 0 {
		return
	}

	if setRoot && len(layer) > 1 {
		panic(`SHOULD ONLY HAVE ONE ROOT`)
	}

	ifs := make(interfaces, 0, len(layer))
	for _, rbs := range layer {
		ifs = append(ifs, rbs)
	}

	var write sync.Mutex
	layer = make(map[*node][]*recursiveBuild, len(layer))
	dummyRoot := &node{
		keys:  newKeys(),
		nodes: newNodes(),
	}
	executeInterfacesInParallel(ifs, func(ifc interface{}) {
		rbs := ifc.([]*recursiveBuild)

		if len(rbs) == 0 {
			return
		}

		n := rbs[0].parent
		if setRoot {
			ptree.root = n
		}

		parent := n.parent
		if parent == nil {
			parent = dummyRoot
			setRoot = true
		}

		for _, rb := range rbs {
			for i, k := range rb.keys {
				if n.keys.len() == 0 {
					n.keys.insert(k)
					n.nodes.push(rb.nodes[i*2])
					n.nodes.push(rb.nodes[i*2+1])
					continue
				}

				n.keys.insert(k)
				index := n.search(k)
				n.nodes.replaceAt(index, rb.nodes[i*2])
				n.nodes.insertAt(index+1, rb.nodes[i*2+1])
			}
		}

		if n.needsSplit(ptree.ary) {
			keys := make(Keys, 0, n.keys.len())
			nodes := make([]*node, 0, n.nodes.len())
			ptree.recursiveSplit(n, parent, nil, &nodes, &keys)
			write.Lock()
			layer[parent] = append(
				layer[parent], &recursiveBuild{keys: keys, nodes: nodes, parent: parent},
			)
			write.Unlock()
		}
	})

	ptree.recursiveAdd(layer, setRoot)
}

func (ptree *ptree) runAdds(addOperations map[*node]Keys) {
	if len(addOperations) == 0 {
		return
	}

	ifs := make(interfaces, 0, len(addOperations))
	for n := range addOperations {
		ifs = append(ifs, n)
	}

	var write sync.Mutex
	nextLayer := make(map[*node][]*recursiveBuild)
	dummyRoot := &node{} // constructed in case we need it
	var needRoot uint64
	executeInterfacesInParallel(ifs, func(ifc interface{}) {
		n := ifc.(*node)
		keys := addOperations[n]

		if len(keys) == 0 {
			return
		}

		parent := n.parent
		if parent == nil {
			parent = dummyRoot
			atomic.AddUint64(&needRoot, 1)
		}

		for _, key := range keys {
			oldKey := n.keys.insert(key)
			if oldKey == nil {
				atomic.AddUint64(&ptree.number, 1)
			}
		}

		if n.needsSplit(ptree.ary) {
			keys := make(Keys, 0, n.keys.len())
			nodes := make([]*node, 0, n.nodes.len())
			ptree.recursiveSplit(n, parent, nil, &nodes, &keys)
			write.Lock()
			nextLayer[parent] = append(
				nextLayer[parent], &recursiveBuild{keys: keys, nodes: nodes, parent: parent},
			)
			write.Unlock()
		}
	})

	setRoot := needRoot > 0
	if setRoot {
		dummyRoot.keys = newKeys()
		dummyRoot.nodes = newNodes()
	}

	ptree.recursiveAdd(nextLayer, setRoot)
}

// Insert will add the provided keys to the tree.
func (ptree *ptree) Insert(keys ...Key) {
	ia := newInsertAction(keys)
	ptree.checkAndRun(ia)
	ia.completer.Wait()
}

// Get will retrieve a list of keys from the provided keys.
func (ptree *ptree) Get(keys ...Key) Keys {
	ga := newGetAction(keys)
	//t0 := time.Now()
	ptree.checkAndRun(ga)
	//log.Printf(`ALLOCATE TIME: %+v`, time.Since(t0).Nanoseconds())
	ga.completer.Wait()
	//log.Printf(`GET TIME: %+v`, time.Since(t0).Nanoseconds())
	return ga.result
}

// Len returns the number of items in the tree.
func (ptree *ptree) Len() uint64 {
	return atomic.LoadUint64(&ptree.number)
}

// Dispose will clean up any resources used by this tree.  This
// must be called to prevent a memory leak.
func (ptree *ptree) Dispose() {
	ptree.actions.Dispose()
	atomic.StoreUint64(&ptree.disposed, 1)
}

func (ptree *ptree) print(output *log.Logger) {
	println(`PRINTING TREE`)
	if ptree.root == nil {
		return
	}

	ptree.root.print(output)
}

func newTree(bufferSize, ary uint64) *ptree {
	ptree := &ptree{}
	ptree.init(bufferSize, ary)
	return ptree
}

// New will allocate, initialize, and return a new B-Tree based
// on PALM principles.  This type of tree is suited for in-memory
// indices in a multi-threaded environment.
func New(bufferSize, ary uint64) BTree {
	return newTree(bufferSize, ary)
}
<|endoftext|>


<commit_before>package debug

import (
	"io"
	"log"

	"github.com/Sirupsen/logrus"
)

/*
Copy of testing/iotest Read- and WriteLogger, but using %q instead of %x for printing
*/

type writeLogger struct {
	prefix string
	w      io.Writer
}

func (l *writeLogger) Write(p []byte) (n int, err error) {
	n, err = l.w.Write(p)
	if err != nil {
		log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
	} else {
		log.Printf("%s %q", l.prefix, string(p[0:n]))
	}
	return
}

// NewWriteLogger returns a writer that behaves like w except
// that it logs (using log.Printf) each write to standard error,
// printing the prefix and the hexadecimal data written.
func NewWriteLogger(prefix string, w io.Writer) io.Writer {
	return &writeLogger{prefix, w}
}

type readLogger struct {
	prefix string
	r      io.Reader
}

func (l *readLogger) Read(p []byte) (n int, err error) {
	n, err = l.r.Read(p)
	if err != nil {
		log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
	} else {
		log.Printf("%s %q", l.prefix, string(p[0:n]))
	}
	return
}

// NewReadLogger returns a reader that behaves like r except
// that it logs (using log.Print) each read to standard error,
// printing the prefix and the hexadecimal data written.
func NewReadLogger(prefix string, r io.Reader) io.Reader {
	return &readLogger{prefix, r}
}

// logrus version
// ==============

type readLogrus struct {
	e *logrus.Entry
	r io.Reader
}

func (l *readLogrus) Read(p []byte) (n int, err error) {
	n, err = l.r.Read(p)
	if err != nil {
		l.e.WithField("read", string(p[0:n])).WithField("err", err).Debug("errored logRead")
	} else {
		l.e.WithField("read", string(p[0:n])).Debug("logRead")
	}
	return
}

func NewReadLogrus(e *logrus.Entry, r io.Reader) io.Reader {
	return &readLogrus{e, r}
}

type writeLogrus struct {
	e *logrus.Entry
	w io.Writer
}

func (l *writeLogrus) Write(p []byte) (n int, err error) {
	n, err = l.w.Write(p)
	if err != nil {
		l.e.WithField("write", string(p[0:n])).WithField("err", err).Debug("errored logWrite")
	} else {
		l.e.WithField("write", string(p[0:n])).Debug("logWrite")
	}
	return
}

func NewWriteLogrus(e *logrus.Entry, w io.Writer) io.Writer {
	return &writeLogrus{e, w}
}
<commit_msg>debug: added readHexLogger<commit_after>package debug

import (
	"encoding/hex"
	"io"
	"log"

	"github.com/Sirupsen/logrus"
)

/*
Copy of testing/iotest Read- and WriteLogger, but using %q instead of %x for printing
*/

type writeLogger struct {
	prefix string
	w      io.Writer
}

func (l *writeLogger) Write(p []byte) (n int, err error) {
	n, err = l.w.Write(p)
	if err != nil {
		log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
	} else {
		log.Printf("%s %q", l.prefix, string(p[0:n]))
	}
	return
}

// NewWriteLogger returns a writer that behaves like w except
// that it logs (using log.Printf) each write to standard error,
// printing the prefix and the hexadecimal data written.
func NewWriteLogger(prefix string, w io.Writer) io.Writer {
	return &writeLogger{prefix, w}
}

type readLogger struct {
	prefix string
	r      io.Reader
}

func (l *readLogger) Read(p []byte) (n int, err error) {
	n, err = l.r.Read(p)
	if err != nil {
		log.Printf("%s %q: %v", l.prefix, string(p[0:n]), err)
	} else {
		log.Printf("%s %q", l.prefix, string(p[0:n]))
	}
	return
}

// NewReadLogger returns a reader that behaves like r except
// that it logs (using log.Print) each read to standard error,
// printing the prefix and the hexadecimal data written.
func NewReadLogger(prefix string, r io.Reader) io.Reader {
	return &readLogger{prefix, r}
}

type readHexLogger struct {
	prefix string
	r      io.Reader
}

func (l *readHexLogger) Read(p []byte) (n int, err error) {
	n, err = l.r.Read(p)
	if err != nil {
		log.Printf("%s (%d bytes) Error: %v", l.prefix, n, err)
	} else {
		log.Printf("%s (%d bytes)", l.prefix, n)
	}
	log.Print("\n" + hex.Dump(p[:n]))
	return
}

// NewReadHexLogger returns a reader that behaves like r except
// that it logs to stderr using ecoding/hex.
func NewReadHexLogger(prefix string, r io.Reader) io.Reader {
	return &readHexLogger{prefix, r}
}

// logrus version
// ==============

type readLogrus struct {
	e *logrus.Entry
	r io.Reader
}

func (l *readLogrus) Read(p []byte) (n int, err error) {
	n, err = l.r.Read(p)
	if err != nil {
		l.e.WithField("read", string(p[0:n])).WithField("err", err).Debug("errored logRead")
	} else {
		l.e.WithField("read", string(p[0:n])).Debug("logRead")
	}
	return
}

func NewReadLogrus(e *logrus.Entry, r io.Reader) io.Reader {
	return &readLogrus{e, r}
}

type writeLogrus struct {
	e *logrus.Entry
	w io.Writer
}

func (l *writeLogrus) Write(p []byte) (n int, err error) {
	n, err = l.w.Write(p)
	if err != nil {
		l.e.WithField("write", string(p[0:n])).WithField("err", err).Debug("errored logWrite")
	} else {
		l.e.WithField("write", string(p[0:n])).Debug("logWrite")
	}
	return
}

func NewWriteLogrus(e *logrus.Entry, w io.Writer) io.Writer {
	return &writeLogrus{e, w}
}
<|endoftext|>


<commit_before>// Copyright 2019 The Ebiten Authors
//
// 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.

// +build go1.13

package jsutil

import (
	"fmt"
	"reflect"
	"runtime"
	"syscall/js"
	"unsafe"
)

func Uint8ArrayToSlice(value js.Value) []byte {
	s := make([]byte, value.Get("byteLength").Int())
	js.CopyBytesToGo(s, value)
	return s
}

func ArrayBufferToSlice(value js.Value) []byte {
	return Uint8ArrayToSlice(js.Global().Get("Uint8Array").New(value))
}

func sliceToByteSlice(s interface{}) (bs []byte) {
	switch s := s.(type) {
	case []int8:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int16:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 2
		h.Cap *= 2
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint8:
		return s
	case []uint16:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 2
		h.Cap *= 2
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []float32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []float64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	default:
		panic(fmt.Sprintf("jsutil: unexpected value at sliceToBytesSlice: %T", s))
	}
	return
}

func SliceToTypedArray(s interface{}) (js.Value, func()) {
	switch s := s.(type) {
	case []int8:
		a := js.Global().Get("Uint8Array").New(len(s))
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int8Array").New(buf, a.Get("byteOffset"), a.Get("byteLength")), func() {}
	case []int16:
		a := js.Global().Get("Uint8Array").New(len(s) * 2)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {}
	case []int32:
		a := js.Global().Get("Uint8Array").New(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []uint8:
		a := js.Global().Get("Uint8Array").New(len(s))
		js.CopyBytesToJS(a, s)
		return a, func() {}
	case []uint16:
		a := js.Global().Get("Uint8Array").New(len(s) * 2)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Uint16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {}
	case []uint32:
		a := js.Global().Get("Uint8Array").New(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Uint32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []float32:
		a := js.Global().Get("Uint8Array").New(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []float64:
		a := js.Global().Get("Uint8Array").New(len(s) * 8)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Float64Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/8), func() {}
	default:
		panic(fmt.Sprintf("jsutil: unexpected value at SliceToTypedArray: %T", s))
	}
}
<commit_msg>jsutil: Avoid allocating ArrayBuffer unnecessarily<commit_after>// Copyright 2019 The Ebiten Authors
//
// 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.

// +build go1.13

package jsutil

import (
	"fmt"
	"reflect"
	"runtime"
	"syscall/js"
	"unsafe"
)

func Uint8ArrayToSlice(value js.Value) []byte {
	s := make([]byte, value.Get("byteLength").Int())
	js.CopyBytesToGo(s, value)
	return s
}

func ArrayBufferToSlice(value js.Value) []byte {
	return Uint8ArrayToSlice(js.Global().Get("Uint8Array").New(value))
}

func sliceToByteSlice(s interface{}) (bs []byte) {
	switch s := s.(type) {
	case []int8:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int16:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 2
		h.Cap *= 2
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []int64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint8:
		return s
	case []uint16:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 2
		h.Cap *= 2
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []uint64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []float32:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 4
		h.Cap *= 4
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	case []float64:
		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
		h.Len *= 8
		h.Cap *= 8
		bs = *(*[]byte)(unsafe.Pointer(h))
		runtime.KeepAlive(s)
	default:
		panic(fmt.Sprintf("jsutil: unexpected value at sliceToBytesSlice: %T", s))
	}
	return
}

var temporaryBuffer = js.Global().Get("ArrayBuffer").New(16)

func getTemporaryUint8Array(size int) js.Value {
	if l := temporaryBuffer.Get("byteLength").Int(); l < size {
		for l < size {
			l *= 2
		}
		temporaryBuffer = js.Global().Get("ArrayBuffer").New(l)
	}
	return js.Global().Get("Uint8Array").New(temporaryBuffer, 0, size)
}

func SliceToTypedArray(s interface{}) (js.Value, func()) {
	switch s := s.(type) {
	case []int8:
		a := getTemporaryUint8Array(len(s))
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int8Array").New(buf, a.Get("byteOffset"), a.Get("byteLength")), func() {}
	case []int16:
		a := getTemporaryUint8Array(len(s) * 2)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {}
	case []int32:
		a := getTemporaryUint8Array(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Int32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []uint8:
		a := getTemporaryUint8Array(len(s))
		js.CopyBytesToJS(a, s)
		return a, func() {}
	case []uint16:
		a := getTemporaryUint8Array(len(s) * 2)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Uint16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {}
	case []uint32:
		a := getTemporaryUint8Array(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Uint32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []float32:
		a := getTemporaryUint8Array(len(s) * 4)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {}
	case []float64:
		a := getTemporaryUint8Array(len(s) * 8)
		js.CopyBytesToJS(a, sliceToByteSlice(s))
		buf := a.Get("buffer")
		return js.Global().Get("Float64Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/8), func() {}
	default:
		panic(fmt.Sprintf("jsutil: unexpected value at SliceToTypedArray: %T", s))
	}
}
<|endoftext|>


<commit_before>package dns

import (
	"errors"
	"net"
	"strconv"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in ClassINET.

// SetReply creates a reply message from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question message, it sets the Question
// section, generates an Id and sets the RecursionDesired (RD)
// bit to true.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify message, it sets the Question
// section, generates an Id and sets the Authoritative (AA)
// bit to true.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error message suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.SetReply(request)
	dns.Rcode = rcode
	return dns
}

// SetRcodeFormatError creates a message with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update message. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates message for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	s.Ns = ns
	s.Mbox = mbox
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates message for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = 300
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	// EDNS0 is at the end of the additional section, start there.
	// We might want to change this to *only* look at the last two
	// records. So we see TSIG and/or OPT - this a slightly bigger
	// change though.
	for i := len(dns.Extra) - 1; i >= 0; i-- {
		if dns.Extra[i].Header().Rrtype == TypeOPT {
			return dns.Extra[i].(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domain name, it returns the number of
// labels and true, when a domain name is valid.  Note that non fully qualified
// domain name is considered valid, in this case the last label is counted in
// the number of labels.  When false is returned the number of labels is not
// defined.  Also note that this function is extremely liberal; almost any
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
// label fits in 63 characters, but there is no length check for the entire
// string s. I.e.  a domain name longer than 255 characters is considered valid.
func IsDomainName(s string) (labels int, ok bool) {
	_, labels, err := packDomainName(s, nil, 0, nil, false)
	return labels, err == nil
}

// IsSubDomain checks if child is indeed a child of the parent. If child and parent
// are the same domain true is returned as well.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareDomainName(parent, child) == CountLabel(parent)
}

// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
// The checking is performed on the binary payload.
func IsMsg(buf []byte) error {
	// Header
	if len(buf) < 12 {
		return errors.New("dns: bad message header")
	}
	// Header: Opcode
	// TODO(miek): more checks here, e.g. check all header bits.
	return nil
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false
	}
	return s[l-1] == '.'
}

// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
// This means the RRs need to have the same type, name, and class. Returns true
// if the RR set is valid, otherwise false.
func IsRRset(rrset []RR) bool {
	if len(rrset) == 0 {
		return false
	}
	if len(rrset) == 1 {
		return true
	}
	rrHeader := rrset[0].Header()
	rrType := rrHeader.Rrtype
	rrClass := rrHeader.Class
	rrName := rrHeader.Name

	for _, rr := range rrset[1:] {
		curRRHeader := rr.Header()
		if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
			// Mismatch between the records, so this is not a valid rrset for
			//signing/verifying
			return false
		}
	}

	return true
}

// Fqdn return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code.

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address suitable for reverse DNS (PTR) record lookups or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{err: "unrecognized address: " + addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t.
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	}
	return "TYPE" + strconv.Itoa(int(t))
}

// String returns the string representation for the class c.
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	}
	return "CLASS" + strconv.Itoa(int(c))
}

// String returns the string representation for the name n.
func (n Name) String() string {
	return sprintName(string(n))
}
<commit_msg>use the fudge (#441)<commit_after>package dns

import (
	"errors"
	"net"
	"strconv"
)

const hexDigit = "0123456789abcdef"

// Everything is assumed in ClassINET.

// SetReply creates a reply message from a request message.
func (dns *Msg) SetReply(request *Msg) *Msg {
	dns.Id = request.Id
	dns.RecursionDesired = request.RecursionDesired // Copy rd bit
	dns.Response = true
	dns.Opcode = OpcodeQuery
	dns.Rcode = RcodeSuccess
	if len(request.Question) > 0 {
		dns.Question = make([]Question, 1)
		dns.Question[0] = request.Question[0]
	}
	return dns
}

// SetQuestion creates a question message, it sets the Question
// section, generates an Id and sets the RecursionDesired (RD)
// bit to true.
func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
	dns.Id = Id()
	dns.RecursionDesired = true
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, t, ClassINET}
	return dns
}

// SetNotify creates a notify message, it sets the Question
// section, generates an Id and sets the Authoritative (AA)
// bit to true.
func (dns *Msg) SetNotify(z string) *Msg {
	dns.Opcode = OpcodeNotify
	dns.Authoritative = true
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetRcode creates an error message suitable for the request.
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
	dns.SetReply(request)
	dns.Rcode = rcode
	return dns
}

// SetRcodeFormatError creates a message with FormError set.
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
	dns.Rcode = RcodeFormatError
	dns.Opcode = OpcodeQuery
	dns.Response = true
	dns.Authoritative = false
	dns.Id = request.Id
	return dns
}

// SetUpdate makes the message a dynamic update message. It
// sets the ZONE section to: z, TypeSOA, ClassINET.
func (dns *Msg) SetUpdate(z string) *Msg {
	dns.Id = Id()
	dns.Response = false
	dns.Opcode = OpcodeUpdate
	dns.Compress = false // BIND9 cannot handle compression
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeSOA, ClassINET}
	return dns
}

// SetIxfr creates message for requesting an IXFR.
func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Ns = make([]RR, 1)
	s := new(SOA)
	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
	s.Serial = serial
	s.Ns = ns
	s.Mbox = mbox
	dns.Question[0] = Question{z, TypeIXFR, ClassINET}
	dns.Ns[0] = s
	return dns
}

// SetAxfr creates message for requesting an AXFR.
func (dns *Msg) SetAxfr(z string) *Msg {
	dns.Id = Id()
	dns.Question = make([]Question, 1)
	dns.Question[0] = Question{z, TypeAXFR, ClassINET}
	return dns
}

// SetTsig appends a TSIG RR to the message.
// This is only a skeleton TSIG RR that is added as the last RR in the
// additional section. The Tsig is calculated when the message is being send.
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
	t := new(TSIG)
	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
	t.Algorithm = algo
	t.Fudge = fudge
	t.TimeSigned = uint64(timesigned)
	t.OrigId = dns.Id
	dns.Extra = append(dns.Extra, t)
	return dns
}

// SetEdns0 appends a EDNS0 OPT RR to the message.
// TSIG should always the last RR in a message.
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
	e := new(OPT)
	e.Hdr.Name = "."
	e.Hdr.Rrtype = TypeOPT
	e.SetUDPSize(udpsize)
	if do {
		e.SetDo()
	}
	dns.Extra = append(dns.Extra, e)
	return dns
}

// IsTsig checks if the message has a TSIG record as the last record
// in the additional section. It returns the TSIG record found or nil.
func (dns *Msg) IsTsig() *TSIG {
	if len(dns.Extra) > 0 {
		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
			return dns.Extra[len(dns.Extra)-1].(*TSIG)
		}
	}
	return nil
}

// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
// record in the additional section will do. It returns the OPT record
// found or nil.
func (dns *Msg) IsEdns0() *OPT {
	// EDNS0 is at the end of the additional section, start there.
	// We might want to change this to *only* look at the last two
	// records. So we see TSIG and/or OPT - this a slightly bigger
	// change though.
	for i := len(dns.Extra) - 1; i >= 0; i-- {
		if dns.Extra[i].Header().Rrtype == TypeOPT {
			return dns.Extra[i].(*OPT)
		}
	}
	return nil
}

// IsDomainName checks if s is a valid domain name, it returns the number of
// labels and true, when a domain name is valid.  Note that non fully qualified
// domain name is considered valid, in this case the last label is counted in
// the number of labels.  When false is returned the number of labels is not
// defined.  Also note that this function is extremely liberal; almost any
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
// label fits in 63 characters, but there is no length check for the entire
// string s. I.e.  a domain name longer than 255 characters is considered valid.
func IsDomainName(s string) (labels int, ok bool) {
	_, labels, err := packDomainName(s, nil, 0, nil, false)
	return labels, err == nil
}

// IsSubDomain checks if child is indeed a child of the parent. If child and parent
// are the same domain true is returned as well.
func IsSubDomain(parent, child string) bool {
	// Entire child is contained in parent
	return CompareDomainName(parent, child) == CountLabel(parent)
}

// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
// The checking is performed on the binary payload.
func IsMsg(buf []byte) error {
	// Header
	if len(buf) < 12 {
		return errors.New("dns: bad message header")
	}
	// Header: Opcode
	// TODO(miek): more checks here, e.g. check all header bits.
	return nil
}

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
	l := len(s)
	if l == 0 {
		return false
	}
	return s[l-1] == '.'
}

// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
// This means the RRs need to have the same type, name, and class. Returns true
// if the RR set is valid, otherwise false.
func IsRRset(rrset []RR) bool {
	if len(rrset) == 0 {
		return false
	}
	if len(rrset) == 1 {
		return true
	}
	rrHeader := rrset[0].Header()
	rrType := rrHeader.Rrtype
	rrClass := rrHeader.Class
	rrName := rrHeader.Name

	for _, rr := range rrset[1:] {
		curRRHeader := rr.Header()
		if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
			// Mismatch between the records, so this is not a valid rrset for
			//signing/verifying
			return false
		}
	}

	return true
}

// Fqdn return the fully qualified domain name from s.
// If s is already fully qualified, it behaves as the identity function.
func Fqdn(s string) string {
	if IsFqdn(s) {
		return s
	}
	return s + "."
}

// Copied from the official Go code.

// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address suitable for reverse DNS (PTR) record lookups or an error if it fails
// to parse the IP address.
func ReverseAddr(addr string) (arpa string, err error) {
	ip := net.ParseIP(addr)
	if ip == nil {
		return "", &Error{err: "unrecognized address: " + addr}
	}
	if ip.To4() != nil {
		return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
			strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for i := len(ip) - 1; i >= 0; i-- {
		v := ip[i]
		buf = append(buf, hexDigit[v&0xF])
		buf = append(buf, '.')
		buf = append(buf, hexDigit[v>>4])
		buf = append(buf, '.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	buf = append(buf, "ip6.arpa."...)
	return string(buf), nil
}

// String returns the string representation for the type t.
func (t Type) String() string {
	if t1, ok := TypeToString[uint16(t)]; ok {
		return t1
	}
	return "TYPE" + strconv.Itoa(int(t))
}

// String returns the string representation for the class c.
func (c Class) String() string {
	if c1, ok := ClassToString[uint16(c)]; ok {
		return c1
	}
	return "CLASS" + strconv.Itoa(int(c))
}

// String returns the string representation for the name n.
func (n Name) String() string {
	return sprintName(string(n))
}
<|endoftext|>


<commit_before>package version

import (
	"fmt"
	"runtime"
	"strconv"
	"time"
)

var Version string = "0.0.0"
var GitCommit string = "unknown"
var BuildTime string = "unknown"

func String() string {
	built := BuildTime
	i, err := strconv.ParseInt(BuildTime, 10, 64)
	if err == nil {
		t := time.Unix(i, 0)
		built = t.Format(time.RFC3339)
	}
	return fmt.Sprintf("%s (git=%s) (built %s) using %s\n", Version, GitCommit, built, runtime.Version())
}
<commit_msg>Improve package documentation<commit_after>// Copyright 2015 The Sporting Exchange Limited. All rights reserved.
// Use of this source code is governed by a free license that can be
// found in the LICENSE file.

// Package version reports build metadata for the currently running binary.
package version

import (
	"fmt"
	"runtime"
	"strconv"
	"time"
)

// These vars get bound at build time using the --ldflags mechanism.
var (
	Version   = "0.0.0"
	GitCommit = "unknown"
	BuildTime = "unknown"
)

func String() string {
	built := BuildTime
	i, err := strconv.ParseInt(BuildTime, 10, 64)
	if err == nil {
		t := time.Unix(i, 0)
		built = t.Format(time.RFC3339)
	}
	return fmt.Sprintf("%s (git=%s) (built %s) using %s\n", Version, GitCommit, built, runtime.Version())
}
<|endoftext|>


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

package vulkan

import "github.com/google/gapid/gapis/memory"

// descriptorSetPoolReservation is the result of descriptor set reservation
// request to homoDescriptorSetPool. It contains the descriptor sets reserved
// for the requester to use. It implements the flushablePiece interface.
type descriptorSetPoolReservation struct {
	valid    bool
	descSets []VkDescriptorSet
	owner    flushableResource
}

// IsValid implements the flushablePiece interface, to show if the descriptor
// set reserved in this reservation are still valid to use.
func (res *descriptorSetPoolReservation) IsValid() bool {
	return res.valid
}

// Owner implements the flushablePiece interface, returns the descriptor set
// pool from where this reservation was made.
func (res *descriptorSetPoolReservation) Owner() flushableResource {
	return res.owner
}

// DescriptorSets returns a list of reserved descriptor sets.
func (res *descriptorSetPoolReservation) DescriptorSets() []VkDescriptorSet {
	return res.descSets
}

// homoDescriptorSetPool is a pool of homogeneous descriptor sets allocated with
// exact same layout and from same descriptor pool. It implements the
// flushableResource interface so all the descriptor sets reserved from it have
// their life time managed by this descriptor set pool.
type homoDescriptorSetPool struct {
	name              debugMarkerName
	dev               VkDevice
	layout            VkDescriptorSetLayout
	next              uint32
	capacity          uint32
	noFlushUntilFree  bool
	pools             []VkDescriptorPool
	descSets          []VkDescriptorSet
	users             map[flushableResourceUser]struct{}
	validReservations []*descriptorSetPoolReservation
}

// newHomoDescriptorSetPool creates a new homoDescriptorPool for the given
// descriptor set layout, and a pool with the given initial count of descriptor
// sets. If notFlushUntilFree is true, the pool will not invalidate any
// descriptor sets reserved from this pool, otherwise, only the descriptor sets
// reserved in the last reservation request is guanranteed to be valid to use,
// a new incoming reservation request may trigger a flush and invalidate
// previously reserved descriptor sets.
func newHomoDescriptorSetPool(sb *stateBuilder, nm debugMarkerName, dev VkDevice, layout VkDescriptorSetLayout, initialSetCount uint32, noFlushUntilFree bool) *homoDescriptorSetPool {
	p := &homoDescriptorSetPool{
		name:              nm,
		dev:               dev,
		layout:            layout,
		next:              0,
		capacity:          initialSetCount,
		noFlushUntilFree:  noFlushUntilFree,
		pools:             []VkDescriptorPool{},
		descSets:          []VkDescriptorSet{},
		users:             map[flushableResourceUser]struct{}{},
		validReservations: []*descriptorSetPoolReservation{},
	}
	p.pools = append(p.pools, p.createDescriptorPool(sb, p.capacity))
	p.descSets = append(p.descSets, p.allocateDescriptorSets(sb, p.pools[0], p.capacity)...)
	return p
}

// ReserveDescriptorSets reserves descriptor sets from this
// homoDescriptorSetPool for a specific count, returns a reservation that
// contains the reserved descriptor sets, and error. If the
// homoDescriptorSetPool was created with noFlushUntilFree set to false, call
// to this function may trigger a flush and all the previously reserved
// descriptor sets might be flushed.
func (dss *homoDescriptorSetPool) ReserveDescriptorSets(sb *stateBuilder, count uint32) (*descriptorSetPoolReservation, error) {
	if count+dss.next > dss.capacity {
		if dss.noFlushUntilFree {
			newDescSetCount := count + dss.next - dss.capacity
			pool := dss.createDescriptorPool(sb, newDescSetCount)
			newDescSets := dss.allocateDescriptorSets(sb, pool, newDescSetCount)
			dss.pools = append(dss.pools, pool)
			dss.descSets = append(dss.descSets, newDescSets...)
			dss.capacity += newDescSetCount
		} else {
			if count > dss.capacity {
				dss.capacity = count
			}
			dss.flush(sb)
		}
		return dss.ReserveDescriptorSets(sb, count)
	}
	current := dss.next
	dss.next += count
	reservation := &descriptorSetPoolReservation{
		valid:    true,
		descSets: dss.descSets[current : current+count],
		owner:    dss,
	}
	return reservation, nil
}

func (dss *homoDescriptorSetPool) createDescriptorPool(sb *stateBuilder, setCount uint32) VkDescriptorPool {
	layoutObj := GetState(sb.newState).DescriptorSetLayouts().Get(dss.layout)
	countPerType := map[VkDescriptorType]uint32{}
	for _, info := range layoutObj.Bindings().All() {
		countPerType[info.Type()] += info.Count()
	}
	for t := range countPerType {
		countPerType[t] *= setCount
	}
	poolSizes := []VkDescriptorPoolSize{}
	for t, c := range countPerType {
		poolSizes = append(poolSizes, NewVkDescriptorPoolSize(sb.ta, t, c))
	}

	handle := VkDescriptorPool(newUnusedID(true, func(x uint64) bool {
		return GetState(sb.newState).DescriptorPools().Contains(VkDescriptorPool(x)) || GetState(sb.oldState).DescriptorPools().Contains(VkDescriptorPool(x))
	}))
	sb.write(sb.cb.VkCreateDescriptorPool(
		dss.dev,
		sb.MustAllocReadData(NewVkDescriptorPoolCreateInfo(sb.ta,
			VkStructureType_VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
			0, // pNext
			VkDescriptorPoolCreateFlags(
				VkDescriptorPoolCreateFlagBits_VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT), // flags
			setCount,               // maxSets
			uint32(len(poolSizes)), // poolSizeCount
			NewVkDescriptorPoolSizeᶜᵖ(sb.MustAllocReadData(poolSizes).Ptr()), // pPoolSizes
		)).Ptr(),
		memory.Nullptr,
		sb.MustAllocWriteData(handle).Ptr(),
		VkResult_VK_SUCCESS,
	))
	if len(dss.name) > 0 {
		attachDebugMarkerName(sb, dss.name, dss.dev, handle)
	}
	return handle
}

func (dss *homoDescriptorSetPool) destroyAllDescriptorPool(sb *stateBuilder) {
	for _, pool := range dss.pools {
		sb.write(sb.cb.VkDestroyDescriptorPool(dss.dev, pool, memory.Nullptr))
	}
	dss.pools = []VkDescriptorPool{}
}

func (dss *homoDescriptorSetPool) allocateDescriptorSets(sb *stateBuilder, pool VkDescriptorPool, count uint32) []VkDescriptorSet {
	newSets := make([]VkDescriptorSet, count)
	for i := range newSets {
		newSets[i] = VkDescriptorSet(
			newUnusedID(true, func(x uint64) bool {
				return GetState(sb.newState).DescriptorSets().Contains(VkDescriptorSet(x))
			}))
	}
	layoutSlice := make([]VkDescriptorSetLayout, count)
	for i := range layoutSlice {
		layoutSlice[i] = dss.layout
	}
	sb.write(sb.cb.VkAllocateDescriptorSets(
		dss.dev,
		sb.MustAllocReadData(NewVkDescriptorSetAllocateInfo(sb.ta,
			VkStructureType_VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
			0,     // pNext
			pool,  // descriptorPool
			count, // descriptorSetCount
			NewVkDescriptorSetLayoutᶜᵖ(sb.MustAllocReadData(layoutSlice).Ptr()), // pSetLayouts
		)).Ptr(),
		sb.MustAllocWriteData(newSets).Ptr(),
		VkResult_VK_SUCCESS,
	))
	if len(dss.name) > 0 {
		for _, set := range newSets {
			attachDebugMarkerName(sb, dss.name, dss.dev, set)
		}
	}
	return newSets
}

// flush implements the flushableResource interface.
func (dss *homoDescriptorSetPool) flush(sb *stateBuilder) {
	for u := range dss.users {
		u.OnResourceFlush(sb, dss)
		delete(dss.users, u)
	}
	for _, res := range dss.validReservations {
		res.valid = false
	}
	dss.validReservations = []*descriptorSetPoolReservation{}
	dss.destroyAllDescriptorPool(sb)
	if dss.layout != VkDescriptorSetLayout(0) {
		pool := dss.createDescriptorPool(sb, dss.capacity)
		dss.pools = append(dss.pools, pool)
		dss.descSets = dss.allocateDescriptorSets(sb, pool, dss.capacity)
	}
	dss.next = 0
}

// AddUser implements the flushableResource interface. It registers a user of
// the descriptor sets reserved from this pool.
func (dss *homoDescriptorSetPool) AddUser(user flushableResourceUser) {
	dss.users[user] = struct{}{}
}

// DropUser implements the flushableResource interface. It removes a user from
// the user list of this pool.
func (dss *homoDescriptorSetPool) DropUser(user flushableResourceUser) {
	if _, ok := dss.users[user]; ok {
		delete(dss.users, user)
	}
}

// Free flushes all the descriptor sets reserved in this pool.
func (dss *homoDescriptorSetPool) Free(sb *stateBuilder) {
	dss.layout = VkDescriptorSetLayout(0)
	dss.flush(sb)
	dss.descSets = nil
}

// naiveImageViewPool is a simple map based pool of VkImageView.
type naiveImageViewPool struct {
	dev VkDevice
	// Use a pair of map + slice to free them in order
	viewsIndex map[ipImageViewInfo]int
	views      []VkImageView
}

func newNaiveImageViewPool(dev VkDevice) *naiveImageViewPool {
	return &naiveImageViewPool{
		dev:        dev,
		viewsIndex: map[ipImageViewInfo]int{},
		views:      []VkImageView{},
	}
}

func (p *naiveImageViewPool) getOrCreateImageView(sb *stateBuilder, nm debugMarkerName, info ipImageViewInfo) VkImageView {
	if i, ok := p.viewsIndex[info]; ok {
		return p.views[i]
	}
	handle := ipCreateImageView(sb, nm, p.dev, info)
	p.viewsIndex[info] = len(p.views)
	p.views = append(p.views, handle)
	return handle
}

// Free destroyes all the image views in this pool.
func (p *naiveImageViewPool) Free(sb *stateBuilder) {
	for _, v := range p.views {
		sb.write(sb.cb.VkDestroyImageView(p.dev, v, memory.Nullptr))
	}
	p.viewsIndex = map[ipImageViewInfo]int{}
	p.views = []VkImageView{}
	return
}

// naiveShaderModulePool is a simple map based pool of VkShaderModule
type naiveShaderModulePool struct {
	dev VkDevice
	// Use a pair of map + slice to free them in order
	shadersIndex map[ipShaderModuleInfo]int
	shaders      []VkShaderModule
}

func newNaiveShaderModulePool(dev VkDevice) *naiveShaderModulePool {
	return &naiveShaderModulePool{
		dev:          dev,
		shadersIndex: map[ipShaderModuleInfo]int{},
		shaders:      []VkShaderModule{},
	}
}

func (p *naiveShaderModulePool) getOrCreateShaderModule(sb *stateBuilder, nm debugMarkerName, info ipShaderModuleInfo) VkShaderModule {
	if i, ok := p.shadersIndex[info]; ok {
		return p.shaders[i]
	}
	handle, err := ipCreateShaderModule(sb, nm, p.dev, info)
	if err != nil {
		panic(err)
	}
	p.shadersIndex[info] = len(p.shaders)
	p.shaders = append(p.shaders, handle)
	return handle
}

// Free destroyes all the shader modules in this pool
func (p *naiveShaderModulePool) Free(sb *stateBuilder) {
	for _, s := range p.shaders {
		sb.write(sb.cb.VkDestroyShaderModule(p.dev, s, memory.Nullptr))
	}
	p.shadersIndex = map[ipShaderModuleInfo]int{}
	p.shaders = []VkShaderModule{}
	return
}
<commit_msg>Make createDescriptorPool deterministic<commit_after>// Copyright (C) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vulkan

import (
	"sort"

	"github.com/google/gapid/gapis/memory"
)

// descriptorSetPoolReservation is the result of descriptor set reservation
// request to homoDescriptorSetPool. It contains the descriptor sets reserved
// for the requester to use. It implements the flushablePiece interface.
type descriptorSetPoolReservation struct {
	valid    bool
	descSets []VkDescriptorSet
	owner    flushableResource
}

// IsValid implements the flushablePiece interface, to show if the descriptor
// set reserved in this reservation are still valid to use.
func (res *descriptorSetPoolReservation) IsValid() bool {
	return res.valid
}

// Owner implements the flushablePiece interface, returns the descriptor set
// pool from where this reservation was made.
func (res *descriptorSetPoolReservation) Owner() flushableResource {
	return res.owner
}

// DescriptorSets returns a list of reserved descriptor sets.
func (res *descriptorSetPoolReservation) DescriptorSets() []VkDescriptorSet {
	return res.descSets
}

// homoDescriptorSetPool is a pool of homogeneous descriptor sets allocated with
// exact same layout and from same descriptor pool. It implements the
// flushableResource interface so all the descriptor sets reserved from it have
// their life time managed by this descriptor set pool.
type homoDescriptorSetPool struct {
	name              debugMarkerName
	dev               VkDevice
	layout            VkDescriptorSetLayout
	next              uint32
	capacity          uint32
	noFlushUntilFree  bool
	pools             []VkDescriptorPool
	descSets          []VkDescriptorSet
	users             map[flushableResourceUser]struct{}
	validReservations []*descriptorSetPoolReservation
}

// newHomoDescriptorSetPool creates a new homoDescriptorPool for the given
// descriptor set layout, and a pool with the given initial count of descriptor
// sets. If notFlushUntilFree is true, the pool will not invalidate any
// descriptor sets reserved from this pool, otherwise, only the descriptor sets
// reserved in the last reservation request is guanranteed to be valid to use,
// a new incoming reservation request may trigger a flush and invalidate
// previously reserved descriptor sets.
func newHomoDescriptorSetPool(sb *stateBuilder, nm debugMarkerName, dev VkDevice, layout VkDescriptorSetLayout, initialSetCount uint32, noFlushUntilFree bool) *homoDescriptorSetPool {
	p := &homoDescriptorSetPool{
		name:              nm,
		dev:               dev,
		layout:            layout,
		next:              0,
		capacity:          initialSetCount,
		noFlushUntilFree:  noFlushUntilFree,
		pools:             []VkDescriptorPool{},
		descSets:          []VkDescriptorSet{},
		users:             map[flushableResourceUser]struct{}{},
		validReservations: []*descriptorSetPoolReservation{},
	}
	p.pools = append(p.pools, p.createDescriptorPool(sb, p.capacity))
	p.descSets = append(p.descSets, p.allocateDescriptorSets(sb, p.pools[0], p.capacity)...)
	return p
}

// ReserveDescriptorSets reserves descriptor sets from this
// homoDescriptorSetPool for a specific count, returns a reservation that
// contains the reserved descriptor sets, and error. If the
// homoDescriptorSetPool was created with noFlushUntilFree set to false, call
// to this function may trigger a flush and all the previously reserved
// descriptor sets might be flushed.
func (dss *homoDescriptorSetPool) ReserveDescriptorSets(sb *stateBuilder, count uint32) (*descriptorSetPoolReservation, error) {
	if count+dss.next > dss.capacity {
		if dss.noFlushUntilFree {
			newDescSetCount := count + dss.next - dss.capacity
			pool := dss.createDescriptorPool(sb, newDescSetCount)
			newDescSets := dss.allocateDescriptorSets(sb, pool, newDescSetCount)
			dss.pools = append(dss.pools, pool)
			dss.descSets = append(dss.descSets, newDescSets...)
			dss.capacity += newDescSetCount
		} else {
			if count > dss.capacity {
				dss.capacity = count
			}
			dss.flush(sb)
		}
		return dss.ReserveDescriptorSets(sb, count)
	}
	current := dss.next
	dss.next += count
	reservation := &descriptorSetPoolReservation{
		valid:    true,
		descSets: dss.descSets[current : current+count],
		owner:    dss,
	}
	return reservation, nil
}

func (dss *homoDescriptorSetPool) createDescriptorPool(sb *stateBuilder, setCount uint32) VkDescriptorPool {
	layoutObj := GetState(sb.newState).DescriptorSetLayouts().Get(dss.layout)
	countPerType := map[VkDescriptorType]uint32{}
	for _, info := range layoutObj.Bindings().All() {
		countPerType[info.Type()] += info.Count()
	}
	for t := range countPerType {
		countPerType[t] *= setCount
	}
	poolSizes := []VkDescriptorPoolSize{}
	// Create pool sizes in order
	keys := make([]VkDescriptorType, 0, len(countPerType))
	for k := range countPerType {
		keys = append(keys, k)
	}
	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
	for _, t := range keys {
		c := countPerType[t]
		poolSizes = append(poolSizes, NewVkDescriptorPoolSize(sb.ta, t, c))
	}

	handle := VkDescriptorPool(newUnusedID(true, func(x uint64) bool {
		return GetState(sb.newState).DescriptorPools().Contains(VkDescriptorPool(x)) || GetState(sb.oldState).DescriptorPools().Contains(VkDescriptorPool(x))
	}))
	sb.write(sb.cb.VkCreateDescriptorPool(
		dss.dev,
		sb.MustAllocReadData(NewVkDescriptorPoolCreateInfo(sb.ta,
			VkStructureType_VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
			0, // pNext
			VkDescriptorPoolCreateFlags(
				VkDescriptorPoolCreateFlagBits_VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT), // flags
			setCount,               // maxSets
			uint32(len(poolSizes)), // poolSizeCount
			NewVkDescriptorPoolSizeᶜᵖ(sb.MustAllocReadData(poolSizes).Ptr()), // pPoolSizes
		)).Ptr(),
		memory.Nullptr,
		sb.MustAllocWriteData(handle).Ptr(),
		VkResult_VK_SUCCESS,
	))
	if len(dss.name) > 0 {
		attachDebugMarkerName(sb, dss.name, dss.dev, handle)
	}
	return handle
}

func (dss *homoDescriptorSetPool) destroyAllDescriptorPool(sb *stateBuilder) {
	for _, pool := range dss.pools {
		sb.write(sb.cb.VkDestroyDescriptorPool(dss.dev, pool, memory.Nullptr))
	}
	dss.pools = []VkDescriptorPool{}
}

func (dss *homoDescriptorSetPool) allocateDescriptorSets(sb *stateBuilder, pool VkDescriptorPool, count uint32) []VkDescriptorSet {
	newSets := make([]VkDescriptorSet, count)
	for i := range newSets {
		newSets[i] = VkDescriptorSet(
			newUnusedID(true, func(x uint64) bool {
				return GetState(sb.newState).DescriptorSets().Contains(VkDescriptorSet(x))
			}))
	}
	layoutSlice := make([]VkDescriptorSetLayout, count)
	for i := range layoutSlice {
		layoutSlice[i] = dss.layout
	}
	sb.write(sb.cb.VkAllocateDescriptorSets(
		dss.dev,
		sb.MustAllocReadData(NewVkDescriptorSetAllocateInfo(sb.ta,
			VkStructureType_VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
			0,     // pNext
			pool,  // descriptorPool
			count, // descriptorSetCount
			NewVkDescriptorSetLayoutᶜᵖ(sb.MustAllocReadData(layoutSlice).Ptr()), // pSetLayouts
		)).Ptr(),
		sb.MustAllocWriteData(newSets).Ptr(),
		VkResult_VK_SUCCESS,
	))
	if len(dss.name) > 0 {
		for _, set := range newSets {
			attachDebugMarkerName(sb, dss.name, dss.dev, set)
		}
	}
	return newSets
}

// flush implements the flushableResource interface.
func (dss *homoDescriptorSetPool) flush(sb *stateBuilder) {
	for u := range dss.users {
		u.OnResourceFlush(sb, dss)
		delete(dss.users, u)
	}
	for _, res := range dss.validReservations {
		res.valid = false
	}
	dss.validReservations = []*descriptorSetPoolReservation{}
	dss.destroyAllDescriptorPool(sb)
	if dss.layout != VkDescriptorSetLayout(0) {
		pool := dss.createDescriptorPool(sb, dss.capacity)
		dss.pools = append(dss.pools, pool)
		dss.descSets = dss.allocateDescriptorSets(sb, pool, dss.capacity)
	}
	dss.next = 0
}

// AddUser implements the flushableResource interface. It registers a user of
// the descriptor sets reserved from this pool.
func (dss *homoDescriptorSetPool) AddUser(user flushableResourceUser) {
	dss.users[user] = struct{}{}
}

// DropUser implements the flushableResource interface. It removes a user from
// the user list of this pool.
func (dss *homoDescriptorSetPool) DropUser(user flushableResourceUser) {
	if _, ok := dss.users[user]; ok {
		delete(dss.users, user)
	}
}

// Free flushes all the descriptor sets reserved in this pool.
func (dss *homoDescriptorSetPool) Free(sb *stateBuilder) {
	dss.layout = VkDescriptorSetLayout(0)
	dss.flush(sb)
	dss.descSets = nil
}

// naiveImageViewPool is a simple map based pool of VkImageView.
type naiveImageViewPool struct {
	dev VkDevice
	// Use a pair of map + slice to free them in order
	viewsIndex map[ipImageViewInfo]int
	views      []VkImageView
}

func newNaiveImageViewPool(dev VkDevice) *naiveImageViewPool {
	return &naiveImageViewPool{
		dev:        dev,
		viewsIndex: map[ipImageViewInfo]int{},
		views:      []VkImageView{},
	}
}

func (p *naiveImageViewPool) getOrCreateImageView(sb *stateBuilder, nm debugMarkerName, info ipImageViewInfo) VkImageView {
	if i, ok := p.viewsIndex[info]; ok {
		return p.views[i]
	}
	handle := ipCreateImageView(sb, nm, p.dev, info)
	p.viewsIndex[info] = len(p.views)
	p.views = append(p.views, handle)
	return handle
}

// Free destroyes all the image views in this pool.
func (p *naiveImageViewPool) Free(sb *stateBuilder) {
	for _, v := range p.views {
		sb.write(sb.cb.VkDestroyImageView(p.dev, v, memory.Nullptr))
	}
	p.viewsIndex = map[ipImageViewInfo]int{}
	p.views = []VkImageView{}
	return
}

// naiveShaderModulePool is a simple map based pool of VkShaderModule
type naiveShaderModulePool struct {
	dev VkDevice
	// Use a pair of map + slice to free them in order
	shadersIndex map[ipShaderModuleInfo]int
	shaders      []VkShaderModule
}

func newNaiveShaderModulePool(dev VkDevice) *naiveShaderModulePool {
	return &naiveShaderModulePool{
		dev:          dev,
		shadersIndex: map[ipShaderModuleInfo]int{},
		shaders:      []VkShaderModule{},
	}
}

func (p *naiveShaderModulePool) getOrCreateShaderModule(sb *stateBuilder, nm debugMarkerName, info ipShaderModuleInfo) VkShaderModule {
	if i, ok := p.shadersIndex[info]; ok {
		return p.shaders[i]
	}
	handle, err := ipCreateShaderModule(sb, nm, p.dev, info)
	if err != nil {
		panic(err)
	}
	p.shadersIndex[info] = len(p.shaders)
	p.shaders = append(p.shaders, handle)
	return handle
}

// Free destroyes all the shader modules in this pool
func (p *naiveShaderModulePool) Free(sb *stateBuilder) {
	for _, s := range p.shaders {
		sb.write(sb.cb.VkDestroyShaderModule(p.dev, s, memory.Nullptr))
	}
	p.shadersIndex = map[ipShaderModuleInfo]int{}
	p.shaders = []VkShaderModule{}
	return
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/fatih/color"
	"github.com/gobuffalo/buffalo/generators/assets/webpack"
	rg "github.com/gobuffalo/buffalo/generators/refresh"
	"github.com/gobuffalo/buffalo/meta"
	"github.com/gobuffalo/events"
	"github.com/markbates/refresh/refresh"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"golang.org/x/sync/errgroup"
)

func init() {
	events.NamedListen("buffalo:dev", func(e events.Event) {
		if strings.HasPrefix(e.Kind, "refresh:") {
			e.Kind = strings.Replace(e.Kind, "refresh:", "buffalo:dev:", 1)
			events.Emit(e)
		}
	})
}

var devOptions = struct {
	Debug bool
}{}

// devCmd represents the dev command
var devCmd = &cobra.Command{
	Use:   "dev",
	Short: "Runs your Buffalo app in 'development' mode",
	Long: `Runs your Buffalo app in 'development' mode.
This includes rebuilding your application when files change.
This behavior can be changed in your .buffalo.dev.yml file.`,
	RunE: func(c *cobra.Command, args []string) error {
		if runtime.GOOS == "windows" {
			color.NoColor = true
		}
		defer func() {
			msg := "There was a problem starting the dev server, Please review the troubleshooting docs: %s\n"
			cause := "Unknown"
			if r := recover(); r != nil {
				if err, ok := r.(error); ok {
					cause = err.Error()
				}
			}
			logrus.Errorf(msg, cause)
		}()
		os.Setenv("GO_ENV", "development")

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()

		wg, ctx := errgroup.WithContext(ctx)

		wg.Go(func() error {
			return startDevServer(ctx)
		})

		wg.Go(func() error {
			return startWebpack(ctx)
		})

		err := wg.Wait()
		if err != context.Canceled {
			return errors.WithStack(err)
		}
		return nil
	},
}

func startWebpack(ctx context.Context) error {
	app := meta.New(".")
	if !app.WithWebpack {
		// there's no webpack, so don't do anything
		return nil
	}

	if _, err := os.Stat(filepath.Join(app.Root, "node_modules")); err != nil {
		tool := "yarnpkg"
		if !app.WithYarn {
			tool = "npm"
		}
		if _, err := exec.LookPath(tool); err != nil {
			return errors.Errorf("no node_modules directory found, and couldn't find %s to install it with", tool)
		}
		cmd := exec.CommandContext(ctx, tool, "install")
		cmd.Stdin = os.Stdin
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		if err := cmd.Run(); err != nil {
			return errors.WithStack(err)
		}
	}

	cmd := exec.CommandContext(ctx, webpack.BinPath, "--watch")
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func startDevServer(ctx context.Context) error {
	cfgFile := "./.buffalo.dev.yml"
	if _, err := os.Stat(cfgFile); err != nil {
		err = rg.Run("./", map[string]interface{}{
			"name": "buffalo",
		})
		if err != nil {
			return err
		}
	}
	c := &refresh.Configuration{}
	if err := c.Load(cfgFile); err != nil {
		return err
	}
	c.Debug = devOptions.Debug

	app := meta.New(".")
	bt := app.BuildTags("development")
	var tf []string
	for _, b := range bt {
		tf = append(tf, "-tags", b)
	}
	c.BuildFlags = append(c.BuildFlags, tf...)
	r := refresh.NewWithContext(c, ctx)
	return r.Start()
}

func init() {
	devCmd.Flags().BoolVarP(&devOptions.Debug, "debug", "d", false, "use delve to debug the app")
	decorate("dev", devCmd)
	RootCmd.AddCommand(devCmd)
}
<commit_msg>Builds with buffalo dev drop sqlite tag on syntax error fixes #1302 (#1330)<commit_after>package cmd

import (
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/fatih/color"
	"github.com/gobuffalo/buffalo/generators/assets/webpack"
	rg "github.com/gobuffalo/buffalo/generators/refresh"
	"github.com/gobuffalo/buffalo/meta"
	"github.com/gobuffalo/events"
	"github.com/markbates/refresh/refresh"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"golang.org/x/sync/errgroup"
)

func init() {
	events.NamedListen("buffalo:dev", func(e events.Event) {
		if strings.HasPrefix(e.Kind, "refresh:") {
			e.Kind = strings.Replace(e.Kind, "refresh:", "buffalo:dev:", 1)
			events.Emit(e)
		}
	})
}

var devOptions = struct {
	Debug bool
}{}

// devCmd represents the dev command
var devCmd = &cobra.Command{
	Use:   "dev",
	Short: "Runs your Buffalo app in 'development' mode",
	Long: `Runs your Buffalo app in 'development' mode.
This includes rebuilding your application when files change.
This behavior can be changed in your .buffalo.dev.yml file.`,
	RunE: func(c *cobra.Command, args []string) error {
		if runtime.GOOS == "windows" {
			color.NoColor = true
		}
		defer func() {
			msg := "There was a problem starting the dev server, Please review the troubleshooting docs: %s\n"
			cause := "Unknown"
			if r := recover(); r != nil {
				if err, ok := r.(error); ok {
					cause = err.Error()
				}
			}
			logrus.Errorf(msg, cause)
		}()
		os.Setenv("GO_ENV", "development")

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()

		wg, ctx := errgroup.WithContext(ctx)

		wg.Go(func() error {
			return startDevServer(ctx)
		})

		wg.Go(func() error {
			return startWebpack(ctx)
		})

		err := wg.Wait()
		if err != context.Canceled {
			return errors.WithStack(err)
		}
		return nil
	},
}

func startWebpack(ctx context.Context) error {
	app := meta.New(".")
	if !app.WithWebpack {
		// there's no webpack, so don't do anything
		return nil
	}

	if _, err := os.Stat(filepath.Join(app.Root, "node_modules")); err != nil {
		tool := "yarnpkg"
		if !app.WithYarn {
			tool = "npm"
		}
		if _, err := exec.LookPath(tool); err != nil {
			return errors.Errorf("no node_modules directory found, and couldn't find %s to install it with", tool)
		}
		cmd := exec.CommandContext(ctx, tool, "install")
		cmd.Stdin = os.Stdin
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		if err := cmd.Run(); err != nil {
			return errors.WithStack(err)
		}
	}

	cmd := exec.CommandContext(ctx, webpack.BinPath, "--watch")
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func startDevServer(ctx context.Context) error {
	cfgFile := "./.buffalo.dev.yml"
	if _, err := os.Stat(cfgFile); err != nil {
		err = rg.Run("./", map[string]interface{}{
			"name": "buffalo",
		})
		if err != nil {
			return err
		}
	}
	c := &refresh.Configuration{}
	if err := c.Load(cfgFile); err != nil {
		return err
	}
	c.Debug = devOptions.Debug

	app := meta.New(".")
	bt := app.BuildTags("development")
	if len(bt) > 0 {
		c.BuildFlags = append(c.BuildFlags, "-tags", bt.String())
	}
	r := refresh.NewWithContext(c, ctx)
	return r.Start()
}

func init() {
	devCmd.Flags().BoolVarP(&devOptions.Debug, "debug", "d", false, "use delve to debug the app")
	decorate("dev", devCmd)
	RootCmd.AddCommand(devCmd)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 build

import (
	"testing"
)

var simple_call *CallExpr = &CallExpr{
	X: &LiteralExpr{
		Token: "java_library",
	},
	List: []Expr{
		&BinaryExpr{
			X: &LiteralExpr{
				Token: "name",
			},
			Op: "=",
			Y: &StringExpr{
				Value: "x",
			},
		},
	},
}

var simple_rule *Rule = &Rule{simple_call}

var struct_call *CallExpr = &CallExpr{
	X: &DotExpr{
		X: &DotExpr{
			X: &LiteralExpr{
				Token: "foo",
			},
			Name: "bar",
		},
		Name: "baz",
	},
	List: []Expr{
		&BinaryExpr{
			X: &LiteralExpr{
				Token: "name",
			},
			Op: "=",
			Y: &StringExpr{
				Value: "x",
			},
		},
	},
}

var struct_rule *Rule = &Rule{struct_call}

func TestKind(t *testing.T) {
	if simple_rule.Kind() != "java_library" {
		t.Errorf(`simple_rule.Kind() = %v, want "java_library"`, simple_rule.Kind())
	}
	if struct_rule.Kind() != "foo.bar.baz" {
		t.Errorf(`struct_rule.Kind() = %v, want "foo.bar.baz"`, struct_rule.Kind())
	}
}

func TestSetKind(t *testing.T) {
	rule := &Rule{
		&CallExpr{
			X: &LiteralExpr{
				Token: "java_library",
			},
			List: []Expr{
				&BinaryExpr{
					X: &LiteralExpr{
						Token: "name",
					},
					Op: "=",
					Y: &StringExpr{
						Value: "x",
					},
				},
			},
		},
	}

	rule.SetKind("java_binary")
	compare(t, rule.Call.X, &LiteralExpr{Token: "java_binary"})

	rule.SetKind("foo.bar.baz")
	compare(t, rule.Call.X, &DotExpr{
		X: &DotExpr{
			X: &LiteralExpr{
				Token: "foo",
			},
			Name: "bar",
		},
		Name: "baz",
	})
}

func TestRules(t *testing.T) {
	f := &File{
		Stmt: []Expr{
			simple_call,
			struct_call,
		},
	}

	compare(t, f.Rules(""), []*Rule{simple_rule, struct_rule})
	compare(t, f.Rules("java_binary"), []*Rule(nil))
	compare(t, f.Rules("java_library"), []*Rule{simple_rule})
	compare(t, f.Rules("foo.bar.baz"), []*Rule{struct_rule})
}
<commit_msg>Fix variable naming to match go standards (#94)<commit_after>/*
Copyright 2016 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 build

import (
	"testing"
)

var simpleCall *CallExpr = &CallExpr{
	X: &LiteralExpr{
		Token: "java_library",
	},
	List: []Expr{
		&BinaryExpr{
			X: &LiteralExpr{
				Token: "name",
			},
			Op: "=",
			Y: &StringExpr{
				Value: "x",
			},
		},
	},
}

var simpleRule *Rule = &Rule{simpleCall}

var structCall *CallExpr = &CallExpr{
	X: &DotExpr{
		X: &DotExpr{
			X: &LiteralExpr{
				Token: "foo",
			},
			Name: "bar",
		},
		Name: "baz",
	},
	List: []Expr{
		&BinaryExpr{
			X: &LiteralExpr{
				Token: "name",
			},
			Op: "=",
			Y: &StringExpr{
				Value: "x",
			},
		},
	},
}

var structRule *Rule = &Rule{structCall}

func TestKind(t *testing.T) {
	if simpleRule.Kind() != "java_library" {
		t.Errorf(`simpleRule.Kind() = %v, want "java_library"`, simpleRule.Kind())
	}
	if structRule.Kind() != "foo.bar.baz" {
		t.Errorf(`structRule.Kind() = %v, want "foo.bar.baz"`, structRule.Kind())
	}
}

func TestSetKind(t *testing.T) {
	rule := &Rule{
		&CallExpr{
			X: &LiteralExpr{
				Token: "java_library",
			},
			List: []Expr{
				&BinaryExpr{
					X: &LiteralExpr{
						Token: "name",
					},
					Op: "=",
					Y: &StringExpr{
						Value: "x",
					},
				},
			},
		},
	}

	rule.SetKind("java_binary")
	compare(t, rule.Call.X, &LiteralExpr{Token: "java_binary"})

	rule.SetKind("foo.bar.baz")
	compare(t, rule.Call.X, &DotExpr{
		X: &DotExpr{
			X: &LiteralExpr{
				Token: "foo",
			},
			Name: "bar",
		},
		Name: "baz",
	})
}

func TestRules(t *testing.T) {
	f := &File{
		Stmt: []Expr{
			simpleCall,
			structCall,
		},
	}

	compare(t, f.Rules(""), []*Rule{simpleRule, structRule})
	compare(t, f.Rules("java_binary"), []*Rule(nil))
	compare(t, f.Rules("java_library"), []*Rule{simpleRule})
	compare(t, f.Rules("foo.bar.baz"), []*Rule{structRule})
}
<|endoftext|>