<commit_before>package deepcopier

import (
	"database/sql/driver"
	"fmt"
	"reflect"
	"strings"
)

const (
	// TagName is the deepcopier struct tag name.
	TagName = "deepcopier"
	// FieldOptionName is the from field option name for struct tag.
	FieldOptionName = "field"
	// ContextOptionName is the context option name for struct tag.
	ContextOptionName = "context"
	// SkipOptionName is the skip option name for struct tag.
	SkipOptionName = "skip"
	// ForceOptionName is the skip option name for struct tag.
	ForceOptionName = "force"
)

type (
	// TagOptions is a map that contains extracted struct tag options.
	TagOptions map[string]string

	// Options are copier options.
	Options struct {
		// Context given to WithContext() method.
		Context map[string]interface{}
		// Reversed reverses struct tag checkings.
		Reversed bool
	}
)

// DeepCopier deep copies a struct to/from a struct.
type DeepCopier struct {
	dst interface{}
	src interface{}
	ctx map[string]interface{}
}

// Copy sets source or destination.
func Copy(src interface{}) *DeepCopier {
	return &DeepCopier{src: src}
}

// WithContext injects the given context into the builder instance.
func (dc *DeepCopier) WithContext(ctx map[string]interface{}) *DeepCopier {
	dc.ctx = ctx
	return dc
}

// To sets the destination.
func (dc *DeepCopier) To(dst interface{}) error {
	dc.dst = dst
	return process(dc.dst, dc.src, Options{Context: dc.ctx})
}

// From sets the given the source as destination and destination as source.
func (dc *DeepCopier) From(src interface{}) error {
	dc.dst = dc.src
	dc.src = src
	return process(dc.dst, dc.src, Options{Context: dc.ctx, Reversed: true})
}

// process handles copy.
func process(dst interface{}, src interface{}, args ...Options) error {
	var (
		options        = Options{}
		srcValue       = reflect.Indirect(reflect.ValueOf(src))
		dstValue       = reflect.Indirect(reflect.ValueOf(dst))
		srcFieldNames  = getFieldNames(src)
		srcMethodNames = getMethodNames(src)
	)

	if len(args) > 0 {
		options = args[0]
	}

	if !dstValue.CanAddr() {
		return fmt.Errorf("destination %+v is unaddressable", dstValue.Interface())
	}

	for _, f := range srcFieldNames {
		var (
			srcFieldValue               = srcValue.FieldByName(f)
			srcFieldType, srcFieldFound = srcValue.Type().FieldByName(f)
			srcFieldName                = srcFieldType.Name
			dstFieldName                = srcFieldName
			tagOptions                  TagOptions
		)

		if !srcFieldFound {
			continue
		}

		if options.Reversed {
			tagOptions = getTagOptions(srcFieldType.Tag.Get(TagName))
			if v, ok := tagOptions[FieldOptionName]; ok && v != "" {
				dstFieldName = v
			}
		} else {
			if name, opts := getRelatedField(dst, srcFieldName); name != "" {
				dstFieldName, tagOptions = name, opts
			}
		}

		if _, ok := tagOptions[SkipOptionName]; ok {
			continue
		}

		var (
			dstFieldType, dstFieldFound = dstValue.Type().FieldByName(dstFieldName)
			dstFieldValue               = dstValue.FieldByName(dstFieldName)
		)

		if !dstFieldFound {
			continue
		}

		// Force option for empty interfaces and nullable types
		_, force := tagOptions[ForceOptionName]

		// Valuer -> ptr
		if isNullableType(srcFieldType.Type) && dstFieldValue.Kind() == reflect.Ptr && force {
			// We have same nullable type on both sides
			if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(srcFieldValue)
				continue
			}

			v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
			if v == nil {
				continue
			}

			valueType := reflect.TypeOf(v)

			ptr := reflect.New(valueType)
			ptr.Elem().Set(reflect.ValueOf(v))

			if valueType.AssignableTo(dstFieldType.Type.Elem()) {
				dstFieldValue.Set(ptr)
			}

			continue
		}

		// Valuer -> value
		if isNullableType(srcFieldType.Type) {
			// We have same nullable type on both sides
			if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(srcFieldValue)
				continue
			}

			if force {
				v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
				if v == nil {
					continue
				}

				rv := reflect.ValueOf(v)
				if rv.Type().AssignableTo(dstFieldType.Type) {
					dstFieldValue.Set(rv)
				}
			}

			continue
		}

		if dstFieldValue.Kind() == reflect.Interface {
			if force {
				dstFieldValue.Set(srcFieldValue)
			}
			continue
		}

		// Ptr -> Value
		if srcFieldType.Type.Kind() == reflect.Ptr && !srcFieldValue.IsNil() && dstFieldType.Type.Kind() != reflect.Ptr {
			indirect := reflect.Indirect(srcFieldValue)

			if indirect.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(indirect)
				continue
			}
		}

		// Other types
		if srcFieldType.Type.AssignableTo(dstFieldType.Type) {
			dstFieldValue.Set(srcFieldValue)
		}
	}

	for _, m := range srcMethodNames {
		name, opts := getRelatedField(dst, m)
		if name == "" {
			continue
		}

		if _, ok := opts[SkipOptionName]; ok {
			continue
		}

		method := reflect.ValueOf(src).MethodByName(m)
		if !method.IsValid() {
			return fmt.Errorf("method %s is invalid", m)
		}

		var (
			dstFieldType, _ = dstValue.Type().FieldByName(name)
			dstFieldValue   = dstValue.FieldByName(name)
			_, withContext  = opts[ContextOptionName]
			_, force        = opts[ForceOptionName]
		)

		args := []reflect.Value{}
		if withContext {
			args = []reflect.Value{reflect.ValueOf(options.Context)}
		}

		var (
			result          = method.Call(args)[0]
			resultInterface = result.Interface()
			resultValue     = reflect.ValueOf(resultInterface)
			resultType      = resultValue.Type()
		)

		// Value -> Ptr
		if dstFieldValue.Kind() == reflect.Ptr && force {
			ptr := reflect.New(resultType)
			ptr.Elem().Set(resultValue)

			if ptr.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(ptr)
			}

			continue
		}

		// Ptr -> value
		if resultValue.Kind() == reflect.Ptr && force {
			if resultValue.Elem().Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(resultValue.Elem())
			}

			continue
		}

		if resultType.AssignableTo(dstFieldType.Type) && result.IsValid() {
			dstFieldValue.Set(result)
		}
	}

	return nil
}

// getTagOptions parses deepcopier tag field and returns options.
func getTagOptions(value string) TagOptions {
	options := TagOptions{}

	for _, opt := range strings.Split(value, ";") {
		o := strings.Split(opt, ":")

		// deepcopier:"keyword; without; value;"
		if len(o) == 1 {
			options[o[0]] = ""
		}

		// deepcopier:"key:value; anotherkey:anothervalue"
		if len(o) == 2 {
			options[strings.TrimSpace(o[0])] = strings.TrimSpace(o[1])
		}
	}

	return options
}

// getRelatedField returns first matching field.
func getRelatedField(instance interface{}, name string) (string, TagOptions) {
	var (
		value      = reflect.Indirect(reflect.ValueOf(instance))
		fieldName  string
		tagOptions TagOptions
	)

	for i := 0; i < value.NumField(); i++ {
		var (
			vField     = value.Field(i)
			tField     = value.Type().Field(i)
			tagOptions = getTagOptions(tField.Tag.Get(TagName))
		)

		if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
			if n, o := getRelatedField(vField.Interface(), name); n != "" {
				return n, o
			}
		}

		if v, ok := tagOptions[FieldOptionName]; ok && v == name {
			return tField.Name, tagOptions
		}

		if tField.Name == name {
			return tField.Name, tagOptions
		}
	}

	return fieldName, tagOptions
}

// getMethodNames returns instance's method names.
func getMethodNames(instance interface{}) []string {
	var methods []string

	t := reflect.TypeOf(instance)
	for i := 0; i < t.NumMethod(); i++ {
		methods = append(methods, t.Method(i).Name)
	}

	return methods
}

// getFieldNames returns instance's field names.
func getFieldNames(instance interface{}) []string {
	var (
		fields []string
		v      = reflect.Indirect(reflect.ValueOf(instance))
		t      = v.Type()
	)

	if t.Kind() != reflect.Struct {
		return nil
	}

	for i := 0; i < v.NumField(); i++ {
		var (
			vField = v.Field(i)
			tField = v.Type().Field(i)
		)

		// Is exportable?
		if tField.PkgPath != "" {
			continue
		}

		if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
			fields = append(fields, getFieldNames(vField.Interface())...)
			continue
		}

		fields = append(fields, tField.Name)
	}

	return fields
}

// isNullableType returns true if the given type is a nullable one.
func isNullableType(t reflect.Type) bool {
	b := t.ConvertibleTo(reflect.TypeOf((*driver.Valuer)(nil)).Elem())
	return b
}
<commit_msg>Remove useless variable.<commit_after>package deepcopier

import (
	"database/sql/driver"
	"fmt"
	"reflect"
	"strings"
)

const (
	// TagName is the deepcopier struct tag name.
	TagName = "deepcopier"
	// FieldOptionName is the from field option name for struct tag.
	FieldOptionName = "field"
	// ContextOptionName is the context option name for struct tag.
	ContextOptionName = "context"
	// SkipOptionName is the skip option name for struct tag.
	SkipOptionName = "skip"
	// ForceOptionName is the skip option name for struct tag.
	ForceOptionName = "force"
)

type (
	// TagOptions is a map that contains extracted struct tag options.
	TagOptions map[string]string

	// Options are copier options.
	Options struct {
		// Context given to WithContext() method.
		Context map[string]interface{}
		// Reversed reverses struct tag checkings.
		Reversed bool
	}
)

// DeepCopier deep copies a struct to/from a struct.
type DeepCopier struct {
	dst interface{}
	src interface{}
	ctx map[string]interface{}
}

// Copy sets source or destination.
func Copy(src interface{}) *DeepCopier {
	return &DeepCopier{src: src}
}

// WithContext injects the given context into the builder instance.
func (dc *DeepCopier) WithContext(ctx map[string]interface{}) *DeepCopier {
	dc.ctx = ctx
	return dc
}

// To sets the destination.
func (dc *DeepCopier) To(dst interface{}) error {
	dc.dst = dst
	return process(dc.dst, dc.src, Options{Context: dc.ctx})
}

// From sets the given the source as destination and destination as source.
func (dc *DeepCopier) From(src interface{}) error {
	dc.dst = dc.src
	dc.src = src
	return process(dc.dst, dc.src, Options{Context: dc.ctx, Reversed: true})
}

// process handles copy.
func process(dst interface{}, src interface{}, args ...Options) error {
	var (
		options        = Options{}
		srcValue       = reflect.Indirect(reflect.ValueOf(src))
		dstValue       = reflect.Indirect(reflect.ValueOf(dst))
		srcFieldNames  = getFieldNames(src)
		srcMethodNames = getMethodNames(src)
	)

	if len(args) > 0 {
		options = args[0]
	}

	if !dstValue.CanAddr() {
		return fmt.Errorf("destination %+v is unaddressable", dstValue.Interface())
	}

	for _, f := range srcFieldNames {
		var (
			srcFieldValue               = srcValue.FieldByName(f)
			srcFieldType, srcFieldFound = srcValue.Type().FieldByName(f)
			srcFieldName                = srcFieldType.Name
			dstFieldName                = srcFieldName
			tagOptions                  TagOptions
		)

		if !srcFieldFound {
			continue
		}

		if options.Reversed {
			tagOptions = getTagOptions(srcFieldType.Tag.Get(TagName))
			if v, ok := tagOptions[FieldOptionName]; ok && v != "" {
				dstFieldName = v
			}
		} else {
			if name, opts := getRelatedField(dst, srcFieldName); name != "" {
				dstFieldName, tagOptions = name, opts
			}
		}

		if _, ok := tagOptions[SkipOptionName]; ok {
			continue
		}

		var (
			dstFieldType, dstFieldFound = dstValue.Type().FieldByName(dstFieldName)
			dstFieldValue               = dstValue.FieldByName(dstFieldName)
		)

		if !dstFieldFound {
			continue
		}

		// Force option for empty interfaces and nullable types
		_, force := tagOptions[ForceOptionName]

		// Valuer -> ptr
		if isNullableType(srcFieldType.Type) && dstFieldValue.Kind() == reflect.Ptr && force {
			// We have same nullable type on both sides
			if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(srcFieldValue)
				continue
			}

			v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
			if v == nil {
				continue
			}

			valueType := reflect.TypeOf(v)

			ptr := reflect.New(valueType)
			ptr.Elem().Set(reflect.ValueOf(v))

			if valueType.AssignableTo(dstFieldType.Type.Elem()) {
				dstFieldValue.Set(ptr)
			}

			continue
		}

		// Valuer -> value
		if isNullableType(srcFieldType.Type) {
			// We have same nullable type on both sides
			if srcFieldValue.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(srcFieldValue)
				continue
			}

			if force {
				v, _ := srcFieldValue.Interface().(driver.Valuer).Value()
				if v == nil {
					continue
				}

				rv := reflect.ValueOf(v)
				if rv.Type().AssignableTo(dstFieldType.Type) {
					dstFieldValue.Set(rv)
				}
			}

			continue
		}

		if dstFieldValue.Kind() == reflect.Interface {
			if force {
				dstFieldValue.Set(srcFieldValue)
			}
			continue
		}

		// Ptr -> Value
		if srcFieldType.Type.Kind() == reflect.Ptr && !srcFieldValue.IsNil() && dstFieldType.Type.Kind() != reflect.Ptr {
			indirect := reflect.Indirect(srcFieldValue)

			if indirect.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(indirect)
				continue
			}
		}

		// Other types
		if srcFieldType.Type.AssignableTo(dstFieldType.Type) {
			dstFieldValue.Set(srcFieldValue)
		}
	}

	for _, m := range srcMethodNames {
		name, opts := getRelatedField(dst, m)
		if name == "" {
			continue
		}

		if _, ok := opts[SkipOptionName]; ok {
			continue
		}

		method := reflect.ValueOf(src).MethodByName(m)
		if !method.IsValid() {
			return fmt.Errorf("method %s is invalid", m)
		}

		var (
			dstFieldType, _ = dstValue.Type().FieldByName(name)
			dstFieldValue   = dstValue.FieldByName(name)
			_, withContext  = opts[ContextOptionName]
			_, force        = opts[ForceOptionName]
		)

		args := []reflect.Value{}
		if withContext {
			args = []reflect.Value{reflect.ValueOf(options.Context)}
		}

		var (
			result          = method.Call(args)[0]
			resultInterface = result.Interface()
			resultValue     = reflect.ValueOf(resultInterface)
			resultType      = resultValue.Type()
		)

		// Value -> Ptr
		if dstFieldValue.Kind() == reflect.Ptr && force {
			ptr := reflect.New(resultType)
			ptr.Elem().Set(resultValue)

			if ptr.Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(ptr)
			}

			continue
		}

		// Ptr -> value
		if resultValue.Kind() == reflect.Ptr && force {
			if resultValue.Elem().Type().AssignableTo(dstFieldType.Type) {
				dstFieldValue.Set(resultValue.Elem())
			}

			continue
		}

		if resultType.AssignableTo(dstFieldType.Type) && result.IsValid() {
			dstFieldValue.Set(result)
		}
	}

	return nil
}

// getTagOptions parses deepcopier tag field and returns options.
func getTagOptions(value string) TagOptions {
	options := TagOptions{}

	for _, opt := range strings.Split(value, ";") {
		o := strings.Split(opt, ":")

		// deepcopier:"keyword; without; value;"
		if len(o) == 1 {
			options[o[0]] = ""
		}

		// deepcopier:"key:value; anotherkey:anothervalue"
		if len(o) == 2 {
			options[strings.TrimSpace(o[0])] = strings.TrimSpace(o[1])
		}
	}

	return options
}

// getRelatedField returns first matching field.
func getRelatedField(instance interface{}, name string) (string, TagOptions) {
	var (
		value      = reflect.Indirect(reflect.ValueOf(instance))
		fieldName  string
		tagOptions TagOptions
	)

	for i := 0; i < value.NumField(); i++ {
		var (
			vField     = value.Field(i)
			tField     = value.Type().Field(i)
			tagOptions = getTagOptions(tField.Tag.Get(TagName))
		)

		if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
			if n, o := getRelatedField(vField.Interface(), name); n != "" {
				return n, o
			}
		}

		if v, ok := tagOptions[FieldOptionName]; ok && v == name {
			return tField.Name, tagOptions
		}

		if tField.Name == name {
			return tField.Name, tagOptions
		}
	}

	return fieldName, tagOptions
}

// getMethodNames returns instance's method names.
func getMethodNames(instance interface{}) []string {
	var methods []string

	t := reflect.TypeOf(instance)
	for i := 0; i < t.NumMethod(); i++ {
		methods = append(methods, t.Method(i).Name)
	}

	return methods
}

// getFieldNames returns instance's field names.
func getFieldNames(instance interface{}) []string {
	var (
		fields []string
		v      = reflect.Indirect(reflect.ValueOf(instance))
		t      = v.Type()
	)

	if t.Kind() != reflect.Struct {
		return nil
	}

	for i := 0; i < v.NumField(); i++ {
		var (
			vField = v.Field(i)
			tField = v.Type().Field(i)
		)

		// Is exportable?
		if tField.PkgPath != "" {
			continue
		}

		if tField.Type.Kind() == reflect.Struct && tField.Anonymous {
			fields = append(fields, getFieldNames(vField.Interface())...)
			continue
		}

		fields = append(fields, tField.Name)
	}

	return fields
}

// isNullableType returns true if the given type is a nullable one.
func isNullableType(t reflect.Type) bool {
	return t.ConvertibleTo(reflect.TypeOf((*driver.Valuer)(nil)).Elem())
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"os"
	"sync"
	"time"

	"github.com/miekg/dns"
)

var inflight = new(single)

// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other
// utilities. It add ".key" for the public key and ".private" for the private key.
func ParseKeyFile(file string) (*dns.DNSKEY, dns.PrivateKey, error) {
	f, e := os.Open(file + ".key")
	if e != nil {
		return nil, nil, e
	}
	k, e := dns.ReadRR(f, file+".key")
	if e != nil {
		return nil, nil, e
	}
	f, e = os.Open(file + ".private")
	if e != nil {
		return nil, nil, e
	}
	p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, file+".private")
	if e != nil {
		return nil, nil, e
	}
	return k.(*dns.DNSKEY), p, nil
}

// sign signs a message m, it takes care of negative or nodata responses as
// well by synthesising NSEC3 records. It will also cache the signatures, using
// a hash of the signed data as a key.
// We also fake the origin TTL in the signature, because we don't want to
// throw away signatures when services decide to have longer TTL. So we just
// set the origTTL to 60.
// TODO(miek): revisit origTTL
func (s *server) sign(m *dns.Msg, bufsize uint16) {
	now := time.Now().UTC()
	incep := uint32(now.Add(-3 * time.Hour).Unix())     // 2+1 hours, be sure to catch daylight saving time and such
	expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week

	for _, r := range rrSets(m.Answer) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Answer = append(m.Answer, sig)
		}
	}
	for _, r := range rrSets(m.Ns) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Ns = append(m.Ns, sig)
		}
	}
	for _, r := range rrSets(m.Extra) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Extra = append(m.Extra, sig)
		}
	}
	if bufsize >= 512 || bufsize <= 4096 {
		m.Truncated = m.Len() > int(bufsize)
	}
	o := new(dns.OPT)
	o.Hdr.Name = "."
	o.Hdr.Rrtype = dns.TypeOPT
	o.SetDo()
	o.SetUDPSize(4096) // TODO(miek): echo client
	m.Extra = append(m.Extra, o)
	return
}

func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.RRSIG, error) {
	key := Key(r)
	if sig, _, exp := s.scache.Search(key); sig != nil { // There can only be one sig in this cache.
		// Is it still valid 24 hours from now?
		if now.Add(+24*time.Hour).Sub(exp) < -24*time.Hour {
			return sig[0].(*dns.RRSIG), nil
		}
		s.scache.Remove(key)
	}
	s.config.log.Infof("cache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype)
	StatsDnssecCacheMiss.Inc(1)
	sig, err, shared := inflight.Do(key, func() (*dns.RRSIG, error) {
		sig1 := s.NewRRSIG(incep, expir)
		sig1.Header().Ttl = r[0].Header().Ttl
		if r[0].Header().Rrtype == dns.TypeTXT {
			sig1.OrigTtl = 0
		}
		e := sig1.Sign(s.config.PrivKey, r)
		if e != nil {
			s.config.log.Errorf("failed to sign: %s", e.Error())
		}
		return sig1, e
	})
	if err != nil {
		return nil, err
	}
	if !shared {
		s.scache.InsertSig(key, sig)
	}
	return dns.Copy(sig).(*dns.RRSIG), nil
}

func (s *server) NewRRSIG(incep, expir uint32) *dns.RRSIG {
	sig := new(dns.RRSIG)
	sig.Hdr.Rrtype = dns.TypeRRSIG
	sig.Hdr.Ttl = s.config.Ttl
	sig.OrigTtl = s.config.Ttl
	sig.Algorithm = s.config.PubKey.Algorithm
	sig.KeyTag = s.config.KeyTag
	sig.Inception = incep
	sig.Expiration = expir
	sig.SignerName = s.config.PubKey.Hdr.Name
	return sig
}

type rrset struct {
	qname string
	qtype uint16
}

func rrSets(rrs []dns.RR) map[rrset][]dns.RR {
	m := make(map[rrset][]dns.RR)
	for _, r := range rrs {
		if s, ok := m[rrset{r.Header().Name, r.Header().Rrtype}]; ok {
			s = append(s, r)
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		} else {
			s := make([]dns.RR, 1, 3)
			s[0] = r
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		}
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

// Adapted from singleinflight.go from the original Go Code. Copyright 2013 The Go Authors.
type call struct {
	wg   sync.WaitGroup
	val  *dns.RRSIG
	err  error
	dups int
}

type single struct {
	sync.Mutex
	m map[string]*call
}

func (g *single) Do(key string, fn func() (*dns.RRSIG, error)) (*dns.RRSIG, error, bool) {
	g.Lock()
	if g.m == nil {
		g.m = make(map[string]*call)
	}
	if c, ok := g.m[key]; ok {
		c.dups++
		g.Unlock()
		c.wg.Wait()
		return c.val, c.err, true
	}
	c := new(call)
	c.wg.Add(1)
	g.m[key] = c
	g.Unlock()

	c.val, c.err = fn()
	c.wg.Done()

	g.Lock()
	delete(g.m, key)
	g.Unlock()

	return c.val, c.err, c.dups > 0
}
<commit_msg>call it scache<commit_after>// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"os"
	"sync"
	"time"

	"github.com/miekg/dns"
)

var inflight = new(single)

// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other
// utilities. It add ".key" for the public key and ".private" for the private key.
func ParseKeyFile(file string) (*dns.DNSKEY, dns.PrivateKey, error) {
	f, e := os.Open(file + ".key")
	if e != nil {
		return nil, nil, e
	}
	k, e := dns.ReadRR(f, file+".key")
	if e != nil {
		return nil, nil, e
	}
	f, e = os.Open(file + ".private")
	if e != nil {
		return nil, nil, e
	}
	p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, file+".private")
	if e != nil {
		return nil, nil, e
	}
	return k.(*dns.DNSKEY), p, nil
}

// sign signs a message m, it takes care of negative or nodata responses as
// well by synthesising NSEC3 records. It will also cache the signatures, using
// a hash of the signed data as a key.
// We also fake the origin TTL in the signature, because we don't want to
// throw away signatures when services decide to have longer TTL. So we just
// set the origTTL to 60.
// TODO(miek): revisit origTTL
func (s *server) sign(m *dns.Msg, bufsize uint16) {
	now := time.Now().UTC()
	incep := uint32(now.Add(-3 * time.Hour).Unix())     // 2+1 hours, be sure to catch daylight saving time and such
	expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week

	for _, r := range rrSets(m.Answer) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Answer = append(m.Answer, sig)
		}
	}
	for _, r := range rrSets(m.Ns) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Ns = append(m.Ns, sig)
		}
	}
	for _, r := range rrSets(m.Extra) {
		if r[0].Header().Rrtype == dns.TypeRRSIG {
			continue
		}
		if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) {
			continue
		}
		if sig, err := s.signSet(r, now, incep, expir); err == nil {
			m.Extra = append(m.Extra, sig)
		}
	}
	if bufsize >= 512 || bufsize <= 4096 {
		m.Truncated = m.Len() > int(bufsize)
	}
	o := new(dns.OPT)
	o.Hdr.Name = "."
	o.Hdr.Rrtype = dns.TypeOPT
	o.SetDo()
	o.SetUDPSize(4096) // TODO(miek): echo client
	m.Extra = append(m.Extra, o)
	return
}

func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.RRSIG, error) {
	key := Key(r)
	if sig, _, exp := s.scache.Search(key); sig != nil { // There can only be one sig in this cache.
		// Is it still valid 24 hours from now?
		if now.Add(+24*time.Hour).Sub(exp) < -24*time.Hour {
			return sig[0].(*dns.RRSIG), nil
		}
		s.scache.Remove(key)
	}
	s.config.log.Infof("scache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype)
	StatsDnssecCacheMiss.Inc(1)
	sig, err, shared := inflight.Do(key, func() (*dns.RRSIG, error) {
		sig1 := s.NewRRSIG(incep, expir)
		sig1.Header().Ttl = r[0].Header().Ttl
		if r[0].Header().Rrtype == dns.TypeTXT {
			sig1.OrigTtl = 0
		}
		e := sig1.Sign(s.config.PrivKey, r)
		if e != nil {
			s.config.log.Errorf("failed to sign: %s", e.Error())
		}
		return sig1, e
	})
	if err != nil {
		return nil, err
	}
	if !shared {
		s.scache.InsertSig(key, sig)
	}
	return dns.Copy(sig).(*dns.RRSIG), nil
}

func (s *server) NewRRSIG(incep, expir uint32) *dns.RRSIG {
	sig := new(dns.RRSIG)
	sig.Hdr.Rrtype = dns.TypeRRSIG
	sig.Hdr.Ttl = s.config.Ttl
	sig.OrigTtl = s.config.Ttl
	sig.Algorithm = s.config.PubKey.Algorithm
	sig.KeyTag = s.config.KeyTag
	sig.Inception = incep
	sig.Expiration = expir
	sig.SignerName = s.config.PubKey.Hdr.Name
	return sig
}

type rrset struct {
	qname string
	qtype uint16
}

func rrSets(rrs []dns.RR) map[rrset][]dns.RR {
	m := make(map[rrset][]dns.RR)
	for _, r := range rrs {
		if s, ok := m[rrset{r.Header().Name, r.Header().Rrtype}]; ok {
			s = append(s, r)
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		} else {
			s := make([]dns.RR, 1, 3)
			s[0] = r
			m[rrset{r.Header().Name, r.Header().Rrtype}] = s
		}
	}
	if len(m) > 0 {
		return m
	}
	return nil
}

// Adapted from singleinflight.go from the original Go Code. Copyright 2013 The Go Authors.
type call struct {
	wg   sync.WaitGroup
	val  *dns.RRSIG
	err  error
	dups int
}

type single struct {
	sync.Mutex
	m map[string]*call
}

func (g *single) Do(key string, fn func() (*dns.RRSIG, error)) (*dns.RRSIG, error, bool) {
	g.Lock()
	if g.m == nil {
		g.m = make(map[string]*call)
	}
	if c, ok := g.m[key]; ok {
		c.dups++
		g.Unlock()
		c.wg.Wait()
		return c.val, c.err, true
	}
	c := new(call)
	c.wg.Add(1)
	g.m[key] = c
	g.Unlock()

	c.val, c.err = fn()
	c.wg.Done()

	g.Lock()
	delete(g.m, key)
	g.Unlock()

	return c.val, c.err, c.dups > 0
}
<|endoftext|>


<commit_before>// Package urlutil contains utility functions
// related to URLs.
package urlutil

import (
	"net/url"
	"strings"
)

// isAbs returns true of the URL is absolute.
// This function considers protocol-relative
// URLs to be absolute
func isAbs(u *url.URL) bool {
	return u.IsAbs() || strings.HasPrefix(u.String(), "//")
}

// SameHost returns true iff both URLs point
// to the same host. It works for both absolute
// and relative URLs.
func SameHost(url1, url2 string) bool {
	if url1 == "" || url2 == "" {
		return true
	}
	u1, err := url.Parse(url1)
	if err != nil {
		return false
	}
	if !isAbs(u1) {
		return true
	}
	u2, err := url.Parse(url2)
	if err != nil {
		return false
	}
	if !isAbs(u2) {
		return true
	}
	return u1.Host == u2.Host
}

// Join returns the result of joining the base URL
// with the rel URL. If either base or rel are not
// valid URLs, an error will be returned.
func Join(base string, rel string) (string, error) {
	b, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	r, err := url.Parse(rel)
	if err != nil {
		return "", err
	}
	return b.ResolveReference(r).String(), nil
}

// MustJoin works like Join, but panics if there's
// an error.
func MustJoin(base string, rel string) string {
	u, err := Join(base, rel)
	if err != nil {
		panic(err)
	}
	return u
}

// IsURL returns true iff s looks like a URL.
func IsURL(s string) bool {
	return strings.Contains(s, "://") || strings.HasPrefix(s, "//")
}
<commit_msg>Add urlutil.AppendQuery<commit_after>// Package urlutil contains utility functions
// related to URLs.
package urlutil

import (
	"net/url"
	"strings"
)

// isAbs returns true of the URL is absolute.
// This function considers protocol-relative
// URLs to be absolute
func isAbs(u *url.URL) bool {
	return u.IsAbs() || strings.HasPrefix(u.String(), "//")
}

// SameHost returns true iff both URLs point
// to the same host. It works for both absolute
// and relative URLs.
func SameHost(url1, url2 string) bool {
	if url1 == "" || url2 == "" {
		return true
	}
	u1, err := url.Parse(url1)
	if err != nil {
		return false
	}
	if !isAbs(u1) {
		return true
	}
	u2, err := url.Parse(url2)
	if err != nil {
		return false
	}
	if !isAbs(u2) {
		return true
	}
	return u1.Host == u2.Host
}

// Join returns the result of joining the base URL
// with the rel URL. If either base or rel are not
// valid URLs, an error will be returned.
func Join(base string, rel string) (string, error) {
	b, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	r, err := url.Parse(rel)
	if err != nil {
		return "", err
	}
	return b.ResolveReference(r).String(), nil
}

// MustJoin works like Join, but panics if there's
// an error.
func MustJoin(base string, rel string) string {
	u, err := Join(base, rel)
	if err != nil {
		panic(err)
	}
	return u
}

// IsURL returns true iff s looks like a URL.
func IsURL(s string) bool {
	return strings.Contains(s, "://") || strings.HasPrefix(s, "//")
}

// AppendQuery appends the given query string as an url.Values to the given
// URL. It works correctly even if the URL already has a query string.
func AppendQuery(s string, query url.Values) string {
	sep := "?"
	if strings.IndexByte(s, '?') >= 0 {
		sep = "&"
	}
	return s + sep + query.Encode()
}
<|endoftext|>


<commit_before>package imap

import (
	"sync"
)

// A response that can be either accepted or rejected by a handler.
type RespHandle struct {
	Resp    interface{}
	Accepts chan bool
}

// Accept this response. This means that the handler will process it.
func (h *RespHandle) Accept() {
	h.Accepts <- true
}

// Reject this response. The handler cannot process it.
func (h *RespHandle) Reject() {
	h.Accepts <- false
}

// Accept this response if it has the specified name. If not, reject it.
func (h *RespHandle) AcceptNamedResp(name string) (fields []interface{}, accepted bool) {
	res, ok := h.Resp.(*Resp)
	if !ok || len(res.Fields) == 0 {
		h.Reject()
		return
	}

	n, ok := res.Fields[0].(string)
	if !ok || n != name {
		h.Reject()
		return
	}

	h.Accept()

	fields = res.Fields[1:]
	accepted = true
	return
}

// Delivers responses to handlers.
type RespHandler chan *RespHandle

// Handles responses from a handler.
type RespHandlerFrom interface {
	HandleFrom(hdlr RespHandler) error
}

// A RespHandlerFrom that forwards responses to multiple RespHandler.
type MultiRespHandler struct {
	handlers []RespHandler
	locker   sync.RWMutex
}

func NewMultiRespHandler() *MultiRespHandler {
	return &MultiRespHandler{}
}

func (mh *MultiRespHandler) HandleFrom(ch RespHandler) error {
	for rh := range ch {
		mh.locker.RLock()

		accepted := false
		for i := len(mh.handlers) - 1; i >= 0; i-- {
			hdlr := mh.handlers[i]

			rh := &RespHandle{
				Resp:    rh.Resp,
				Accepts: make(chan bool),
			}

			hdlr <- rh
			if accepted = <-rh.Accepts; accepted {
				break
			}
		}

		mh.locker.RUnlock()

		if accepted {
			rh.Accept()
		} else {
			rh.Reject()
		}
	}

	// Close and remove all handlers
	mh.locker.Lock()
	for _, hdlr := range mh.handlers {
		close(hdlr)
	}
	mh.handlers = nil
	mh.locker.Unlock()

	return nil
}

func (mh *MultiRespHandler) Add(hdlr RespHandler) {
	if hdlr == nil {
		return
	}

	mh.locker.Lock()
	mh.handlers = append(mh.handlers, hdlr)
	mh.locker.Unlock()
}

func (mh *MultiRespHandler) Del(hdlr RespHandler) {
	// Find the handler's index
	mh.locker.RLock()
	found := -1
	for i, h := range mh.handlers {
		if h == hdlr {
			found = i
			break
		}
	}
	mh.locker.RUnlock()

	if found < 0 {
		// Not found
		return
	}

	// Close handler and remove it
	// Make sure to close it before locking, because of deadlocks
	close(hdlr)
	mh.locker.Lock()
	mh.handlers = append(mh.handlers[:found], mh.handlers[found+1:]...)
	mh.locker.Unlock()
}
<commit_msg>Revert "Fixes deadlock, fixes #107"<commit_after>package imap

import (
	"sync"
)

// A response that can be either accepted or rejected by a handler.
type RespHandle struct {
	Resp    interface{}
	Accepts chan bool
}

// Accept this response. This means that the handler will process it.
func (h *RespHandle) Accept() {
	h.Accepts <- true
}

// Reject this response. The handler cannot process it.
func (h *RespHandle) Reject() {
	h.Accepts <- false
}

// Accept this response if it has the specified name. If not, reject it.
func (h *RespHandle) AcceptNamedResp(name string) (fields []interface{}, accepted bool) {
	res, ok := h.Resp.(*Resp)
	if !ok || len(res.Fields) == 0 {
		h.Reject()
		return
	}

	n, ok := res.Fields[0].(string)
	if !ok || n != name {
		h.Reject()
		return
	}

	h.Accept()

	fields = res.Fields[1:]
	accepted = true
	return
}

// Delivers responses to handlers.
type RespHandler chan *RespHandle

// Handles responses from a handler.
type RespHandlerFrom interface {
	HandleFrom(hdlr RespHandler) error
}

// A RespHandlerFrom that forwards responses to multiple RespHandler.
type MultiRespHandler struct {
	handlers []RespHandler
	locker   sync.Locker
}

func NewMultiRespHandler() *MultiRespHandler {
	return &MultiRespHandler{
		locker: &sync.Mutex{},
	}
}

func (mh *MultiRespHandler) HandleFrom(ch RespHandler) error {
	for rh := range ch {
		mh.locker.Lock()

		accepted := false
		for i := len(mh.handlers) - 1; i >= 0; i-- {
			hdlr := mh.handlers[i]

			rh := &RespHandle{
				Resp:    rh.Resp,
				Accepts: make(chan bool),
			}

			hdlr <- rh
			if accepted = <-rh.Accepts; accepted {
				break
			}
		}

		mh.locker.Unlock()

		if accepted {
			rh.Accept()
		} else {
			rh.Reject()
		}
	}

	mh.locker.Lock()
	for _, hdlr := range mh.handlers {
		close(hdlr)
	}
	mh.handlers = nil
	mh.locker.Unlock()

	return nil
}

func (mh *MultiRespHandler) Add(hdlr RespHandler) {
	if hdlr == nil {
		return
	}

	mh.locker.Lock()
	mh.handlers = append(mh.handlers, hdlr)
	mh.locker.Unlock()
}

func (mh *MultiRespHandler) Del(hdlr RespHandler) {
	mh.locker.Lock()
	for i, h := range mh.handlers {
		if h == hdlr {
			close(hdlr)
			mh.handlers = append(mh.handlers[:i], mh.handlers[i+1:]...)
		}
	}
	mh.locker.Unlock()
}
<|endoftext|>


<commit_before>package ingest

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/guregu/null"
	sq "github.com/lann/squirrel"
	"github.com/stellar/go-stellar-base/xdr"
	"github.com/stellar/horizon/db2/core"
	"github.com/stellar/horizon/db2/history"
	"github.com/stellar/horizon/db2/sqx"
)

// Account ingests the provided account data into a new row in the
// `history_accounts` table
func (ingest *Ingestion) Account(id int64, address string) error {

	q := history.Q{Repo: ingest.DB}
	var existing history.Account
	err := q.AccountByAddress(&existing, address)

	if err != nil && !q.NoRows(err) {
		return err
	}

	// already imported
	if !q.NoRows(err) {
		return nil
	}

	sql := ingest.accounts.Values(id, address)

	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Clear removes data from the ledger
func (ingest *Ingestion) Clear(start int64, end int64) error {

	if start <= 1 {
		del := sq.Delete("history_accounts").Where("id = 1")
		ingest.DB.Exec(del)
	}

	err := ingest.clearRange(start, end, "history_effects", "history_operation_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_operation_participants", "history_operation_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_operations", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_transaction_participants", "history_transaction_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_transactions", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_accounts", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_ledgers", "id")
	if err != nil {
		return err
	}

	return nil
}

// Close finishes the current transaction and finishes this ingestion.
func (ingest *Ingestion) Close() error {
	return ingest.commit()
}

// Effect adds a new row into the `history_effects` table.
func (ingest *Ingestion) Effect(aid int64, opid int64, order int, typ history.EffectType, details interface{}) error {
	djson, err := json.Marshal(details)
	if err != nil {
		return err
	}

	sql := ingest.effects.Values(aid, opid, order, typ, djson)

	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Flush writes the currently buffered rows to the db, and if successful
// starts a new transaction.
func (ingest *Ingestion) Flush() error {
	err := ingest.commit()
	if err != nil {
		return err
	}

	return ingest.Start()
}

// Ledger adds a ledger to the current ingestion
func (ingest *Ingestion) Ledger(
	id int64,
	header *core.LedgerHeader,
	txs int,
	ops int,
) error {

	sql := ingest.ledgers.Values(
		CurrentVersion,
		id,
		header.Sequence,
		header.LedgerHash,
		null.NewString(header.PrevHash, header.Sequence > 1),
		header.Data.TotalCoins,
		header.Data.FeePool,
		header.Data.BaseFee,
		header.Data.BaseReserve,
		header.Data.MaxTxSetSize,
		time.Unix(header.CloseTime, 0).UTC(),
		time.Now().UTC(),
		time.Now().UTC(),
		txs,
		ops,
	)

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Operation ingests the provided operation data into a new row in the
// `history_operations` table
func (ingest *Ingestion) Operation(
	id int64,
	txid int64,
	order int32,
	source xdr.AccountId,
	typ xdr.OperationType,
	details map[string]interface{},

) error {
	djson, err := json.Marshal(details)
	if err != nil {
		return err
	}

	sql := ingest.operations.Values(id, txid, order, source.Address(), typ, djson)
	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// OperationParticipants ingests the provided accounts `aids` as participants of
// operation with id `op`, creating a new row in the
// `history_operation_participants` table.
func (ingest *Ingestion) OperationParticipants(op int64, aids []int64) error {
	sql := ingest.operation_participants

	for _, aid := range aids {
		sql = sql.Values(op, aid)
	}

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Rollback aborts this ingestions transaction
func (ingest *Ingestion) Rollback() (err error) {
	err = ingest.DB.Rollback()
	return
}

// Start makes the ingestion reeady, initializing the insert builders and tx
func (ingest *Ingestion) Start() (err error) {
	err = ingest.DB.Begin()
	if err != nil {
		return
	}

	ingest.createInsertBuilders()

	return
}

// Transaction ingests the provided transaction data into a new row in the
// `history_transactions` table
func (ingest *Ingestion) Transaction(
	id int64,
	tx *core.Transaction,
	fee *core.TransactionFee,
) error {

	sql := ingest.transactions.Values(
		id,
		tx.TransactionHash,
		tx.LedgerSequence,
		tx.Index,
		tx.SourceAddress(),
		tx.Sequence(),
		tx.Fee(),
		len(tx.Envelope.Tx.Operations),
		tx.EnvelopeXDR(),
		tx.ResultXDR(),
		tx.ResultMetaXDR(),
		fee.ChangesXDR(),
		sqx.StringArray(tx.Base64Signatures()),
		ingest.formatTimeBounds(tx.Envelope.Tx.TimeBounds),
		tx.MemoType(),
		tx.Memo(),
		time.Now().UTC(),
		time.Now().UTC(),
	)

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// TransactionParticipants ingests the provided account ids as participants of
// transaction with id `tx`, creating a new row in the
// `history_transaction_participants` table.
func (ingest *Ingestion) TransactionParticipants(tx int64, aids []int64) error {
	sql := ingest.transaction_participants

	for _, aid := range aids {
		sql = sql.Values(tx, aid)
	}

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

func (ingest *Ingestion) clearRange(start int64, end int64, table string, idCol string) error {
	del := sq.Delete(table).Where(
		fmt.Sprintf("%s >= ? AND %s < ?", idCol, idCol),
		start,
		end,
	)
	_, err := ingest.DB.Exec(del)
	return err
}

func (ingest *Ingestion) createInsertBuilders() {
	ingest.ledgers = sq.Insert("history_ledgers").Columns(
		"importer_version",
		"id",
		"sequence",
		"ledger_hash",
		"previous_ledger_hash",
		"total_coins",
		"fee_pool",
		"base_fee",
		"base_reserve",
		"max_tx_set_size",
		"closed_at",
		"created_at",
		"updated_at",
		"transaction_count",
		"operation_count",
	)

	ingest.accounts = sq.Insert("history_accounts").Columns(
		"id",
		"address",
	)

	ingest.transactions = sq.Insert("history_transactions").Columns(
		"id",
		"transaction_hash",
		"ledger_sequence",
		"application_order",
		"account",
		"account_sequence",
		"fee_paid",
		"operation_count",
		"tx_envelope",
		"tx_result",
		"tx_meta",
		"tx_fee_meta",
		"signatures",
		"time_bounds",
		"memo_type",
		"memo",
		"created_at",
		"updated_at",
	)

	ingest.transaction_participants = sq.Insert("history_transaction_participants").Columns(
		"history_transaction_id",
		"history_account_id",
	)

	ingest.operations = sq.Insert("history_operations").Columns(
		"id",
		"transaction_id",
		"application_order",
		"source_account",
		"type",
		"details",
	)

	ingest.operation_participants = sq.Insert("history_operation_participants").Columns(
		"history_operation_id",
		"history_account_id",
	)

	ingest.effects = sq.Insert("history_effects").Columns(
		"history_account_id",
		"history_operation_id",
		"\"order\"",
		"type",
		"details",
	)
}

func (ingest *Ingestion) commit() error {
	err := ingest.DB.Commit()
	if err != nil {
		return err
	}

	return nil
}

func (ingest *Ingestion) formatTimeBounds(bounds *xdr.TimeBounds) interface{} {
	if bounds == nil {
		return nil
	}

	return sq.Expr("?::int8range", fmt.Sprintf("[%d,%d]", bounds.MinTime, bounds.MaxTime))
}
<commit_msg>Fix ingest when TimeBounds.maxTime = 0<commit_after>package ingest

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/guregu/null"
	sq "github.com/lann/squirrel"
	"github.com/stellar/go-stellar-base/xdr"
	"github.com/stellar/horizon/db2/core"
	"github.com/stellar/horizon/db2/history"
	"github.com/stellar/horizon/db2/sqx"
)

// Account ingests the provided account data into a new row in the
// `history_accounts` table
func (ingest *Ingestion) Account(id int64, address string) error {

	q := history.Q{Repo: ingest.DB}
	var existing history.Account
	err := q.AccountByAddress(&existing, address)

	if err != nil && !q.NoRows(err) {
		return err
	}

	// already imported
	if !q.NoRows(err) {
		return nil
	}

	sql := ingest.accounts.Values(id, address)

	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Clear removes data from the ledger
func (ingest *Ingestion) Clear(start int64, end int64) error {

	if start <= 1 {
		del := sq.Delete("history_accounts").Where("id = 1")
		ingest.DB.Exec(del)
	}

	err := ingest.clearRange(start, end, "history_effects", "history_operation_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_operation_participants", "history_operation_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_operations", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_transaction_participants", "history_transaction_id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_transactions", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_accounts", "id")
	if err != nil {
		return err
	}
	err = ingest.clearRange(start, end, "history_ledgers", "id")
	if err != nil {
		return err
	}

	return nil
}

// Close finishes the current transaction and finishes this ingestion.
func (ingest *Ingestion) Close() error {
	return ingest.commit()
}

// Effect adds a new row into the `history_effects` table.
func (ingest *Ingestion) Effect(aid int64, opid int64, order int, typ history.EffectType, details interface{}) error {
	djson, err := json.Marshal(details)
	if err != nil {
		return err
	}

	sql := ingest.effects.Values(aid, opid, order, typ, djson)

	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Flush writes the currently buffered rows to the db, and if successful
// starts a new transaction.
func (ingest *Ingestion) Flush() error {
	err := ingest.commit()
	if err != nil {
		return err
	}

	return ingest.Start()
}

// Ledger adds a ledger to the current ingestion
func (ingest *Ingestion) Ledger(
	id int64,
	header *core.LedgerHeader,
	txs int,
	ops int,
) error {

	sql := ingest.ledgers.Values(
		CurrentVersion,
		id,
		header.Sequence,
		header.LedgerHash,
		null.NewString(header.PrevHash, header.Sequence > 1),
		header.Data.TotalCoins,
		header.Data.FeePool,
		header.Data.BaseFee,
		header.Data.BaseReserve,
		header.Data.MaxTxSetSize,
		time.Unix(header.CloseTime, 0).UTC(),
		time.Now().UTC(),
		time.Now().UTC(),
		txs,
		ops,
	)

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Operation ingests the provided operation data into a new row in the
// `history_operations` table
func (ingest *Ingestion) Operation(
	id int64,
	txid int64,
	order int32,
	source xdr.AccountId,
	typ xdr.OperationType,
	details map[string]interface{},

) error {
	djson, err := json.Marshal(details)
	if err != nil {
		return err
	}

	sql := ingest.operations.Values(id, txid, order, source.Address(), typ, djson)
	_, err = ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// OperationParticipants ingests the provided accounts `aids` as participants of
// operation with id `op`, creating a new row in the
// `history_operation_participants` table.
func (ingest *Ingestion) OperationParticipants(op int64, aids []int64) error {
	sql := ingest.operation_participants

	for _, aid := range aids {
		sql = sql.Values(op, aid)
	}

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// Rollback aborts this ingestions transaction
func (ingest *Ingestion) Rollback() (err error) {
	err = ingest.DB.Rollback()
	return
}

// Start makes the ingestion reeady, initializing the insert builders and tx
func (ingest *Ingestion) Start() (err error) {
	err = ingest.DB.Begin()
	if err != nil {
		return
	}

	ingest.createInsertBuilders()

	return
}

// Transaction ingests the provided transaction data into a new row in the
// `history_transactions` table
func (ingest *Ingestion) Transaction(
	id int64,
	tx *core.Transaction,
	fee *core.TransactionFee,
) error {

	sql := ingest.transactions.Values(
		id,
		tx.TransactionHash,
		tx.LedgerSequence,
		tx.Index,
		tx.SourceAddress(),
		tx.Sequence(),
		tx.Fee(),
		len(tx.Envelope.Tx.Operations),
		tx.EnvelopeXDR(),
		tx.ResultXDR(),
		tx.ResultMetaXDR(),
		fee.ChangesXDR(),
		sqx.StringArray(tx.Base64Signatures()),
		ingest.formatTimeBounds(tx.Envelope.Tx.TimeBounds),
		tx.MemoType(),
		tx.Memo(),
		time.Now().UTC(),
		time.Now().UTC(),
	)

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

// TransactionParticipants ingests the provided account ids as participants of
// transaction with id `tx`, creating a new row in the
// `history_transaction_participants` table.
func (ingest *Ingestion) TransactionParticipants(tx int64, aids []int64) error {
	sql := ingest.transaction_participants

	for _, aid := range aids {
		sql = sql.Values(tx, aid)
	}

	_, err := ingest.DB.Exec(sql)
	if err != nil {
		return err
	}

	return nil
}

func (ingest *Ingestion) clearRange(start int64, end int64, table string, idCol string) error {
	del := sq.Delete(table).Where(
		fmt.Sprintf("%s >= ? AND %s < ?", idCol, idCol),
		start,
		end,
	)
	_, err := ingest.DB.Exec(del)
	return err
}

func (ingest *Ingestion) createInsertBuilders() {
	ingest.ledgers = sq.Insert("history_ledgers").Columns(
		"importer_version",
		"id",
		"sequence",
		"ledger_hash",
		"previous_ledger_hash",
		"total_coins",
		"fee_pool",
		"base_fee",
		"base_reserve",
		"max_tx_set_size",
		"closed_at",
		"created_at",
		"updated_at",
		"transaction_count",
		"operation_count",
	)

	ingest.accounts = sq.Insert("history_accounts").Columns(
		"id",
		"address",
	)

	ingest.transactions = sq.Insert("history_transactions").Columns(
		"id",
		"transaction_hash",
		"ledger_sequence",
		"application_order",
		"account",
		"account_sequence",
		"fee_paid",
		"operation_count",
		"tx_envelope",
		"tx_result",
		"tx_meta",
		"tx_fee_meta",
		"signatures",
		"time_bounds",
		"memo_type",
		"memo",
		"created_at",
		"updated_at",
	)

	ingest.transaction_participants = sq.Insert("history_transaction_participants").Columns(
		"history_transaction_id",
		"history_account_id",
	)

	ingest.operations = sq.Insert("history_operations").Columns(
		"id",
		"transaction_id",
		"application_order",
		"source_account",
		"type",
		"details",
	)

	ingest.operation_participants = sq.Insert("history_operation_participants").Columns(
		"history_operation_id",
		"history_account_id",
	)

	ingest.effects = sq.Insert("history_effects").Columns(
		"history_account_id",
		"history_operation_id",
		"\"order\"",
		"type",
		"details",
	)
}

func (ingest *Ingestion) commit() error {
	err := ingest.DB.Commit()
	if err != nil {
		return err
	}

	return nil
}

func (ingest *Ingestion) formatTimeBounds(bounds *xdr.TimeBounds) interface{} {
	if bounds == nil {
		return nil
	}

	if bounds.MaxTime == 0 {
		return sq.Expr("?::int8range", fmt.Sprintf("[%d,]", bounds.MinTime))
	}

	return sq.Expr("?::int8range", fmt.Sprintf("[%d,%d]", bounds.MinTime, bounds.MaxTime))
}
<|endoftext|>


<commit_before>// +build !linux

package netlink

import "net"

func LinkSetUp(link Link) error {
	return ErrNotImplemented
}

func LinkSetDown(link Link) error {
	return ErrNotImplemented
}

func LinkSetMTU(link Link, mtu int) error {
	return ErrNotImplemented
}

func LinkSetMaster(link Link, master *Bridge) error {
	return ErrNotImplemented
}

func LinkSetNsPid(link Link, nspid int) error {
	return ErrNotImplemented
}

func LinkSetNsFd(link Link, fd int) error {
	return ErrNotImplemented
}

func LinkSetName(link Link, name string) error {
	return ErrNotImplemented
}

func LinkSetAlias(link Link, name string) error {
	return ErrNotImplemented
}

func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
	return ErrNotImplemented
}

func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
	return ErrNotImplemented
}

func LinkSetVfVlan(link Link, vf, vlan int) error {
	return ErrNotImplemented
}

func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
	return ErrNotImplemented
}

func LinkSetVfTxRate(link Link, vf, rate int) error {
	return ErrNotImplemented
}

func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
	return ErrNotImplemented
}

func LinkSetNoMaster(link Link) error {
	return ErrNotImplemented
}

func LinkSetMasterByIndex(link Link, masterIndex int) error {
	return ErrNotImplemented
}

func LinkSetXdpFd(link Link, fd int) error {
	return ErrNotImplemented
}

func LinkSetARPOff(link Link) error {
	return ErrNotImplemented
}

func LinkSetARPOn(link Link) error {
	return ErrNotImplemented
}

func LinkByName(name string) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkByAlias(alias string) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkByIndex(index int) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkSetHairpin(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetGuard(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetFastLeave(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetLearning(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetRootBlock(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetFlood(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetTxQLen(link Link, qlen int) error {
	return ErrNotImplemented
}

func LinkAdd(link Link) error {
	return ErrNotImplemented
}

func LinkDel(link Link) error {
	return ErrNotImplemented
}

func SetHairpin(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetGuard(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetFastLeave(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetLearning(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetRootBlock(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetFlood(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkList() ([]Link, error) {
	return nil, ErrNotImplemented
}

func AddrAdd(link Link, addr *Addr) error {
	return ErrNotImplemented
}

func AddrDel(link Link, addr *Addr) error {
	return ErrNotImplemented
}

func AddrList(link Link, family int) ([]Addr, error) {
	return nil, ErrNotImplemented
}

func RouteAdd(route *Route) error {
	return ErrNotImplemented
}

func RouteDel(route *Route) error {
	return ErrNotImplemented
}

func RouteList(link Link, family int) ([]Route, error) {
	return nil, ErrNotImplemented
}

func XfrmPolicyAdd(policy *XfrmPolicy) error {
	return ErrNotImplemented
}

func XfrmPolicyDel(policy *XfrmPolicy) error {
	return ErrNotImplemented
}

func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
	return nil, ErrNotImplemented
}

func XfrmStateAdd(policy *XfrmState) error {
	return ErrNotImplemented
}

func XfrmStateDel(policy *XfrmState) error {
	return ErrNotImplemented
}

func XfrmStateList(family int) ([]XfrmState, error) {
	return nil, ErrNotImplemented
}

func NeighAdd(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighSet(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighAppend(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighDel(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighList(linkIndex, family int) ([]Neigh, error) {
	return nil, ErrNotImplemented
}

func NeighDeserialize(m []byte) (*Neigh, error) {
	return nil, ErrNotImplemented
}

func SocketGet(local, remote net.Addr) (*Socket, error) {
	return nil, ErrNotImplemented
}
<commit_msg>Update netlink_unspecified.go<commit_after>// +build !linux

package netlink

import "net"

func LinkSetUp(link Link) error {
	return ErrNotImplemented
}

func LinkSetDown(link Link) error {
	return ErrNotImplemented
}

func LinkSetMTU(link Link, mtu int) error {
	return ErrNotImplemented
}

func LinkSetMaster(link Link, master *Bridge) error {
	return ErrNotImplemented
}

func LinkSetNsPid(link Link, nspid int) error {
	return ErrNotImplemented
}

func LinkSetNsFd(link Link, fd int) error {
	return ErrNotImplemented
}

func LinkSetName(link Link, name string) error {
	return ErrNotImplemented
}

func LinkSetAlias(link Link, name string) error {
	return ErrNotImplemented
}

func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
	return ErrNotImplemented
}

func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
	return ErrNotImplemented
}

func LinkSetVfVlan(link Link, vf, vlan int) error {
	return ErrNotImplemented
}

func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
	return ErrNotImplemented
}

func LinkSetVfTxRate(link Link, vf, rate int) error {
	return ErrNotImplemented
}

func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
	return ErrNotImplemented
}

func LinkSetNoMaster(link Link) error {
	return ErrNotImplemented
}

func LinkSetMasterByIndex(link Link, masterIndex int) error {
	return ErrNotImplemented
}

func LinkSetXdpFd(link Link, fd int) error {
	return ErrNotImplemented
}

func LinkSetARPOff(link Link) error {
	return ErrNotImplemented
}

func LinkSetARPOn(link Link) error {
	return ErrNotImplemented
}

func LinkByName(name string) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkByAlias(alias string) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkByIndex(index int) (Link, error) {
	return nil, ErrNotImplemented
}

func LinkSetHairpin(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetGuard(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetFastLeave(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetLearning(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetRootBlock(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetFlood(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkSetTxQLen(link Link, qlen int) error {
	return ErrNotImplemented
}

func LinkAdd(link Link) error {
	return ErrNotImplemented
}

func LinkDel(link Link) error {
	return ErrNotImplemented
}

func SetHairpin(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetGuard(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetFastLeave(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetLearning(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetRootBlock(link Link, mode bool) error {
	return ErrNotImplemented
}

func SetFlood(link Link, mode bool) error {
	return ErrNotImplemented
}

func LinkList() ([]Link, error) {
	return nil, ErrNotImplemented
}

func AddrAdd(link Link, addr *Addr) error {
	return ErrNotImplemented
}

func AddrReplace(link Link, addr *Addr) error {
	return ErrNotImplemented
}

func AddrDel(link Link, addr *Addr) error {
	return ErrNotImplemented
}

func AddrList(link Link, family int) ([]Addr, error) {
	return nil, ErrNotImplemented
}

func RouteAdd(route *Route) error {
	return ErrNotImplemented
}

func RouteDel(route *Route) error {
	return ErrNotImplemented
}

func RouteList(link Link, family int) ([]Route, error) {
	return nil, ErrNotImplemented
}

func XfrmPolicyAdd(policy *XfrmPolicy) error {
	return ErrNotImplemented
}

func XfrmPolicyDel(policy *XfrmPolicy) error {
	return ErrNotImplemented
}

func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
	return nil, ErrNotImplemented
}

func XfrmStateAdd(policy *XfrmState) error {
	return ErrNotImplemented
}

func XfrmStateDel(policy *XfrmState) error {
	return ErrNotImplemented
}

func XfrmStateList(family int) ([]XfrmState, error) {
	return nil, ErrNotImplemented
}

func NeighAdd(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighSet(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighAppend(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighDel(neigh *Neigh) error {
	return ErrNotImplemented
}

func NeighList(linkIndex, family int) ([]Neigh, error) {
	return nil, ErrNotImplemented
}

func NeighDeserialize(m []byte) (*Neigh, error) {
	return nil, ErrNotImplemented
}

func SocketGet(local, remote net.Addr) (*Socket, error) {
	return nil, ErrNotImplemented
}
<|endoftext|>


<commit_before>package httpauth

import (
    "bytes"
    "fmt"
    "os"
    "testing"
    "gopkg.in/mgo.v2"
    //"gopkg.in/mgo.v2/bson"
)

var (
    backend         MongodbAuthBackend
    url = "mongodb://127.0.0.1/"
    db = "test"
)

func TestMongodbInit(t *testing.T) {
    con, err := mgo.Dial(url)
    if err != nil {
        t.Errorf("Couldn't set up test mongodb session: %v\nHave you started the mongo db?\n```\n$ mongod --dbpath mongodbtest/\n```", err)
        fmt.Printf("Couldn't set up test mongodb session: %v\nHave you started the mongo db?\n```\n$ mongod --dbpath mongodbtest/\n```\n", err)
        os.Exit(1)
    }
    err = con.Ping()
    if err != nil {
        t.Errorf("Couldn't ping test mongodb database: %v", err)
        fmt.Printf("Couldn't ping test mongodb database: %v\n", err)
        // t.Errorf("Couldn't ping test database: %v\n", err)
        os.Exit(1)
    }
    db := con.DB(db)
    err = db.DropDatabase()
    if err != nil {
        t.Errorf("Couldn't drop test mongodb database: %v", err)
        fmt.Printf("Couldn't drop test mongodb database: %v\n", err)
        // t.Errorf("Couldn't ping test database: %v\n", err)
        os.Exit(1)
    }
}

func TestNewMongodbAuthBackend(t *testing.T) {
    backend, err := NewMongodbBackend(url, db)
    if err != nil {
        t.Fatalf("NewMongodbBackend error: %v", err)
    }
    if backend.mongoUrl != url {
        t.Fatal("Url name.")
    }
    if backend.database != db {
        t.Fatal("DB not saved.")
    }
}

func TestSaveUser_mongodb(t *testing.T) {
    user2 := UserData{"username2", "email2", []byte("passwordhash2"), "role2"}
    if err := backend.SaveUser(user2); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }

    user := UserData{"username", "email", []byte("passwordhash"), "role"}
    if err := backend.SaveUser(user); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }
}

func TestNewMongodbAuthBackend_existing(t *testing.T) {
    b2, err := NewMongodbBackend(driverName, driverInfo)
    if err != nil {
        t.Fatalf("NewMongodbBackend (existing) error: %v", err)
    }

    user, ok := b2.User("username")
    if !ok {
        t.Fatal("Secondary backend failed")
    }
    if user.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if user.Email != "email" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(user.Hash, []byte("passwordhash")) {
        t.Fatal("User password not correct.")
    }
}

func TestUser_existing_mongodb(t *testing.T) {
    if user, ok := backend.User("username"); ok {
        if user.Username != "username" {
            t.Fatal("Username not correct.")
        }
        if user.Email != "email" {
            t.Fatal("User email not correct.")
        }
        if !bytes.Equal(user.Hash, []byte("passwordhash")) {
            t.Fatal("User password not correct.")
        }
    } else {
        t.Fatal("User not found")
    }
    if user, ok := backend.User("username2"); ok {
        if user.Username != "username2" {
            t.Fatal("Username not correct.")
        }
        if user.Email != "email2" {
            t.Fatal("User email not correct.")
        }
        if !bytes.Equal(user.Hash, []byte("passwordhash2")) {
            t.Fatal("User password not correct.")
        }
    } else {
        t.Fatal("User not found")
    }
}

func TestUser_notexisting_mongodb(t *testing.T) {
    if _, ok := backend.User("notexist"); ok {
        t.Fatal("Not existing user found.")
    }
}

func TestUsers_mongodb(t *testing.T) {
    var (
        u1 UserData
        u2 UserData
    )
    users := backend.Users()
    if len(users) != 2 {
        t.Fatal("Wrong amount of users found.")
    }
    if users[0].Username == "username" {
        u1 = users[0]
        u2 = users[1]
    } else if users[1].Username == "username" {
        u1 = users[1]
        u2 = users[0]
    } else {
        t.Fatal("One of the users not found.")
    }

    if u1.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if u1.Email != "email" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(u1.Hash, []byte("passwordhash")) {
        t.Fatal("User password not correct.")
    }
    if u2.Username != "username2" {
        t.Fatal("Username not correct.")
    }
    if u2.Email != "email2" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(u2.Hash, []byte("passwordhash2")) {
        t.Fatal("User password not correct.")
    }
}

func TestUpdateUser_mongodb(t *testing.T) {
    user2 := UserData{"username", "newemail", []byte("newpassword"), "newrole"}
    if err := backend.SaveUser(user2); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }
    u2, ok := backend.User("username")
    if !ok {
        t.Fatal("Updated user not found")
    }
    if u2.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if u2.Email != "newemail" {
        t.Fatal("User email not correct.")
    }
    if u2.Role != "newrole" {
        t.Fatalf("User role not correct: found %v, expected %v", u2.Role, "newrole");
    }
    if !bytes.Equal(u2.Hash, []byte("newpassword")) {
        t.Fatal("User password not correct.")
    }
}

func TestMongodbDeleteUser_mongodb(t *testing.T) {
    if err := backend.DeleteUser("username"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }
    if err := backend.DeleteUser("username"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }

    if err := backend.DeleteUser("username2"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }
}

<commit_msg>Addresses issue #6. Fixed one test, just forgot to update code<commit_after>package httpauth

import (
    "bytes"
    "fmt"
    "os"
    "testing"
    "gopkg.in/mgo.v2"
    //"gopkg.in/mgo.v2/bson"
)

var (
    backend         MongodbAuthBackend
    url = "mongodb://127.0.0.1/"
    db = "test"
)

func TestMongodbInit(t *testing.T) {
    con, err := mgo.Dial(url)
    if err != nil {
        t.Errorf("Couldn't set up test mongodb session: %v\nHave you started the mongo db?\n```\n$ mongod --dbpath mongodbtest/\n```", err)
        fmt.Printf("Couldn't set up test mongodb session: %v\nHave you started the mongo db?\n```\n$ mongod --dbpath mongodbtest/\n```\n", err)
        os.Exit(1)
    }
    err = con.Ping()
    if err != nil {
        t.Errorf("Couldn't ping test mongodb database: %v", err)
        fmt.Printf("Couldn't ping test mongodb database: %v\n", err)
        // t.Errorf("Couldn't ping test database: %v\n", err)
        os.Exit(1)
    }
    db := con.DB(db)
    err = db.DropDatabase()
    if err != nil {
        t.Errorf("Couldn't drop test mongodb database: %v", err)
        fmt.Printf("Couldn't drop test mongodb database: %v\n", err)
        // t.Errorf("Couldn't ping test database: %v\n", err)
        os.Exit(1)
    }
}

func TestNewMongodbAuthBackend(t *testing.T) {
    backend, err := NewMongodbBackend(url, db)
    if err != nil {
        t.Fatalf("NewMongodbBackend error: %v", err)
    }
    if backend.mongoUrl != url {
        t.Fatal("Url name.")
    }
    if backend.database != db {
        t.Fatal("DB not saved.")
    }
}

func TestSaveUser_mongodb(t *testing.T) {
    user2 := UserData{"username2", "email2", []byte("passwordhash2"), "role2"}
    if err := backend.SaveUser(user2); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }

    user := UserData{"username", "email", []byte("passwordhash"), "role"}
    if err := backend.SaveUser(user); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }
}

func TestNewMongodbAuthBackend_existing(t *testing.T) {
    b2, err := NewMongodbBackend(url, db)
    if err != nil {
        t.Fatalf("NewMongodbBackend (existing) error: %v", err)
    }

    user, ok := b2.User("username")
    if !ok {
        t.Fatal("Secondary backend failed")
    }
    if user.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if user.Email != "email" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(user.Hash, []byte("passwordhash")) {
        t.Fatal("User password not correct.")
    }
}

func TestUser_existing_mongodb(t *testing.T) {
    if user, ok := backend.User("username"); ok {
        if user.Username != "username" {
            t.Fatal("Username not correct.")
        }
        if user.Email != "email" {
            t.Fatal("User email not correct.")
        }
        if !bytes.Equal(user.Hash, []byte("passwordhash")) {
            t.Fatal("User password not correct.")
        }
    } else {
        t.Fatal("User not found")
    }
    if user, ok := backend.User("username2"); ok {
        if user.Username != "username2" {
            t.Fatal("Username not correct.")
        }
        if user.Email != "email2" {
            t.Fatal("User email not correct.")
        }
        if !bytes.Equal(user.Hash, []byte("passwordhash2")) {
            t.Fatal("User password not correct.")
        }
    } else {
        t.Fatal("User not found")
    }
}

func TestUser_notexisting_mongodb(t *testing.T) {
    if _, ok := backend.User("notexist"); ok {
        t.Fatal("Not existing user found.")
    }
}

func TestUsers_mongodb(t *testing.T) {
    var (
        u1 UserData
        u2 UserData
    )
    users := backend.Users()
    if len(users) != 2 {
        t.Fatal("Wrong amount of users found.")
    }
    if users[0].Username == "username" {
        u1 = users[0]
        u2 = users[1]
    } else if users[1].Username == "username" {
        u1 = users[1]
        u2 = users[0]
    } else {
        t.Fatal("One of the users not found.")
    }

    if u1.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if u1.Email != "email" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(u1.Hash, []byte("passwordhash")) {
        t.Fatal("User password not correct.")
    }
    if u2.Username != "username2" {
        t.Fatal("Username not correct.")
    }
    if u2.Email != "email2" {
        t.Fatal("User email not correct.")
    }
    if !bytes.Equal(u2.Hash, []byte("passwordhash2")) {
        t.Fatal("User password not correct.")
    }
}

func TestUpdateUser_mongodb(t *testing.T) {
    user2 := UserData{"username", "newemail", []byte("newpassword"), "newrole"}
    if err := backend.SaveUser(user2); err != nil {
        t.Fatalf("SaveUser mongodb error: %v", err)
    }
    u2, ok := backend.User("username")
    if !ok {
        t.Fatal("Updated user not found")
    }
    if u2.Username != "username" {
        t.Fatal("Username not correct.")
    }
    if u2.Email != "newemail" {
        t.Fatal("User email not correct.")
    }
    if u2.Role != "newrole" {
        t.Fatalf("User role not correct: found %v, expected %v", u2.Role, "newrole");
    }
    if !bytes.Equal(u2.Hash, []byte("newpassword")) {
        t.Fatal("User password not correct.")
    }
}

func TestMongodbDeleteUser_mongodb(t *testing.T) {
    if err := backend.DeleteUser("username"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }
    if err := backend.DeleteUser("username"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }

    if err := backend.DeleteUser("username2"); err != nil {
        t.Fatalf("DeleteUser error: %v", err)
    }
}

<|endoftext|>


<commit_before>package shell

import (
	"log"
	"os"
	"os/exec"
	"os/signal"
	"reflect"
	"strings"
	"syscall"

	"bytes"
	"github.com/gruntwork-io/terragrunt/errors"
	"github.com/gruntwork-io/terragrunt/options"
)

// Run the given Terraform command
func RunTerraformCommand(terragruntOptions *options.TerragruntOptions, args ...string) error {
	return RunShellCommand(terragruntOptions, terragruntOptions.TerraformPath, args...)
}

// Run the given Terraform command and return the stdout as a string
func RunTerraformCommandAndCaptureOutput(terragruntOptions *options.TerragruntOptions, args ...string) (string, error) {
	return RunShellCommandAndCaptureOutput(terragruntOptions, terragruntOptions.TerraformPath, args...)
}

// Run the specified shell command with the specified arguments. Connect the command's stdin, stdout, and stderr to
// the currently running app.
func RunShellCommand(terragruntOptions *options.TerragruntOptions, command string, args ...string) error {
	terragruntOptions.Logger.Printf("Running command: %s %s", command, strings.Join(args, " "))

	cmd := exec.Command(command, args...)

	// TODO: consider adding prefix from terragruntOptions logger to stdout and stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = terragruntOptions.Writer
	cmd.Stderr = terragruntOptions.ErrWriter

	// Terragrunt can run some commands (such as terraform remote config) before running the actual terraform
	// command requested by the user. The output of these other commands should not end up on stdout as this
	// breaks scripts relying on terraform's output.
	if !reflect.DeepEqual(terragruntOptions.TerraformCliArgs, args) {
		cmd.Stdout = cmd.Stderr
	}

	cmd.Dir = terragruntOptions.WorkingDir

	cmdChannel := make(chan error)
	signalChannel := NewSignalsForwarder(forwardSignals, cmd, terragruntOptions.Logger, cmdChannel)
	defer signalChannel.Close()

	err := cmd.Run()
	cmdChannel <- err

	return errors.WithStackTrace(err)
}

// Run the specified shell command with the specified arguments. Capture the command's stdout and return it as a
// string.
func RunShellCommandAndCaptureOutput(terragruntOptions *options.TerragruntOptions, command string, args ...string) (string, error) {
	stdout := new(bytes.Buffer)

	terragruntOptionsCopy := terragruntOptions.Clone(terragruntOptions.TerragruntConfigPath)
	terragruntOptionsCopy.Writer = stdout
	terragruntOptionsCopy.ErrWriter = stdout

	if err := RunShellCommand(terragruntOptionsCopy, command, args...); err != nil {
		return "", err
	}

	return stdout.String(), nil
}

// Return the exit code of a command. If the error is not an exec.ExitError type,
// the error is returned.
func GetExitCode(err error) (int, error) {
	if exiterr, ok := errors.Unwrap(err).(errors.IErrorCode); ok {
		return exiterr.ExitStatus()
	}

	if exiterr, ok := errors.Unwrap(err).(*exec.ExitError); ok {
		status := exiterr.Sys().(syscall.WaitStatus)
		return status.ExitStatus(), nil
	}
	return 0, err
}

type SignalsForwarder chan os.Signal

// Forwards signals to a command, waiting for the command to finish.
func NewSignalsForwarder(signals []os.Signal, c *exec.Cmd, logger *log.Logger, cmdChannel chan error) SignalsForwarder {
	signalChannel := make(chan os.Signal, 1)
	signal.Notify(signalChannel, signals...)

	go func() {
		for {
			select {
			case s := <-signalChannel:
				logger.Printf("Forward signal %s to terraform.", s.String())
				err := c.Process.Signal(s)
				if err != nil {
					logger.Printf("Error forwarding signal: %v", err)
				}
			case <-cmdChannel:
				return
			}
		}
	}()

	return signalChannel
}

func (signalChannel *SignalsForwarder) Close() error {
	signal.Stop(*signalChannel)
	*signalChannel <- nil
	close(*signalChannel)
	return nil
}
<commit_msg>Added specification to the GetExitCode() comment<commit_after>package shell

import (
	"log"
	"os"
	"os/exec"
	"os/signal"
	"reflect"
	"strings"
	"syscall"

	"bytes"
	"github.com/gruntwork-io/terragrunt/errors"
	"github.com/gruntwork-io/terragrunt/options"
)

// Run the given Terraform command
func RunTerraformCommand(terragruntOptions *options.TerragruntOptions, args ...string) error {
	return RunShellCommand(terragruntOptions, terragruntOptions.TerraformPath, args...)
}

// Run the given Terraform command and return the stdout as a string
func RunTerraformCommandAndCaptureOutput(terragruntOptions *options.TerragruntOptions, args ...string) (string, error) {
	return RunShellCommandAndCaptureOutput(terragruntOptions, terragruntOptions.TerraformPath, args...)
}

// Run the specified shell command with the specified arguments. Connect the command's stdin, stdout, and stderr to
// the currently running app.
func RunShellCommand(terragruntOptions *options.TerragruntOptions, command string, args ...string) error {
	terragruntOptions.Logger.Printf("Running command: %s %s", command, strings.Join(args, " "))

	cmd := exec.Command(command, args...)

	// TODO: consider adding prefix from terragruntOptions logger to stdout and stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = terragruntOptions.Writer
	cmd.Stderr = terragruntOptions.ErrWriter

	// Terragrunt can run some commands (such as terraform remote config) before running the actual terraform
	// command requested by the user. The output of these other commands should not end up on stdout as this
	// breaks scripts relying on terraform's output.
	if !reflect.DeepEqual(terragruntOptions.TerraformCliArgs, args) {
		cmd.Stdout = cmd.Stderr
	}

	cmd.Dir = terragruntOptions.WorkingDir

	cmdChannel := make(chan error)
	signalChannel := NewSignalsForwarder(forwardSignals, cmd, terragruntOptions.Logger, cmdChannel)
	defer signalChannel.Close()

	err := cmd.Run()
	cmdChannel <- err

	return errors.WithStackTrace(err)
}

// Run the specified shell command with the specified arguments. Capture the command's stdout and return it as a
// string.
func RunShellCommandAndCaptureOutput(terragruntOptions *options.TerragruntOptions, command string, args ...string) (string, error) {
	stdout := new(bytes.Buffer)

	terragruntOptionsCopy := terragruntOptions.Clone(terragruntOptions.TerragruntConfigPath)
	terragruntOptionsCopy.Writer = stdout
	terragruntOptionsCopy.ErrWriter = stdout

	if err := RunShellCommand(terragruntOptionsCopy, command, args...); err != nil {
		return "", err
	}

	return stdout.String(), nil
}

// Return the exit code of a command. If the error does not implement errors.IErrorCode or is not an exec.ExitError type,
// the error is returned.
func GetExitCode(err error) (int, error) {
	if exiterr, ok := errors.Unwrap(err).(errors.IErrorCode); ok {
		return exiterr.ExitStatus()
	}

	if exiterr, ok := errors.Unwrap(err).(*exec.ExitError); ok {
		status := exiterr.Sys().(syscall.WaitStatus)
		return status.ExitStatus(), nil
	}
	return 0, err
}

type SignalsForwarder chan os.Signal

// Forwards signals to a command, waiting for the command to finish.
func NewSignalsForwarder(signals []os.Signal, c *exec.Cmd, logger *log.Logger, cmdChannel chan error) SignalsForwarder {
	signalChannel := make(chan os.Signal, 1)
	signal.Notify(signalChannel, signals...)

	go func() {
		for {
			select {
			case s := <-signalChannel:
				logger.Printf("Forward signal %s to terraform.", s.String())
				err := c.Process.Signal(s)
				if err != nil {
					logger.Printf("Error forwarding signal: %v", err)
				}
			case <-cmdChannel:
				return
			}
		}
	}()

	return signalChannel
}

func (signalChannel *SignalsForwarder) Close() error {
	signal.Stop(*signalChannel)
	*signalChannel <- nil
	close(*signalChannel)
	return nil
}
<|endoftext|>


<commit_before>package security

import (
	. "jvmgo/any"
	"jvmgo/jvm/rtda"
	rtc "jvmgo/jvm/rtda/class"
)

func init() {
	_ac(doPrivileged, "doPrivileged", "(Ljava/security/PrivilegedAction;)Ljava/lang/Object;")
	_ac(doPrivileged2, "doPrivileged", "(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;")
	_ac(doPrivileged3, "doPrivileged", "(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;")
	_ac(getStackAccessControlContext, "getStackAccessControlContext", "()Ljava/security/AccessControlContext;")
}

func _ac(method Any, name, desc string) {
	rtc.RegisterNativeMethod("java/security/AccessController", name, desc, method)
}

// public static native <T> T doPrivileged(PrivilegedAction<T> action);
// (Ljava/security/PrivilegedAction;)Ljava/lang/Object;
func doPrivileged(frame *rtda.Frame) {
	vars := frame.LocalVars()
	action := vars.GetRef(0)

	stack := frame.OperandStack()
	stack.PushRef(action)

	method := action.Class().GetInstanceMethod("run", "()Ljava/lang/Object;") // todo
	frame.Thread().InvokeMethod(method)
}

// @CallerSensitive
// public static native <T> T
//     doPrivileged(PrivilegedExceptionAction<T> action)
//     throws PrivilegedActionException;
// (Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;
func doPrivileged2(frame *rtda.Frame) {
	// todo
	doPrivileged(frame)
}

// @CallerSensitive
// public static native <T> T doPrivileged(PrivilegedAction<T> action,
//                                         AccessControlContext context);
// (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;
func doPrivileged3(frame *rtda.Frame) {
	// todo
	doPrivileged(frame)
}

// private static native AccessControlContext getStackAccessControlContext();
// ()Ljava/security/AccessControlContext;
func getStackAccessControlContext(frame *rtda.Frame) {
	// todo
	frame.OperandStack().PushRef(nil)
}
<commit_msg>code refactor<commit_after>package security

import (
	. "jvmgo/any"
	"jvmgo/jvm/rtda"
	rtc "jvmgo/jvm/rtda/class"
)

func init() {
	_ac(doPrivileged, "doPrivileged", "(Ljava/security/PrivilegedAction;)Ljava/lang/Object;")
	_ac(doPrivileged2, "doPrivileged", "(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;")
	_ac(doPrivileged3, "doPrivileged", "(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;")
	_ac(getStackAccessControlContext, "getStackAccessControlContext", "()Ljava/security/AccessControlContext;")
}

func _ac(method Any, name, desc string) {
	rtc.RegisterNativeMethod("java/security/AccessController", name, desc, method)
}

// @CallerSensitive
// public static native <T> T doPrivileged(PrivilegedAction<T> action);
// (Ljava/security/PrivilegedAction;)Ljava/lang/Object;
func doPrivileged(frame *rtda.Frame) {
	vars := frame.LocalVars()
	action := vars.GetRef(0)

	stack := frame.OperandStack()
	stack.PushRef(action)

	method := action.Class().GetInstanceMethod("run", "()Ljava/lang/Object;") // todo
	frame.Thread().InvokeMethod(method)
}

// @CallerSensitive
// public static native <T> T doPrivileged(PrivilegedAction<T> action,
//                                         AccessControlContext context);
// (Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;
func doPrivileged2(frame *rtda.Frame) {
	// todo
	doPrivileged(frame)
}

// @CallerSensitive
// public static native <T> T
//     doPrivileged(PrivilegedExceptionAction<T> action)
//     throws PrivilegedActionException;
// (Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;
func doPrivileged3(frame *rtda.Frame) {
	// todo
	doPrivileged(frame)
}

// @CallerSensitive
// public static native <T> T
//     doPrivileged(PrivilegedExceptionAction<T> action,
//                  AccessControlContext context)
//     throws PrivilegedActionException;
//

// private static native AccessControlContext getStackAccessControlContext();
// ()Ljava/security/AccessControlContext;
func getStackAccessControlContext(frame *rtda.Frame) {
	// todo
	frame.OperandStack().PushRef(nil)
}
<|endoftext|>