<commit_before>package docker

import (
	"fmt"
	"strings"
)

// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
// If OpenStdin is set, then it differs
func CompareConfig(a, b *Config) bool {
	if a == nil || b == nil ||
		a.OpenStdin || b.OpenStdin {
		return false
	}
	if a.AttachStdout != b.AttachStdout ||
		a.AttachStderr != b.AttachStderr ||
		a.User != b.User ||
		a.Memory != b.Memory ||
		a.MemorySwap != b.MemorySwap ||
		a.CpuShares != b.CpuShares ||
		a.OpenStdin != b.OpenStdin ||
		a.Tty != b.Tty ||
		a.VolumesFrom != b.VolumesFrom {
		return false
	}
	if len(a.Cmd) != len(b.Cmd) ||
		len(a.Dns) != len(b.Dns) ||
		len(a.Env) != len(b.Env) ||
		len(a.PortSpecs) != len(b.PortSpecs) ||
		len(a.Entrypoint) != len(b.Entrypoint) ||
		len(a.Volumes) != len(b.Volumes) {
		return false
	}

	for i := 0; i < len(a.Cmd); i++ {
		if a.Cmd[i] != b.Cmd[i] {
			return false
		}
	}
	for i := 0; i < len(a.Dns); i++ {
		if a.Dns[i] != b.Dns[i] {
			return false
		}
	}
	for i := 0; i < len(a.Env); i++ {
		if a.Env[i] != b.Env[i] {
			return false
		}
	}
	for i := 0; i < len(a.PortSpecs); i++ {
		if a.PortSpecs[i] != b.PortSpecs[i] {
			return false
		}
	}
	for i := 0; i < len(a.Entrypoint); i++ {
		if a.Entrypoint[i] != b.Entrypoint[i] {
			return false
		}
	}
	for key := range a.Volumes {
		if _, exists := b.Volumes[key]; !exists {
			return false
		}
	}
	return true
}

func MergeConfig(userConf, imageConf *Config) error {
	if userConf.User == "" {
		userConf.User = imageConf.User
	}
	if userConf.Memory == 0 {
		userConf.Memory = imageConf.Memory
	}
	if userConf.MemorySwap == 0 {
		userConf.MemorySwap = imageConf.MemorySwap
	}
	if userConf.CpuShares == 0 {
		userConf.CpuShares = imageConf.CpuShares
	}
	if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
		userConf.PortSpecs = imageConf.PortSpecs
	} else {
		for _, imagePortSpec := range imageConf.PortSpecs {
			found := false
			imageNat, _ := parseNat(imagePortSpec)
			for _, userPortSpec := range userConf.PortSpecs {
				userNat, err := parseNat(userPortSpec)
				if err != nil {
					return err
				}
				if imageNat.Proto == userNat.Proto && imageNat.Backend == userNat.Backend {
					found = true
				}
			}
			if !found {
				userConf.PortSpecs = append(userConf.PortSpecs, imagePortSpec)
			}
		}
	}
	if !userConf.Tty {
		userConf.Tty = imageConf.Tty
	}
	if !userConf.OpenStdin {
		userConf.OpenStdin = imageConf.OpenStdin
	}
	if !userConf.StdinOnce {
		userConf.StdinOnce = imageConf.StdinOnce
	}
	if userConf.Env == nil || len(userConf.Env) == 0 {
		userConf.Env = imageConf.Env
	} else {
		for _, imageEnv := range imageConf.Env {
			found := false
			imageEnvKey := strings.Split(imageEnv, "=")[0]
			for _, userEnv := range userConf.Env {
				userEnvKey := strings.Split(userEnv, "=")[0]
				if imageEnvKey == userEnvKey {
					found = true
				}
			}
			if !found {
				userConf.Env = append(userConf.Env, imageEnv)
			}
		}
	}
	if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
		userConf.Cmd = imageConf.Cmd
	}
	if userConf.Dns == nil || len(userConf.Dns) == 0 {
		userConf.Dns = imageConf.Dns
	} else {
		//duplicates aren't an issue here
		userConf.Dns = append(userConf.Dns, imageConf.Dns...)
	}
	if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
		userConf.Entrypoint = imageConf.Entrypoint
	}
	if userConf.WorkingDir == "" {
		userConf.WorkingDir = imageConf.WorkingDir
	}
	if userConf.VolumesFrom == "" {
		userConf.VolumesFrom = imageConf.VolumesFrom
	}
	if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
		userConf.Volumes = imageConf.Volumes
	} else {
		for k, v := range imageConf.Volumes {
			userConf.Volumes[k] = v
		}
	}
	return nil
}

func parseLxcConfOpts(opts ListOpts) ([]KeyValuePair, error) {
	out := make([]KeyValuePair, len(opts))
	for i, o := range opts {
		k, v, err := parseLxcOpt(o)
		if err != nil {
			return nil, err
		}
		out[i] = KeyValuePair{Key: k, Value: v}
	}
	return out, nil
}

func parseLxcOpt(opt string) (string, string, error) {
	parts := strings.SplitN(opt, "=", 2)
	if len(parts) != 2 {
		return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
	}
	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
}
<commit_msg>add missing error check<commit_after>package docker

import (
	"fmt"
	"strings"
)

// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
// If OpenStdin is set, then it differs
func CompareConfig(a, b *Config) bool {
	if a == nil || b == nil ||
		a.OpenStdin || b.OpenStdin {
		return false
	}
	if a.AttachStdout != b.AttachStdout ||
		a.AttachStderr != b.AttachStderr ||
		a.User != b.User ||
		a.Memory != b.Memory ||
		a.MemorySwap != b.MemorySwap ||
		a.CpuShares != b.CpuShares ||
		a.OpenStdin != b.OpenStdin ||
		a.Tty != b.Tty ||
		a.VolumesFrom != b.VolumesFrom {
		return false
	}
	if len(a.Cmd) != len(b.Cmd) ||
		len(a.Dns) != len(b.Dns) ||
		len(a.Env) != len(b.Env) ||
		len(a.PortSpecs) != len(b.PortSpecs) ||
		len(a.Entrypoint) != len(b.Entrypoint) ||
		len(a.Volumes) != len(b.Volumes) {
		return false
	}

	for i := 0; i < len(a.Cmd); i++ {
		if a.Cmd[i] != b.Cmd[i] {
			return false
		}
	}
	for i := 0; i < len(a.Dns); i++ {
		if a.Dns[i] != b.Dns[i] {
			return false
		}
	}
	for i := 0; i < len(a.Env); i++ {
		if a.Env[i] != b.Env[i] {
			return false
		}
	}
	for i := 0; i < len(a.PortSpecs); i++ {
		if a.PortSpecs[i] != b.PortSpecs[i] {
			return false
		}
	}
	for i := 0; i < len(a.Entrypoint); i++ {
		if a.Entrypoint[i] != b.Entrypoint[i] {
			return false
		}
	}
	for key := range a.Volumes {
		if _, exists := b.Volumes[key]; !exists {
			return false
		}
	}
	return true
}

func MergeConfig(userConf, imageConf *Config) error {
	if userConf.User == "" {
		userConf.User = imageConf.User
	}
	if userConf.Memory == 0 {
		userConf.Memory = imageConf.Memory
	}
	if userConf.MemorySwap == 0 {
		userConf.MemorySwap = imageConf.MemorySwap
	}
	if userConf.CpuShares == 0 {
		userConf.CpuShares = imageConf.CpuShares
	}
	if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
		userConf.PortSpecs = imageConf.PortSpecs
	} else {
		for _, imagePortSpec := range imageConf.PortSpecs {
			found := false
			imageNat, err := parseNat(imagePortSpec)
			if err != nil {
				return err
			}
			for _, userPortSpec := range userConf.PortSpecs {
				userNat, err := parseNat(userPortSpec)
				if err != nil {
					return err
				}
				if imageNat.Proto == userNat.Proto && imageNat.Backend == userNat.Backend {
					found = true
				}
			}
			if !found {
				userConf.PortSpecs = append(userConf.PortSpecs, imagePortSpec)
			}
		}
	}
	if !userConf.Tty {
		userConf.Tty = imageConf.Tty
	}
	if !userConf.OpenStdin {
		userConf.OpenStdin = imageConf.OpenStdin
	}
	if !userConf.StdinOnce {
		userConf.StdinOnce = imageConf.StdinOnce
	}
	if userConf.Env == nil || len(userConf.Env) == 0 {
		userConf.Env = imageConf.Env
	} else {
		for _, imageEnv := range imageConf.Env {
			found := false
			imageEnvKey := strings.Split(imageEnv, "=")[0]
			for _, userEnv := range userConf.Env {
				userEnvKey := strings.Split(userEnv, "=")[0]
				if imageEnvKey == userEnvKey {
					found = true
				}
			}
			if !found {
				userConf.Env = append(userConf.Env, imageEnv)
			}
		}
	}
	if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
		userConf.Cmd = imageConf.Cmd
	}
	if userConf.Dns == nil || len(userConf.Dns) == 0 {
		userConf.Dns = imageConf.Dns
	} else {
		//duplicates aren't an issue here
		userConf.Dns = append(userConf.Dns, imageConf.Dns...)
	}
	if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
		userConf.Entrypoint = imageConf.Entrypoint
	}
	if userConf.WorkingDir == "" {
		userConf.WorkingDir = imageConf.WorkingDir
	}
	if userConf.VolumesFrom == "" {
		userConf.VolumesFrom = imageConf.VolumesFrom
	}
	if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
		userConf.Volumes = imageConf.Volumes
	} else {
		for k, v := range imageConf.Volumes {
			userConf.Volumes[k] = v
		}
	}
	return nil
}

func parseLxcConfOpts(opts ListOpts) ([]KeyValuePair, error) {
	out := make([]KeyValuePair, len(opts))
	for i, o := range opts {
		k, v, err := parseLxcOpt(o)
		if err != nil {
			return nil, err
		}
		out[i] = KeyValuePair{Key: k, Value: v}
	}
	return out, nil
}

func parseLxcOpt(opt string) (string, string, error) {
	parts := strings.SplitN(opt, "=", 2)
	if len(parts) != 2 {
		return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
	}
	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"strings"
)

// Convert and concatenate a []int8 slice to a string
// inspired by perterGo: https://groups.google.com/forum/#!topic/golang-nuts/Jel8Bb-YwX8
func int8SliceToString(char []int8) string {
	s := make([]string, len(char))
	for i := range s {
		s[i] = string(char[i])
	}
	return strings.Join(s, "")
	// TODO maybe change this to convert exclusively to [65]int8 array ?
}

// Read a text file and return the content without the EOF carriage return
// this utility may be used with files from `/sys` or `/proc` file systems
func readAndTrimFile(path string) (ret string, err error) {
	ret = ""
	data, err := ioutil.ReadFile(path)
	if err == nil {
		ret = strings.TrimRight(string(data), "\n") // Trimright remove the EOF carriage return
	}
	return ret, err
	//TODO manage multiple line files ?
}

// `appendError()` combines two errors into one
func appendError(err1 error, err2 error) (err error) {
	switch {
	case err1 != nil && err2 != nil:
		err = fmt.Errorf("%v; %v", err1, err2)
	case err1 != nil:
		err = err1
	case err2 != nil:
		err = err2
	case err1 == nil && err2 == nil:
		err = nil
	}

	return err
}
<commit_msg>Update comments<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"strings"
)

// int8SliceToString convert and concatenate a []int8 slice to a string
// inspired by perterGo: https://groups.google.com/forum/#!topic/golang-nuts/Jel8Bb-YwX8
func int8SliceToString(char []int8) string {
	s := make([]string, len(char))
	for i := range s {
		s[i] = string(char[i])
	}
	return strings.Join(s, "")
	// TODO maybe change this to convert exclusively to [65]int8 array ?
}

// readAndTrimFile read a text file and return the content without the EOF carriage return
// this utility may be used with files from `/sys` or `/proc` file systems
func readAndTrimFile(path string) (ret string, err error) {
	ret = ""
	data, err := ioutil.ReadFile(path)
	if err == nil {
		ret = strings.TrimRight(string(data), "\n") // Trimright remove the EOF carriage return
	}
	return ret, err
	//TODO manage multiple line files ?
}

// appendError() combines two errors into one
func appendError(err1 error, err2 error) (err error) {
	switch {
	case err1 != nil && err2 != nil:
		err = fmt.Errorf("%v; %v", err1, err2)
	case err1 != nil:
		err = err1
	case err2 != nil:
		err = err2
	case err1 == nil && err2 == nil:
		err = nil
	}

	return err
}
<|endoftext|>


<commit_before>package gopac

import (
	"net"
	"os"
	"regexp"
	"strings"

	"github.com/robertkrimen/otto"
)

const dnsServer = "8.8.8.8:53"

// isPlainHostName return true if there is no domain name in the host.
func isPlainHostName(host string) bool {
	return strings.Index(host, ".") == -1
}

// dnsDomainIs return true if the host is valid for the domain.
func dnsDomainIs(host, domain string) bool {
	if len(host) < len(domain) {
		return false
	}

	return strings.HasSuffix(host, domain)
}

// localHostOrDomainIs returns true if the host matches the specified hostdom,
// or if there is no domain name part in the host, but the unqualified hostdom
// matches.
func localHostOrDomainIs(host, hostdom string) bool {
	if host == hostdom {
		return true
	}

	return strings.LastIndex(hostdom, host+".") == 0
}

// isResolvable returns true if the host is resolvable.
func isResolvable(host string) bool {
	if len(host) == 0 {
		return false
	}

	if _, err := net.ResolveIPAddr("ip4", host); err != nil {
		return false
	}

	return true
}

// isInNet returns true if the IP address of the host matches the specified IP
// address pattern.
// mask is the pattern informing which parts of the IP address to match against.
// 0 means ignore, 255 means match.
func isInNet(host, pattern, mask string) bool {
	if len(host) == 0 {
		return false
	}

	address, err := net.ResolveIPAddr("ip4", host)

	if err != nil {
		return false
	}

	maskIp := net.IPMask(net.ParseIP(mask))
	return address.IP.Mask(maskIp).String() == pattern
}

// dnsResolve returns the IP address of the host.
func dnsResolve(host string) string {
	address, err := net.ResolveIPAddr("ip4", host)

	if err != nil {
		return ""
	}

	return address.String()
}

// myIpAddress returns the IP address of the host machine.
func myIpAddress() otto.Value {
	hostname, err := os.Hostname()

	if err != nil {
		return otto.UndefinedValue()
	}

	address := dnsResolve(hostname)

	if value, err := otto.ToValue(address); err == nil {
		return value
	}

	return otto.UndefinedValue()
}

// dnsDomainLevels returns the number of domain levels in the host.
func dnsDomainLevels(host string) int {
	return strings.Count(host, ".")
}

// shExpMatch returns true if the string matches the specified shell expression.
func shExpMatch(str, shexp string) bool {
	shexp = strings.Replace(shexp, ".", "\\.", -1)
	shexp = strings.Replace(shexp, "?", ".?", -1)
	shexp = strings.Replace(shexp, "*", ".*", -1)
	matched, err := regexp.MatchString(shexp, "^"+str+"$")

	return err == nil && matched
}
<commit_msg>feature(utils): add built-in date/time functions<commit_after>// Copyright 2014 Jack Wakefield
//
// 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 gopac

import (
	"net"
	"os"
	"regexp"
	"strings"

	"github.com/robertkrimen/otto"
)

// https://lxr.mozilla.org/seamonkey/source/netwerk/base/src/nsProxyAutoConfig.js
var javascriptUtils string = `
 var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};
 var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11}
 function weekdayRange() {
     function getDay(weekday) {
         if (weekday in wdays) {
             return wdays[weekday];
         }
         return -1;
     }
     var date = new Date();
     var argc = arguments.length;
     var wday;
     if (argc < 1)
         return false;
     if (arguments[argc - 1] == 'GMT') {
         argc--;
         wday = date.getUTCDay();
     } else {
         wday = date.getDay();
     }
     var wd1 = getDay(arguments[0]);
     var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;
     return (wd1 == -1 || wd2 == -1) ? false
                                     : (wd1 <= wday && wday <= wd2);
 }

 function dateRange() {
     function getMonth(name) {
         if (name in months) {
             return months[name];
         }
         return -1;
     }
     var date = new Date();
     var argc = arguments.length;
     if (argc < 1) {
         return false;
     }
     var isGMT = (arguments[argc - 1] == 'GMT');

     if (isGMT) {
         argc--;
     }
     // function will work even without explict handling of this case
     if (argc == 1) {
         var tmp = parseInt(arguments[0]);
         if (isNaN(tmp)) {
             return ((isGMT ? date.getUTCMonth() : date.getMonth()) ==
 getMonth(arguments[0]));
         } else if (tmp < 32) {
             return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);
         } else {
             return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==
 tmp);
         }
     }
     var year = date.getFullYear();
     var date1, date2;
     date1 = new Date(year,  0,  1,  0,  0,  0);
     date2 = new Date(year, 11, 31, 23, 59, 59);
     var adjustMonth = false;
     for (var i = 0; i < (argc >> 1); i++) {
         var tmp = parseInt(arguments[i]);
         if (isNaN(tmp)) {
             var mon = getMonth(arguments[i]);
             date1.setMonth(mon);
         } else if (tmp < 32) {
             adjustMonth = (argc <= 2);
             date1.setDate(tmp);
         } else {
             date1.setFullYear(tmp);
         }
     }
     for (var i = (argc >> 1); i < argc; i++) {
         var tmp = parseInt(arguments[i]);
         if (isNaN(tmp)) {
             var mon = getMonth(arguments[i]);
             date2.setMonth(mon);
         } else if (tmp < 32) {
             date2.setDate(tmp);
         } else {
             date2.setFullYear(tmp);
         }
     }
     if (adjustMonth) {
         date1.setMonth(date.getMonth());
         date2.setMonth(date.getMonth());
     }
     if (isGMT) {
     var tmp = date;
         tmp.setFullYear(date.getUTCFullYear());
         tmp.setMonth(date.getUTCMonth());
         tmp.setDate(date.getUTCDate());
         tmp.setHours(date.getUTCHours());
         tmp.setMinutes(date.getUTCMinutes());
         tmp.setSeconds(date.getUTCSeconds());
         date = tmp;
     }
     return ((date1 <= date) && (date <= date2));
 }

 function timeRange() {
     var argc = arguments.length;
     var date = new Date();
     var isGMT= false

     if (argc < 1) {
         return false;
     }
     if (arguments[argc - 1] == 'GMT') {
         isGMT = true;
         argc--;
     }

     var hour = isGMT ? date.getUTCHours() : date.getHours();
     var date1, date2;
     date1 = new Date();
     date2 = new Date();

     if (argc == 1) {
         return (hour == arguments[0]);
     } else if (argc == 2) {
         return ((arguments[0] <= hour) && (hour <= arguments[1]));
     } else {
         switch (argc) {
         case 6:
             date1.setSeconds(arguments[2]);
             date2.setSeconds(arguments[5]);
         case 4:
             var middle = argc >> 1;
             date1.setHours(arguments[0]);
             date1.setMinutes(arguments[1]);
             date2.setHours(arguments[middle]);
             date2.setMinutes(arguments[middle + 1]);
             if (middle == 2) {
                 date2.setSeconds(59);
             }
             break;
         default:
           throw 'timeRange: bad number of arguments'
         }
     }

     if (isGMT) {
         date.setFullYear(date.getUTCFullYear());
         date.setMonth(date.getUTCMonth());
         date.setDate(date.getUTCDate());
         date.setHours(date.getUTCHours());
         date.setMinutes(date.getUTCMinutes());
         date.setSeconds(date.getUTCSeconds());
     }
     return ((date1 <= date) && (date <= date2));
}`

// isPlainHostName return true if there is no domain name in the host.
func isPlainHostName(host string) bool {
	return strings.Index(host, ".") == -1
}

// dnsDomainIs return true if the host is valid for the domain.
func dnsDomainIs(host, domain string) bool {
	if len(host) < len(domain) {
		return false
	}

	return strings.HasSuffix(host, domain)
}

// localHostOrDomainIs returns true if the host matches the specified hostdom,
// or if there is no domain name part in the host, but the unqualified hostdom
// matches.
func localHostOrDomainIs(host, hostdom string) bool {
	if host == hostdom {
		return true
	}

	return strings.LastIndex(hostdom, host+".") == 0
}

// isResolvable returns true if the host is resolvable.
func isResolvable(host string) bool {
	if len(host) == 0 {
		return false
	}

	if _, err := net.ResolveIPAddr("ip4", host); err != nil {
		return false
	}

	return true
}

// isInNet returns true if the IP address of the host matches the specified IP
// address pattern.
// mask is the pattern informing which parts of the IP address to match against.
// 0 means ignore, 255 means match.
func isInNet(host, pattern, mask string) bool {
	if len(host) == 0 {
		return false
	}

	address, err := net.ResolveIPAddr("ip4", host)

	if err != nil {
		return false
	}

	maskIp := net.IPMask(net.ParseIP(mask))
	return address.IP.Mask(maskIp).String() == pattern
}

// dnsResolve returns the IP address of the host.
func dnsResolve(host string) string {
	address, err := net.ResolveIPAddr("ip4", host)

	if err != nil {
		return ""
	}

	return address.String()
}

// myIpAddress returns the IP address of the host machine.
func myIpAddress() otto.Value {
	hostname, err := os.Hostname()

	if err != nil {
		return otto.UndefinedValue()
	}

	address := dnsResolve(hostname)

	if value, err := otto.ToValue(address); err == nil {
		return value
	}

	return otto.UndefinedValue()
}

// dnsDomainLevels returns the number of domain levels in the host.
func dnsDomainLevels(host string) int {
	return strings.Count(host, ".")
}

// shExpMatch returns true if the string matches the specified shell expression.
func shExpMatch(str, shexp string) bool {
	shexp = strings.Replace(shexp, ".", "\\.", -1)
	shexp = strings.Replace(shexp, "?", ".?", -1)
	shexp = strings.Replace(shexp, "*", ".*", -1)
	matched, err := regexp.MatchString("^"+shexp+"$", str)

	return err == nil && matched
}
<|endoftext|>


<commit_before>package btree

import (
	"bytes"
	"code.google.com/p/goprotobuf/proto"
	"time"
	"sync/atomic"
)

// TreeNode interface
// node, leaf support this interface
type TreeNode interface {
	insertRecord(record *Record, tree *Btree) (bool, TreeNode)
	deleteRecord(key []byte, tree *Btree) (bool, TreeNode, []byte)
	updateRecord(recode *Record, tree *Btree) (bool, TreeNode)
	searchRecord(key []byte, tree *Btree) []byte
	split(tree *Btree) (key []byte, left, right int32)
	locate(key []byte) int
	GetId() int32
	GetKeys() [][]byte
}

// genrate node/leaf id
func (t *Btree) genrateID() int32 {
	var id int32
	if len(t.FreeList) > 0 {
		id = t.FreeList[len(t.FreeList)-1]
		t.FreeList = t.FreeList[:len(t.FreeList)-1]
	} else {
		if t.GetIndexCursor() >= t.GetSize() {
			t.nodes = append(t.nodes, make([]TreeNode, TreeSize)...)
			*t.Size += int32(TreeSize)
		}
		id = t.GetIndexCursor()
		*t.IndexCursor++
	}
	return id
}

//alloc new leaf
func (t *Btree) newLeaf() *Leaf {
	*t.LeafCount++
	id := t.genrateID()
	leaf := &Leaf{
		IndexMetaData: IndexMetaData{Id: proto.Int32(id),
			Version: proto.Uint32(t.GetVersion())},
	}
	t.nodes[id] = leaf
	return leaf
}

//alloc new tree node
func (t *Btree) newNode() *Node {
	*t.NodeCount++
	id := t.genrateID()
	node := &Node{
		IndexMetaData: IndexMetaData{Id: proto.Int32(id),
			Version: proto.Uint32(t.GetVersion())},
	}
	t.nodes[id] = node
	return node
}

//mark node/leaf duplicated
func (t *Btree)markDup(id int32) {
	t.dupnodelist = append(t.dupnodelist, id)
}

//get node by id
func (t *Btree)getNode(id int32) *Node {
	if node, ok := t.nodes[id].(*Node); ok {
		return node
	}
	return nil
}

//get leaf by id
func (t *Btree)getLeaf(id int32) *Leaf {
	if leaf, ok := t.nodes[id].(*Leaf); ok {
		return leaf
	}
	return nil
}

//locate key's index in a node
func (n *Node) locate(key []byte) int {
	i := 0
	size := len(n.Keys)
	for {
		mid := (i + size) / 2
		if i == size {
			break
		}
		if bytes.Compare(n.Keys[mid], key) <= 0 {
			i = mid + 1
		} else {
			size = mid
		}
	}
	return i
}

//locate key's index in a leaf
func (l *Leaf) locate(key []byte) int {
	i := 0
	size := len(l.Keys)
	for {
		mid := (i + size) / 2
		if i == size {
			break
		}
		if bytes.Compare(l.Keys[mid], key) <= 0 {
			i = mid + 1
		} else {
			size = mid
		}
	}
	return i
}

//clone node
func (n *Node) clone(tree *Btree) TreeNode {
	nnode := tree.newNode()
	nnode.Keys = make([][]byte, len(n.Keys))
	copy(nnode.Keys, n.Keys)
	nnode.Childrens = make([]int32, len(n.Childrens))
	copy(nnode.Childrens, n.Childrens)
	return nnode
}

//clone leaf
func (l *Leaf) clone(tree *Btree) TreeNode {
	nleaf := tree.newLeaf()
	nleaf.Keys = make([][]byte, len(l.Keys))
	copy(nleaf.Keys, l.Keys)
	nleaf.Values = make([][]byte, len(l.Values))
	copy(nleaf.Values, l.Values)
	return nleaf
}

//gc dupnodelist
func (t *Btree) gc() {
	for {
		if atomic.CompareAndSwapInt32(&t.state, StateNormal, StateGc) {
			if len(t.dupnodelist) > 0 {
				id := t.dupnodelist[len(t.dupnodelist)-1]
				switch t.nodes[id].(type) {
				case *Node:
					*t.NodeCount--
				case *Leaf:
					*t.LeafCount--
				default:
					atomic.CompareAndSwapInt32(&t.state, StateDump, StateNormal)
					continue
				}
				t.FreeList = append(t.FreeList, id)
				t.dupnodelist = t.dupnodelist[:len(t.dupnodelist)-1]
				atomic.CompareAndSwapInt32(&t.state, StateGc, StateNormal)
			}
		} else {
			time.Sleep(time.Second)
		}
	}
}
<commit_msg>bugfix<commit_after>package btree

import (
	"bytes"
	"code.google.com/p/goprotobuf/proto"
	"time"
	"sync/atomic"
)

// TreeNode interface
// node, leaf support this interface
type TreeNode interface {
	insertRecord(record *Record, tree *Btree) (bool, TreeNode)
	deleteRecord(key []byte, tree *Btree) (bool, TreeNode, []byte)
	updateRecord(recode *Record, tree *Btree) (bool, TreeNode)
	searchRecord(key []byte, tree *Btree) []byte
	split(tree *Btree) (key []byte, left, right int32)
	locate(key []byte) int
	GetId() int32
	GetKeys() [][]byte
}

// genrate node/leaf id
func (t *Btree) genrateID() int32 {
	var id int32
	if len(t.FreeList) > 0 {
		id = t.FreeList[len(t.FreeList)-1]
		t.FreeList = t.FreeList[:len(t.FreeList)-1]
	} else {
		if t.GetIndexCursor() >= t.GetSize() {
			t.nodes = append(t.nodes, make([]TreeNode, TreeSize)...)
			*t.Size += int32(TreeSize)
		}
		id = t.GetIndexCursor()
		*t.IndexCursor++
	}
	return id
}

//alloc new leaf
func (t *Btree) newLeaf() *Leaf {
	*t.LeafCount++
	id := t.genrateID()
	leaf := &Leaf{
		IndexMetaData: IndexMetaData{Id: proto.Int32(id),
			Version: proto.Uint32(t.GetVersion())},
	}
	t.nodes[id] = leaf
	return leaf
}

//alloc new tree node
func (t *Btree) newNode() *Node {
	*t.NodeCount++
	id := t.genrateID()
	node := &Node{
		IndexMetaData: IndexMetaData{Id: proto.Int32(id),
			Version: proto.Uint32(t.GetVersion())},
	}
	t.nodes[id] = node
	return node
}

//mark node/leaf duplicated
func (t *Btree)markDup(id int32) {
	t.dupnodelist = append(t.dupnodelist, id)
}

//get node by id
func (t *Btree)getNode(id int32) *Node {
	if node, ok := t.nodes[id].(*Node); ok {
		return node
	}
	return nil
}

//get leaf by id
func (t *Btree)getLeaf(id int32) *Leaf {
	if leaf, ok := t.nodes[id].(*Leaf); ok {
		return leaf
	}
	return nil
}

//locate key's index in a node
func (n *Node) locate(key []byte) int {
	i := 0
	size := len(n.Keys)
	for {
		mid := (i + size) / 2
		if i == size {
			break
		}
		if bytes.Compare(n.Keys[mid], key) <= 0 {
			i = mid + 1
		} else {
			size = mid
		}
	}
	return i
}

//locate key's index in a leaf
func (l *Leaf) locate(key []byte) int {
	i := 0
	size := len(l.Keys)
	for {
		mid := (i + size) / 2
		if i == size {
			break
		}
		if bytes.Compare(l.Keys[mid], key) <= 0 {
			i = mid + 1
		} else {
			size = mid
		}
	}
	return i
}

//clone node
func (n *Node) clone(tree *Btree) TreeNode {
	nnode := tree.newNode()
	nnode.Keys = make([][]byte, len(n.Keys))
	copy(nnode.Keys, n.Keys)
	nnode.Childrens = make([]int32, len(n.Childrens))
	copy(nnode.Childrens, n.Childrens)
	return nnode
}

//clone leaf
func (l *Leaf) clone(tree *Btree) TreeNode {
	nleaf := tree.newLeaf()
	nleaf.Keys = make([][]byte, len(l.Keys))
	copy(nleaf.Keys, l.Keys)
	nleaf.Values = make([][]byte, len(l.Values))
	copy(nleaf.Values, l.Values)
	return nleaf
}

//gc dupnodelist
func (t *Btree) gc() {
	for {
		if atomic.CompareAndSwapInt32(&t.state, StateNormal, StateGc) {
			if len(t.dupnodelist) > 0 {
				id := t.dupnodelist[len(t.dupnodelist)-1]
				switch t.nodes[id].(type) {
				case *Node:
					*t.NodeCount--
				case *Leaf:
					*t.LeafCount--
				default:
					atomic.CompareAndSwapInt32(&t.state, StateGc, StateNormal)
					continue
				}
				t.FreeList = append(t.FreeList, id)
				t.dupnodelist = t.dupnodelist[:len(t.dupnodelist)-1]
				atomic.CompareAndSwapInt32(&t.state, StateGc, StateNormal)
			}
		} else {
			time.Sleep(time.Second)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	//"fmt"
	"github.com/adeven/redismq"
	. "github.com/matttproud/gocheck"
	"strconv"
	"sync"
)

//benchmark single publisher 1k payload
func (suite *TestSuite) BenchmarkSinglePub1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < c.N; i++ {
		suite.queue.Put(payload)
	}
}

//benchmark single consumer 1k payload
func (suite *TestSuite) BenchmarkSingleCon1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.Get()
		p.Ack()
	}
}

//benchmark single consumer multi 100 1k payload
func (suite *TestSuite) BenchmarkSingleConMulti1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.MultiGet(100)
		p[99].Ack()
	}
}

//benchmark single publisher 4k payload
func (suite *TestSuite) BenchmarkSinglePub4k(c *C) {
	payload := randomString(1024 * 4)
	for i := 0; i < c.N; i++ {
		suite.queue.Put(payload)
	}
}

//benchmark single consumer 4k payload
func (suite *TestSuite) BenchmarkSingleCon4k(c *C) {
	payload := randomString(1024 * 4)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.Get()
		p.Ack()
	}
}

//benchmark four publishers 1k payload
func (suite *TestSuite) BenchmarkFourPub1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
		}
		wg.Wait()
	}
}

//benchmark four consumers 1k payload
func (suite *TestSuite) BenchmarkFourCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark four publisher 4k payload
func (suite *TestSuite) BenchmarkFourPub4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
		}
		wg.Wait()
	}
}

//benchmark four consumers 4k payload
func (suite *TestSuite) BenchmarkFourCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark single publisher and single consumer 1k payload
func (suite *TestSuite) BenchmarkSingPubSingCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		wg.Add(1)
		go func() {
			suite.queue.Put(payload)
			defer wg.Done()
		}()
		wg.Add(1)
		go func() {
			p, _ := suite.consumer.Get()
			p.Ack()
			defer wg.Done()
		}()
		wg.Wait()
	}
}

//benchmark single publisher and single consumer 4k payload
func (suite *TestSuite) BenchmarkSingPubSingCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		wg.Add(1)
		go func() {
			suite.queue.Put(payload)
			defer wg.Done()
		}()
		wg.Add(1)
		go func() {
			p, _ := suite.consumer.Get()
			p.Ack()
			defer wg.Done()
		}()
		wg.Wait()
	}
}

//benchmark four publisher and four consumers 1k payload
func (suite *TestSuite) BenchmarkFourPubFourCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark four publisher and four consumers 4k payload
func (suite *TestSuite) BenchmarkFourPubFourCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}
<commit_msg>fix failing bench<commit_after>package main

import (
	"fmt"
	"github.com/adeven/redismq"
	. "github.com/matttproud/gocheck"
	"strconv"
	"sync"
)

//benchmark single publisher 1k payload
func (suite *TestSuite) BenchmarkSinglePub1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < c.N; i++ {
		suite.queue.Put(payload)
	}
}

//benchmark single consumer 1k payload
func (suite *TestSuite) BenchmarkSingleCon1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.Get()
		p.Ack()
	}
}

//benchmark single consumer multi 100 1k payload
func (suite *TestSuite) BenchmarkSingleConMulti1k(c *C) {
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.MultiGet(100)
		p[99].MutliAck()
	}
}

//benchmark single publisher 4k payload
func (suite *TestSuite) BenchmarkSinglePub4k(c *C) {
	payload := randomString(1024 * 4)
	for i := 0; i < c.N; i++ {
		suite.queue.Put(payload)
	}
}

//benchmark single consumer 4k payload
func (suite *TestSuite) BenchmarkSingleCon4k(c *C) {
	payload := randomString(1024 * 4)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		p, _ := suite.consumer.Get()
		p.Ack()
	}
}

//benchmark four publishers 1k payload
func (suite *TestSuite) BenchmarkFourPub1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
		}
		wg.Wait()
	}
}

//benchmark four consumers 1k payload
func (suite *TestSuite) BenchmarkFourCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark four publisher 4k payload
func (suite *TestSuite) BenchmarkFourPub4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
		}
		wg.Wait()
	}
}

//benchmark four consumers 4k payload
func (suite *TestSuite) BenchmarkFourCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	for i := 0; i < 100000; i++ {
		suite.queue.Put(payload)
	}
	c.ResetTimer()
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark single publisher and single consumer 1k payload
func (suite *TestSuite) BenchmarkSingPubSingCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		wg.Add(1)
		go func() {
			suite.queue.Put(payload)
			defer wg.Done()
		}()
		wg.Add(1)
		go func() {
			p, _ := suite.consumer.Get()
			p.Ack()
			defer wg.Done()
		}()
		wg.Wait()
	}
}

//benchmark single publisher and single consumer 4k payload
func (suite *TestSuite) BenchmarkSingPubSingCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		wg.Add(1)
		go func() {
			suite.queue.Put(payload)
			defer wg.Done()
		}()
		wg.Add(1)
		go func() {
			p, _ := suite.consumer.Get()
			p.Ack()
			defer wg.Done()
		}()
		wg.Wait()
	}
}

//benchmark four publisher and four consumers 1k payload
func (suite *TestSuite) BenchmarkFourPubFourCon1k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}

//benchmark four publisher and four consumers 4k payload
func (suite *TestSuite) BenchmarkFourPubFourCon4k(c *C) {
	var wg sync.WaitGroup
	payload := randomString(1024 * 4)
	//add first package so consumer doesn't wait for publisher
	suite.queue.Put(payload)
	for i := 0; i < c.N; i++ {
		for j := 0; j < 4; j++ {
			wg.Add(1)
			go func() {
				suite.queue.Put(payload)
				defer wg.Done()
			}()
			consumer, _ := suite.queue.AddConsumer("test" + strconv.Itoa(i) + strconv.Itoa(j))
			wg.Add(1)
			go func(consumer *redismq.Consumer) {
				p, _ := consumer.Get()
				p.Ack()
				defer wg.Done()
			}(consumer)
		}
		wg.Wait()
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess 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.
*/
package throttler

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base"

	"vitess.io/vitess/go/test/endtoend/cluster"

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

var (
	clusterInstance *cluster.LocalProcessCluster
	primaryTablet   *cluster.Vttablet
	replicaTablet   *cluster.Vttablet
	hostname        = "localhost"
	keyspaceName    = "ks"
	cell            = "zone1"
	sqlSchema       = `
	create table t1(
		id bigint,
		value varchar(16),
		primary key(id)
	) Engine=InnoDB;
`

	vSchema = `
	{
    "sharded": true,
    "vindexes": {
      "hash": {
        "type": "hash"
      }
    },
    "tables": {
      "t1": {
        "column_vindexes": [
          {
            "column": "id",
            "name": "hash"
          }
        ]
      }
    }
	}`

	httpClient       = base.SetupHTTPClient(time.Second)
	checkAPIPath     = "throttler/check"
	checkSelfAPIPath = "throttler/check-self"
)

const (
	throttlerInitWait            = 10 * time.Second
	accumulateLagWait            = 2 * time.Second
	throttlerRefreshIntervalWait = 12 * time.Second
	replicationCatchUpWait       = 5 * time.Second
)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		err := clusterInstance.StartTopo()
		if err != nil {
			return 1
		}

		// Set extra tablet args for lock timeout
		clusterInstance.VtTabletExtraArgs = []string{
			"-lock_tables_timeout", "5s",
			"-watch_replication_stream",
			"-enable_replication_reporter",
			"-enable-lag-throttler",
			"-throttle_threshold", "1s",
			"-heartbeat_enable",
			"-heartbeat_interval", "250ms",
		}
		// We do not need semiSync for this test case.
		clusterInstance.EnableSemiSync = false

		// Start keyspace
		keyspace := &cluster.Keyspace{
			Name:      keyspaceName,
			SchemaSQL: sqlSchema,
			VSchema:   vSchema,
		}

		if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil {
			return 1
		}

		// Collect table paths and ports
		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
		for _, tablet := range tablets {
			if tablet.Type == "primary" {
				primaryTablet = tablet
			} else if tablet.Type != "rdonly" {
				replicaTablet = tablet
			}
		}

		return m.Run()
	}()
	os.Exit(exitCode)
}

func throttleCheck(tablet *cluster.Vttablet) (*http.Response, error) {
	return httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", tablet.HTTPPort, checkAPIPath))
}

func throttleCheckSelf(tablet *cluster.Vttablet) (*http.Response, error) {
	return httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", tablet.HTTPPort, checkSelfAPIPath))
}

func TestThrottlerBeforeMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	// Immediately after startup, we expect this response:
	// {"StatusCode":404,"Value":0,"Threshold":0,"Message":"No such metric"}
	{
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusNotFound, resp.StatusCode)
	}
}

func TestThrottlerAfterMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	time.Sleep(throttlerInitWait)
	// By this time metrics will have been collected. We expect no lag, and something like:
	// {"StatusCode":200,"Value":0.282278,"Threshold":1,"Message":""}
	{
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		resp, err := throttleCheckSelf(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		resp, err := throttleCheckSelf(replicaTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
}

func TestLag(t *testing.T) {
	defer cluster.PanicHandler(t)

	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("StopReplication", replicaTablet.Alias)
		assert.NoError(t, err)

		time.Sleep(accumulateLagWait)
		// Lag will have accumulated
		// {"StatusCode":429,"Value":4.864921,"Threshold":1,"Message":"Threshold exceeded"}
		{
			resp, err := throttleCheck(primaryTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusTooManyRequests, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(primaryTablet)
			assert.NoError(t, err)
			// self (on primary) is unaffected by replication lag
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(replicaTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusTooManyRequests, resp.StatusCode)
		}
	}
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", replicaTablet.Alias)
		assert.NoError(t, err)

		time.Sleep(replicationCatchUpWait)
		// Restore
		{
			resp, err := throttleCheck(primaryTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(primaryTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(replicaTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
	}
}

func TestNoReplicas(t *testing.T) {
	defer cluster.PanicHandler(t)
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "RDONLY")
		assert.NoError(t, err)

		time.Sleep(throttlerRefreshIntervalWait)
		// This makes no REPLICA servers available. We expect something like:
		// {"StatusCode":200,"Value":0,"Threshold":1,"Message":""}
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "REPLICA")
		assert.NoError(t, err)

		time.Sleep(throttlerRefreshIntervalWait)
		// Restore valid replica
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
}
<commit_msg>adapt test<commit_after>/*
Copyright 2020 The Vitess 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.
*/
package throttler

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base"

	"vitess.io/vitess/go/test/endtoend/cluster"

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

var (
	clusterInstance *cluster.LocalProcessCluster
	primaryTablet   *cluster.Vttablet
	replicaTablet   *cluster.Vttablet
	hostname        = "localhost"
	keyspaceName    = "ks"
	cell            = "zone1"
	sqlSchema       = `
	create table t1(
		id bigint,
		value varchar(16),
		primary key(id)
	) Engine=InnoDB;
`

	vSchema = `
	{
    "sharded": true,
    "vindexes": {
      "hash": {
        "type": "hash"
      }
    },
    "tables": {
      "t1": {
        "column_vindexes": [
          {
            "column": "id",
            "name": "hash"
          }
        ]
      }
    }
	}`

	httpClient       = base.SetupHTTPClient(time.Second)
	checkAPIPath     = "throttler/check"
	checkSelfAPIPath = "throttler/check-self"
)

const (
	throttlerInitWait            = 10 * time.Second
	accumulateLagWait            = 2 * time.Second
	throttlerRefreshIntervalWait = 12 * time.Second
	replicationCatchUpWait       = 5 * time.Second
)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		err := clusterInstance.StartTopo()
		if err != nil {
			return 1
		}

		// Set extra tablet args for lock timeout
		clusterInstance.VtTabletExtraArgs = []string{
			"-lock_tables_timeout", "5s",
			"-watch_replication_stream",
			"-enable_replication_reporter",
			"-enable-lag-throttler",
			"-throttle_threshold", "1s",
			"-heartbeat_enable",
			"-heartbeat_interval", "250ms",
		}
		// We do not need semiSync for this test case.
		clusterInstance.EnableSemiSync = false

		// Start keyspace
		keyspace := &cluster.Keyspace{
			Name:      keyspaceName,
			SchemaSQL: sqlSchema,
			VSchema:   vSchema,
		}

		if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil {
			return 1
		}

		// Collect table paths and ports
		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
		for _, tablet := range tablets {
			if tablet.Type == "primary" {
				primaryTablet = tablet
			} else if tablet.Type != "rdonly" {
				replicaTablet = tablet
			}
		}

		return m.Run()
	}()
	os.Exit(exitCode)
}

func throttleCheck(tablet *cluster.Vttablet) (*http.Response, error) {
	return httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", tablet.HTTPPort, checkAPIPath))
}

func throttleCheckSelf(tablet *cluster.Vttablet) (*http.Response, error) {
	return httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", tablet.HTTPPort, checkSelfAPIPath))
}

func TestThrottlerBeforeMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	// Immediately after startup, we expect this response:
	// {"StatusCode":404,"Value":0,"Threshold":0,"Message":"No such metric"}
	{
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusNotFound, resp.StatusCode)
	}
}

func TestThrottlerAfterMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	time.Sleep(throttlerInitWait)
	// By this time metrics will have been collected. We expect no lag, and something like:
	// {"StatusCode":200,"Value":0.282278,"Threshold":1,"Message":""}
	{
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		resp, err := throttleCheckSelf(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		resp, err := throttleCheckSelf(replicaTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
}

func TestLag(t *testing.T) {
	defer cluster.PanicHandler(t)

	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("StopReplication", replicaTablet.Alias)
		assert.NoError(t, err)

		time.Sleep(accumulateLagWait)
		// Lag will have accumulated
		// {"StatusCode":429,"Value":4.864921,"Threshold":1,"Message":"Threshold exceeded"}
		{
			resp, err := throttleCheck(primaryTablet)
			assert.NoError(t, err)
			assert.NotEqual(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(primaryTablet)
			assert.NoError(t, err)
			// self (on primary) is unaffected by replication lag
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(replicaTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusTooManyRequests, resp.StatusCode)
		}
	}
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("StartReplication", replicaTablet.Alias)
		assert.NoError(t, err)

		time.Sleep(replicationCatchUpWait)
		// Restore
		{
			resp, err := throttleCheck(primaryTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(primaryTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
		{
			resp, err := throttleCheckSelf(replicaTablet)
			assert.NoError(t, err)
			assert.Equal(t, http.StatusOK, resp.StatusCode)
		}
	}
}

func TestNoReplicas(t *testing.T) {
	defer cluster.PanicHandler(t)
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "RDONLY")
		assert.NoError(t, err)

		time.Sleep(throttlerRefreshIntervalWait)
		// This makes no REPLICA servers available. We expect something like:
		// {"StatusCode":200,"Value":0,"Threshold":1,"Message":""}
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
	{
		err := clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "REPLICA")
		assert.NoError(t, err)

		time.Sleep(throttlerRefreshIntervalWait)
		// Restore valid replica
		resp, err := throttleCheck(primaryTablet)
		assert.NoError(t, err)
		assert.Equal(t, http.StatusOK, resp.StatusCode)
	}
}
<|endoftext|>


<commit_before><commit_msg>wrote half a loader now let's play dice<commit_after><|endoftext|>


<commit_before>package git

import (
	"errors"
	"time"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
)

type PruneHandler func(unreferencedObjectHash plumbing.Hash) error
type PruneOptions struct {
	// OnlyObjectsOlderThan if set to non-zero value
	// selects only objects older than the time provided.
	OnlyObjectsOlderThan time.Time
	// Handler is called on matching objects
	Handler PruneHandler
}

var ErrLooseObjectsNotSupported = errors.New("Loose objects not supported")

// DeleteObject deletes an object from a repository.
// The type conveniently matches PruneHandler.
func (r *Repository) DeleteObject(hash plumbing.Hash) error {
	los, ok := r.Storer.(storer.LooseObjectStorer)
	if !ok {
		return ErrLooseObjectsNotSupported
	}

	return los.DeleteLooseObject(hash)
}

func (r *Repository) Prune(opt PruneOptions) error {
	los, ok := r.Storer.(storer.LooseObjectStorer)
	if !ok {
		return ErrLooseObjectsNotSupported
	}

	pw := newObjectWalker(r.Storer)
	err := pw.walkAllRefs()
	if err != nil {
		return err
	}
	// Now walk all (loose) objects in storage.
	return los.ForEachObjectHash(func(hash plumbing.Hash) error {
		// Get out if we have seen this object.
		if pw.isSeen(hash) {
			return nil
		}
		// Otherwise it is a candidate for pruning.
		// Check out for too new objects next.
		if opt.OnlyObjectsOlderThan != (time.Time{}) {
			// Errors here are non-fatal. The object may be e.g. packed.
			// Or concurrently deleted. Skip such objects.
			t, err := los.LooseObjectTime(hash)
			if err != nil {
				return nil
			}
			// Skip too new objects.
			if !t.Before(opt.OnlyObjectsOlderThan) {
				return nil
			}
		}
		return opt.Handler(hash)
	})
}
<commit_msg>use time.IsZero in Prune<commit_after>package git

import (
	"errors"
	"time"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
)

type PruneHandler func(unreferencedObjectHash plumbing.Hash) error
type PruneOptions struct {
	// OnlyObjectsOlderThan if set to non-zero value
	// selects only objects older than the time provided.
	OnlyObjectsOlderThan time.Time
	// Handler is called on matching objects
	Handler PruneHandler
}

var ErrLooseObjectsNotSupported = errors.New("Loose objects not supported")

// DeleteObject deletes an object from a repository.
// The type conveniently matches PruneHandler.
func (r *Repository) DeleteObject(hash plumbing.Hash) error {
	los, ok := r.Storer.(storer.LooseObjectStorer)
	if !ok {
		return ErrLooseObjectsNotSupported
	}

	return los.DeleteLooseObject(hash)
}

func (r *Repository) Prune(opt PruneOptions) error {
	los, ok := r.Storer.(storer.LooseObjectStorer)
	if !ok {
		return ErrLooseObjectsNotSupported
	}

	pw := newObjectWalker(r.Storer)
	err := pw.walkAllRefs()
	if err != nil {
		return err
	}
	// Now walk all (loose) objects in storage.
	return los.ForEachObjectHash(func(hash plumbing.Hash) error {
		// Get out if we have seen this object.
		if pw.isSeen(hash) {
			return nil
		}
		// Otherwise it is a candidate for pruning.
		// Check out for too new objects next.
		if !opt.OnlyObjectsOlderThan.IsZero() {
			// Errors here are non-fatal. The object may be e.g. packed.
			// Or concurrently deleted. Skip such objects.
			t, err := los.LooseObjectTime(hash)
			if err != nil {
				return nil
			}
			// Skip too new objects.
			if !t.Before(opt.OnlyObjectsOlderThan) {
				return nil
			}
		}
		return opt.Handler(hash)
	})
}
<|endoftext|>


<commit_before>package couchdb

import (
	"reflect"
	"regexp"
	"testing"
)

var client, _ = NewClient("http://127.0.0.1:5984/")

func TestInfo(t *testing.T) {
	info, err := client.Info()
	if err != nil {
		t.Fatal(err)
	}
	if info.Couchdb != "Welcome" {
		t.Error("Couchdb error")
	}
}

func TestLog(t *testing.T) {
	log, err := client.Log()
	if err != nil {
		t.Fatal(err)
	}
	valid := regexp.MustCompile("[info]")
	if valid.MatchString(log) == false {
		t.Error("invalid log")
	}
}

func TestActiveTasks(t *testing.T) {
	res, err := client.ActiveTasks()
	if err != nil {
		t.Fatal(err)
	}
	out := make([]Task, 0)
	if reflect.DeepEqual(out, res) == false {
		t.Error("active tasks should be an empty array")
	}
}

func TestAll(t *testing.T) {
	res, err := client.All()
	if err != nil {
		t.Fatal(err)
	}
	if res[0] != "_replicator" || res[1] != "_users" {
		t.Error("slice error")
	}
}

func TestGet(t *testing.T) {
	info, err := client.Get("_users")
	if err != nil {
		t.Fatal(err)
	}
	if info.DbName != "_users" {
		t.Error("DbName error")
	}
	if info.CompactRunning != false {
		t.Error("CompactRunning error")
	}
}

func TestCreate(t *testing.T) {
	status, err := client.Create("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if status.Ok != true {
		t.Error("status error")
	}
}

func TestCreateFail(t *testing.T) {
	res, err := client.Create("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == true {
		t.Fatal("should not create duplicate database")
	}
}

func TestCreateUser(t *testing.T) {
	user := NewUser("john", "password", []string{})
	res, err := client.CreateUser(user)
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Id != "org.couchdb.user:john" {
		t.Error("create user error")
	}
}

func TestCreateSession(t *testing.T) {
	res, err := client.CreateSession("john", "password")
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Name != "john" {
		t.Error("create session error")
	}
}

func TestGetSession(t *testing.T) {
	session, err := client.GetSession()
	if err != nil {
		t.Fatal(err)
	}
	if session.Ok == false || session.UserContext.Name != "john" {
		t.Error("get session error")
	}
}

func TestDeleteSession(t *testing.T) {
	res, err := client.DeleteSession()
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false {
		t.Error("delete session error")
	}
}

func TestGetUser(t *testing.T) {
	user, err := client.GetUser("john")
	if err != nil {
		t.Fatal(err)
	}
	if user.Name != "john" || user.Type != "user" || user.Iterations != 10 {
		t.Error("get user error")
	}
}

func TestDeleteUser(t *testing.T) {
	user, err := client.GetUser("john")
	if err != nil {
		t.Fatal(err)
	}
	res, err := client.DeleteUser(*user)
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Id != "org.couchdb.user:john" {
		t.Error("delete user error")
	}
}

func TestGetSessionAdmin(t *testing.T) {
	session, err := client.GetSession()
	if err != nil {
		t.Fatal(err)
	}
	if session.Ok == false {
		t.Error("session response is false")
	}
	roles := []string{"_admin"}
	if reflect.DeepEqual(roles, session.UserContext.Roles) == false {
		t.Error("session roles are wrong")
	}
}

func TestDelete(t *testing.T) {
	status, err := client.Delete("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if status.Ok != true {
		t.Error("status error")
	}
}

func TestDeleteFail(t *testing.T) {
	res, err := client.Delete("dummy")
	if err != nil {
		t.Fatal("should not delete non existing database")
	}
	if res.Ok == true {
		t.Fatal("should not delete non existing database")
	}
}

func TestUse(t *testing.T) {
	db := client.Use("_users")
	if db.Url != "http://127.0.0.1:5984/_users/" {
		t.Error("use error")
	}
}
<commit_msg>log error instead custom error message<commit_after>package couchdb

import (
	"reflect"
	"regexp"
	"testing"
)

var client, _ = NewClient("http://127.0.0.1:5984/")

func TestInfo(t *testing.T) {
	info, err := client.Info()
	if err != nil {
		t.Fatal(err)
	}
	if info.Couchdb != "Welcome" {
		t.Error("Couchdb error")
	}
}

func TestLog(t *testing.T) {
	log, err := client.Log()
	if err != nil {
		t.Fatal(err)
	}
	valid := regexp.MustCompile("[info]")
	if valid.MatchString(log) == false {
		t.Error("invalid log")
	}
}

func TestActiveTasks(t *testing.T) {
	res, err := client.ActiveTasks()
	if err != nil {
		t.Fatal(err)
	}
	out := make([]Task, 0)
	if reflect.DeepEqual(out, res) == false {
		t.Error("active tasks should be an empty array")
	}
}

func TestAll(t *testing.T) {
	res, err := client.All()
	if err != nil {
		t.Fatal(err)
	}
	if res[0] != "_replicator" || res[1] != "_users" {
		t.Error("slice error")
	}
}

func TestGet(t *testing.T) {
	info, err := client.Get("_users")
	if err != nil {
		t.Fatal(err)
	}
	if info.DbName != "_users" {
		t.Error("DbName error")
	}
	if info.CompactRunning != false {
		t.Error("CompactRunning error")
	}
}

func TestCreate(t *testing.T) {
	status, err := client.Create("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if status.Ok != true {
		t.Error("status error")
	}
}

func TestCreateFail(t *testing.T) {
	res, err := client.Create("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == true {
		t.Fatal("should not create duplicate database")
	}
}

func TestCreateUser(t *testing.T) {
	user := NewUser("john", "password", []string{})
	res, err := client.CreateUser(user)
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Id != "org.couchdb.user:john" {
		t.Error("create user error")
	}
}

func TestCreateSession(t *testing.T) {
	res, err := client.CreateSession("john", "password")
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Name != "john" {
		t.Error("create session error")
	}
}

func TestGetSession(t *testing.T) {
	session, err := client.GetSession()
	if err != nil {
		t.Fatal(err)
	}
	if session.Ok == false || session.UserContext.Name != "john" {
		t.Error("get session error")
	}
}

func TestDeleteSession(t *testing.T) {
	res, err := client.DeleteSession()
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false {
		t.Error("delete session error")
	}
}

func TestGetUser(t *testing.T) {
	user, err := client.GetUser("john")
	if err != nil {
		t.Fatal(err)
	}
	if user.Name != "john" || user.Type != "user" || user.Iterations != 10 {
		t.Error("get user error")
	}
}

func TestDeleteUser(t *testing.T) {
	user, err := client.GetUser("john")
	if err != nil {
		t.Fatal(err)
	}
	res, err := client.DeleteUser(*user)
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == false || res.Id != "org.couchdb.user:john" {
		t.Error("delete user error")
	}
}

func TestGetSessionAdmin(t *testing.T) {
	session, err := client.GetSession()
	if err != nil {
		t.Fatal(err)
	}
	if session.Ok == false {
		t.Error("session response is false")
	}
	roles := []string{"_admin"}
	if reflect.DeepEqual(roles, session.UserContext.Roles) == false {
		t.Error("session roles are wrong")
	}
}

func TestDelete(t *testing.T) {
	status, err := client.Delete("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if status.Ok != true {
		t.Error("status error")
	}
}

func TestDeleteFail(t *testing.T) {
	res, err := client.Delete("dummy")
	if err != nil {
		t.Fatal(err)
	}
	if res.Ok == true {
		t.Fatal("should not delete non existing database")
	}
}

func TestUse(t *testing.T) {
	db := client.Use("_users")
	if db.Url != "http://127.0.0.1:5984/_users/" {
		t.Error("use error")
	}
}
<|endoftext|>


<commit_before>// Package cloudatgost is a CloudAtCost API wrapper written in Go.
package cloudatgost

import (
	"encoding/json"
	"net/http"
)

// A Client represents a CloudAtCost API client. It does HTTP requests
// and returns properly populated structures.
type Client struct {
	client *http.Client
	BaseURL string
	Login string
	Token string
}

// NewClient instantiates and returns a new API client. This function
// accepts an email and a token as its parameters, as well as an optional
// HTTP client. If httpClient is nil, the function creates a new
// http.DefaultClient and assigns it to the newly created client.
func NewClient(email string, token string, httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	baseURL := "https://panel.cloudatcost.com/api/v1/"

	c := &Client{
		Login: email,
		Token: token,
		client: httpClient,
		BaseURL: baseURL,
	}

	return c
}

// Do is a shorthand for HTTP requests in the cloudatgost client domain.
// The function takes an HTTP request, sends it and returns the API response,
// decoded to the v, usually passed passed by reference.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return resp, err
	}

	defer resp.Body.Close()

	if v != nil {
		json.NewDecoder(resp.Body).Decode(v)
	}

	return resp, err
}
<commit_msg>cloudatgost go package corrections<commit_after>// Package cloudatgost is a Go wrapper for CloudAtCost API.
package cloudatgost

import (
	"encoding/json"
	"net/http"
)

// A Client represents a CloudAtCost API client. It does HTTP requests
// and returns properly populated structures.
type Client struct {
	client *http.Client
	BaseURL string
	Login string
	Token string
}

// NewClient instantiates and returns a new API client. This function
// accepts an email and a token as its parameters, as well as an optional
// HTTP client. If httpClient is nil, the function creates a new
// http.DefaultClient and assigns it to the newly created client.
func NewClient(email string, token string, httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	baseURL := "https://panel.cloudatcost.com/api/v1/"

	c := &Client{
		Login: email,
		Token: token,
		client: httpClient,
		BaseURL: baseURL,
	}

	return c
}

// Do is a shorthand for HTTP requests in the cloudatgost client domain.
// The function takes an HTTP request, sends it and returns the API response,
// decoded to the v, usually passed passed by reference.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return resp, err
	}

	defer resp.Body.Close()

	if v != nil {
		json.NewDecoder(resp.Body).Decode(v)
	}

	return resp, err
}
<|endoftext|>


<commit_before>package disgo

import "strconv"

func (s *Guild) BuildChannel(name string) *ChannelBuilder {
	return s.session.BuildChannel(s.internal.ID, name)
}

func (s *Guild) Role(id Snowflake) (*Role, bool) {
	for _, role := range s.internal.Roles {
		if role.internal.ID == id {
			return role, true
		}
	}

	return nil, false
}

func (s *Session) AddGuildMemberRole(guildID, userID, roleID Snowflake) error {
	return s.doHttpPut(EndPointGuildMemberRoles(guildID, userID, roleID), nil)
}

func (s *Session) RemoveGuildMemberRole(guildID, userID, roleID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMemberRoles(guildID, userID, roleID), nil)
}

func (s *Guild) GetRoleUsers(roleID Snowflake) []*User {
	users := make([]*User, 0)

	for _, user := range s.internal.Members {
		if SnowflakeInSlice(roleID, user.internal.RolesIDs) {
			users = append(users, user.internal.User)
		}
	}

	return users
}

func (s *Guild) GetUserRoles(userID Snowflake) ([]Snowflake, bool) {
	membership, exists := s.GetUserMembership(userID)
	if exists {
		return membership.RolesIDs(), true
	}

	return nil, false
}

func (s *Guild) GetUserMembership(userID Snowflake) (*GuildMember, bool) {
	for _, membership := range s.internal.Members {
		if membership.User().ID() == userID {
			return membership, true
		}
	}

	return nil, false
}

func (s *Guild) GetUserColor(userID Snowflake) (int, bool) {
	roles, inGuild := s.GetUserRoles(userID)
	if !inGuild {
		return 0, false
	}

	var (
		highest *Role
	)
	for _, role := range s.internal.Roles {
		if SnowflakeInSlice(role.internal.ID, roles) && (highest == nil || role.internal.Position > highest.internal.Position) && role.internal.Color != 0 {
			highest = role
		}
	}

	if highest != nil {
		return highest.internal.Color, true
	}

	return 0, false
}

func (s *Session) KickUser(guildID, userID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMember(guildID, userID), nil)
}

func (s *Guild) KickUser(userID Snowflake) error {
	return s.session.KickUser(s.internal.ID, userID)
}

func (s *Session) BanUser(guildID, userID Snowflake, deleteMessageDays int) error {
	endPoint := EndPointGuildMemberBan(guildID, userID)
	endPoint.Url += "?delete-message-days=" + strconv.FormatInt(int64(deleteMessageDays), 10)

	return s.doHttpPut(endPoint, nil)
}

func (s *Guild) BanUser(userID Snowflake, deleteMessageDays int) error {
	return s.session.BanUser(s.internal.ID, userID, deleteMessageDays)
}

func (s *Session) UnbanUser(guildID, userID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMemberBan(guildID, userID), nil)
}

func (s *Guild) UnbanUser(userID Snowflake) error {
	return s.session.UnbanUser(s.internal.ID, userID)
}
<commit_msg>Added nick member support<commit_after>package disgo

import "strconv"

func (s *Guild) BuildChannel(name string) *ChannelBuilder {
	return s.session.BuildChannel(s.internal.ID, name)
}

func (s *Guild) Role(id Snowflake) (*Role, bool) {
	for _, role := range s.internal.Roles {
		if role.internal.ID == id {
			return role, true
		}
	}

	return nil, false
}

func (s *Session) AddGuildMemberRole(guildID, userID, roleID Snowflake) error {
	return s.doHttpPut(EndPointGuildMemberRoles(guildID, userID, roleID), nil)
}

func (s *Session) RemoveGuildMemberRole(guildID, userID, roleID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMemberRoles(guildID, userID, roleID), nil)
}

func (s *Guild) GetRoleUsers(roleID Snowflake) []*User {
	users := make([]*User, 0)

	for _, user := range s.internal.Members {
		if SnowflakeInSlice(roleID, user.internal.RolesIDs) {
			users = append(users, user.internal.User)
		}
	}

	return users
}

func (s *Guild) GetUserRoles(userID Snowflake) ([]Snowflake, bool) {
	membership, exists := s.GetUserMembership(userID)
	if exists {
		return membership.RolesIDs(), true
	}

	return nil, false
}

func (s *Guild) GetUserMembership(userID Snowflake) (*GuildMember, bool) {
	for _, membership := range s.internal.Members {
		if membership.User().ID() == userID {
			return membership, true
		}
	}

	return nil, false
}

func (s *Guild) GetUserColor(userID Snowflake) (int, bool) {
	roles, inGuild := s.GetUserRoles(userID)
	if !inGuild {
		return 0, false
	}

	var (
		highest *Role
	)
	for _, role := range s.internal.Roles {
		if SnowflakeInSlice(role.internal.ID, roles) && (highest == nil || role.internal.Position > highest.internal.Position) && role.internal.Color != 0 {
			highest = role
		}
	}

	if highest != nil {
		return highest.internal.Color, true
	}

	return 0, false
}

type updateGuildMember struct {
	Nick      string       `json:"nick,omitempty"`
	Roles     *[]Snowflake `json:"roles,omitempty"`
	Mute      *bool        `json:"mute,omitempty"`
	Deaf      *bool        `json:"deaf,omitempty"`
	ChannelID *Snowflake   `json:"channel_id,omitempty"`
}

func (s *Session) SetUserNick(guildID, userID Snowflake, nick string) error {
	return s.doHttpPatch(EndPointGuildMember(guildID, userID), updateGuildMember{Nick: nick}, nil)
}

func (s *Session) KickUser(guildID, userID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMember(guildID, userID), nil)
}

func (s *Guild) KickUser(userID Snowflake) error {
	return s.session.KickUser(s.internal.ID, userID)
}

func (s *Session) BanUser(guildID, userID Snowflake, deleteMessageDays int) error {
	endPoint := EndPointGuildMemberBan(guildID, userID)
	endPoint.Url += "?delete-message-days=" + strconv.FormatInt(int64(deleteMessageDays), 10)

	return s.doHttpPut(endPoint, nil)
}

func (s *Guild) BanUser(userID Snowflake, deleteMessageDays int) error {
	return s.session.BanUser(s.internal.ID, userID, deleteMessageDays)
}

func (s *Session) UnbanUser(guildID, userID Snowflake) error {
	return s.doHttpDelete(EndPointGuildMemberBan(guildID, userID), nil)
}

func (s *Guild) UnbanUser(userID Snowflake) error {
	return s.session.UnbanUser(s.internal.ID, userID)
}
<|endoftext|>


<commit_before>package configstore

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"koding/kites/config"
	"koding/kites/kloud/utils/object"
	"koding/klient/storage"
	"koding/tools/util"

	"github.com/boltdb/bolt"
)

var defaultCacheOpts = &config.CacheOptions{
	File: filepath.Join(config.KodingHome(), "konfig.bolt"),
	BoltDB: &bolt.Options{
		Timeout: 5 * time.Second,
	},
	Bucket: []byte("konfig"),
}

var DefaultClient = &Client{}

type Client struct {
	CacheOpts *config.CacheOptions
	Home      string       // uses config.KodingHome by default
	Owner     *config.User // uses config.CurrentUser by default

	once sync.Once // for c.init()
}

type usedKonfig struct {
	ID string `json:"id"`
}

func (c *Client) List() (k config.Konfigs) {
	c.init()

	_ = c.commit(func(cache *config.Cache) error {
		return cache.GetValue("konfigs", &k)
	})

	return k
}

func (c *Client) Read(e *config.Environments) *config.Konfig {
	c.init()

	k := config.NewKonfig(e)

	_ = c.commit(func(cache *config.Cache) error {
		var mixin config.Konfig

		if err := cache.GetValue("konfig", &mixin); err == nil {
			if err := mergeIn(k, &mixin); err != nil {
				return err
			}
		}

		return nil
	})

	return k
}

func (c *Client) Use(k *config.Konfig) error {
	c.init()

	if err := k.Valid(); err != nil {
		return err
	}

	return c.commit(makeUseFunc(k))
}

func (c *Client) Used() (*config.Konfig, error) {
	c.init()

	var konfig config.Konfig

	if err := c.commit(makeUsedFunc(&konfig)); err != nil {
		return nil, err
	}

	return &konfig, nil
}

func (c *Client) CacheOptions(app string) *config.CacheOptions {
	c.init()

	oldFile := filepath.Join(c.home(), app+".bolt")
	file := c.boltFile(app)

	if _, err := os.Stat(file); oldFile != file && os.IsNotExist(err) {
		if _, err := os.Stat(oldFile); err == nil {
			// Bolt file exists in old location but not in the new one,
			// most likely we just migrated from old config version.
			if err := os.Rename(oldFile, file); err != nil {
				// If it's not possible to move - symlink.
				if e := os.Symlink(oldFile, file); e != nil {
					log.Printf("unable to move old bolt file to new location %q: %s, %s", file, err, e)
				}
			}
		}
	}

	dir := filepath.Dir(file)

	// Best-effort attempts, ignore errors.
	_ = os.MkdirAll(dir, 0755)
	_ = util.Chown(dir, c.owner().User)

	return &config.CacheOptions{
		File: file,
		BoltDB: &bolt.Options{
			Timeout: 5 * time.Second,
		},
		Bucket: []byte(app),
	}
}

func (c *Client) Set(key, value string) error {
	return c.commit(func(cache *config.Cache) error {
		var used usedKonfig
		var konfigs = make(config.Konfigs)

		if err := cache.GetValue("konfigs.used", &used); err != nil {
			return err
		}

		if err := cache.GetValue("konfigs", &konfigs); err != nil {
			return err
		}

		k, ok := konfigs[used.ID]
		if !ok {
			return storage.ErrKeyNotFound
		}

		if err := setKonfig(k, key, value); err != nil {
			return fmt.Errorf("failed to update %s=%s: %s", key, value, err)
		}

		return cache.SetValue("konfigs", konfigs)
	})
}

func (c *Client) init() {
	c.once.Do(c.initClient)
}

func (c *Client) initClient() {
	// TODO(rjeczalik): various migrations are perform in the init method
	// to ensure old kd / klients that has old boltdb databases
	// continue to work. When we're sure it's no longer needed, this
	// code should be removed.
	_ = c.commit(func(cache *config.Cache) error {
		return nonil(
			// Best-effort attempt to ensure data in klient.bolt is consistent.
			// Ignore any error, as there's no recovery from corrupted
			// configuration, other than reinstalling kd / klient.
			//
			// This migration must be executed before kite.key one.
			migrateKonfigBolt(cache),

			// Best-effort attemp to ensure /etc/kite/kite.key is stored
			// in ~/.config/koding/konfig.bolt, so it is possible to
			// use kd / konfig with koding deployments that sign with
			// different kontrol keys, e.g. production <-> sandbox or
			// production <-> self-hosted opensource version.
			migrateKiteKey(cache),
		)
	})
}

func (c *Client) boltFile(app string) string {
	if used, err := c.Used(); err == nil {
		return filepath.Join(config.KodingHome(), app+"."+used.ID()+".bolt")
	}
	return filepath.Join(config.KodingHome(), app+".bolt")
}

func (c *Client) cacheOpts() *config.CacheOptions {
	if c.CacheOpts != nil {
		return c.CacheOpts
	}
	return defaultCacheOpts
}

func (c *Client) commit(fn func(*config.Cache) error) error {
	cache := config.NewCache(c.cacheOpts())
	return nonil(fn(cache), cache.Close())
}

func (c *Client) home() string {
	if c.Home != "" {
		return c.Home
	}
	return config.KodingHome()
}

func (c *Client) owner() *config.User {
	if c.Owner != nil {
		return c.Owner
	}
	return config.CurrentUser
}

func makeUsedFunc(konfig *config.Konfig) func(cache *config.Cache) error {
	return func(cache *config.Cache) error {
		var used usedKonfig

		if err := cache.GetValue("konfigs.used", &used); err != nil {
			return err
		}

		var konfigs config.Konfigs

		if err := cache.GetValue("konfigs", &konfigs); err != nil {
			return err
		}

		if k, ok := konfigs[used.ID]; ok {
			*konfig = *k
			return nil
		}

		return errors.New("config not found - use one that exists")
	}
}

func makeUseFunc(konfig *config.Konfig) func(cache *config.Cache) error {
	return func(cache *config.Cache) error {
		konfigs := make(config.Konfigs)

		if err := cache.GetValue("konfigs", &konfigs); isFatal(err) {
			return err
		}

		konfigs[konfig.ID()] = konfig

		return cache.SetValue("konfigs", konfigs)
	}
}

func migrateKonfigBolt(cache *config.Cache) error {
	var used usedKonfig
	var oldKonfig config.Konfig
	var konfigs = make(config.Konfigs)

	if err := cache.GetValue("konfig", &oldKonfig); isFatal(err) {
		return err
	}

	if err := cache.GetValue("konfigs", &konfigs); isFatal(err) {
		return err
	}

	if err := cache.GetValue("konfigs.used", &used); isFatal(err) {
		return err
	}

	// If old konfig exists, try to migrate it over to konfigs.
	if oldKonfig.Valid() == nil {
		id := oldKonfig.ID()

		if _, ok := konfigs[id]; !ok {
			konfigs[id] = &oldKonfig

			_ = cache.SetValue("konfigs", konfigs)
		}
	}

	// If no konfig is in use (e.g. we just migrated one),
	// try to set to the default one.
	if used.ID == "" && len(konfigs) == 1 {
		for id, konfig := range konfigs {
			if konfig.Valid() == nil {
				_ = cache.SetValue("konfigs.used", &usedKonfig{ID: id})
			}
			break
		}
	}

	return nil
}

func migrateKiteKey(cache *config.Cache) error {
	var konfig config.Konfig

	if err := makeUsedFunc(&konfig)(cache); err != nil {
		return err
	}

	// KiteKey already exists in the DB - we don't care
	// whether it's our one or user overriden it explictely
	// as long as it's there.
	if konfig.KiteKey != "" {
		return nil
	}

	defaultKitekey := config.NewKonfig(&config.Environments{Env: konfig.Environment}).KiteKeyFile
	kitekey := konfig.KiteKeyFile

	if kitekey == "" {
		kitekey = defaultKitekey
	}

	if _, err := os.Stat(kitekey); err != nil {
		// Either no access to the file or it does not exist,
		// in either case nothing to do here.
		return nil
	}

	p, err := ioutil.ReadFile(kitekey)
	if err != nil {
		return err
	}

	if konfig.KiteKeyFile == defaultKitekey {
		konfig.KiteKeyFile = ""
	}

	konfig.KiteKey = string(p)

	return makeUseFunc(&konfig)(cache)
}

func isFatal(err error) bool {
	return err != nil && err != storage.ErrKeyNotFound
}

func mergeIn(kfg, mixin *config.Konfig) error {
	p, err := json.Marshal(object.Inline(mixin, kfg))
	if err != nil {
		return err
	}

	return json.Unmarshal(p, kfg)
}

func setFlatKeyValue(m map[string]interface{}, key, value string) error {
	keys := strings.Split(key, ".")
	it := m
	last := len(keys) - 1

	for _, key := range keys[:last] {
		switch v := it[key].(type) {
		case map[string]interface{}:
			it = v
		case nil:
			newV := make(map[string]interface{})
			it[key] = newV
			it = newV
		default:
			return errors.New("key is not an object")
		}
	}

	if value == "" {
		delete(it, keys[last])
	} else {
		it[keys[last]] = value
	}

	return nil
}

func setKonfig(cfg *config.Konfig, key, value string) error {
	m := make(map[string]interface{})

	p, err := json.Marshal(cfg)
	if err != nil {
		return err
	}

	if err := json.Unmarshal(p, &m); err != nil {
		return err
	}

	if err := setFlatKeyValue(m, key, value); err != nil {
		return err
	}

	if p, err = json.Marshal(m); err != nil {
		return err
	}

	if value == "" {
		*cfg = config.Konfig{}
	}

	return json.Unmarshal(p, cfg)
}

func nonil(err ...error) error {
	for _, e := range err {
		if e != nil {
			return e
		}
	}
	return nil
}

func CacheOptions(app string) *config.CacheOptions { return DefaultClient.CacheOptions(app) }
func List() config.Konfigs                         { return DefaultClient.List() }
func Read(e *config.Environments) *config.Konfig   { return DefaultClient.Read(e) }
func Set(key, value string) error                  { return DefaultClient.Set(key, value) }
func Use(k *config.Konfig) error                   { return DefaultClient.Use(k) }
func Used() (*config.Konfig, error)                { return DefaultClient.Used() }
<commit_msg>config/configstore: fix setting used configuration<commit_after>package configstore

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"koding/kites/config"
	"koding/kites/kloud/utils/object"
	"koding/klient/storage"
	"koding/tools/util"

	"github.com/boltdb/bolt"
)

var defaultCacheOpts = &config.CacheOptions{
	File: filepath.Join(config.KodingHome(), "konfig.bolt"),
	BoltDB: &bolt.Options{
		Timeout: 5 * time.Second,
	},
	Bucket: []byte("konfig"),
}

var DefaultClient = &Client{}

type Client struct {
	CacheOpts *config.CacheOptions
	Home      string       // uses config.KodingHome by default
	Owner     *config.User // uses config.CurrentUser by default

	once sync.Once // for c.init()
}

type usedKonfig struct {
	ID string `json:"id"`
}

func (c *Client) List() (k config.Konfigs) {
	c.init()

	_ = c.commit(func(cache *config.Cache) error {
		return cache.GetValue("konfigs", &k)
	})

	return k
}

func (c *Client) Read(e *config.Environments) *config.Konfig {
	c.init()

	k := config.NewKonfig(e)

	_ = c.commit(func(cache *config.Cache) error {
		var mixin config.Konfig

		if err := cache.GetValue("konfig", &mixin); err == nil {
			if err := mergeIn(k, &mixin); err != nil {
				return err
			}
		}

		return nil
	})

	return k
}

func (c *Client) Use(k *config.Konfig) error {
	c.init()

	if err := k.Valid(); err != nil {
		return err
	}

	return c.commit(makeUseFunc(k))
}

func (c *Client) Used() (*config.Konfig, error) {
	c.init()

	var konfig config.Konfig

	if err := c.commit(makeUsedFunc(&konfig)); err != nil {
		return nil, err
	}

	return &konfig, nil
}

func (c *Client) CacheOptions(app string) *config.CacheOptions {
	c.init()

	oldFile := filepath.Join(c.home(), app+".bolt")
	file := c.boltFile(app)

	if _, err := os.Stat(file); oldFile != file && os.IsNotExist(err) {
		if _, err := os.Stat(oldFile); err == nil {
			// Bolt file exists in old location but not in the new one,
			// most likely we just migrated from old config version.
			if err := os.Rename(oldFile, file); err != nil {
				// If it's not possible to move - symlink.
				if e := os.Symlink(oldFile, file); e != nil {
					log.Printf("unable to move old bolt file to new location %q: %s, %s", file, err, e)
				}
			}
		}
	}

	dir := filepath.Dir(file)

	// Best-effort attempts, ignore errors.
	_ = os.MkdirAll(dir, 0755)
	_ = util.Chown(dir, c.owner().User)

	return &config.CacheOptions{
		File: file,
		BoltDB: &bolt.Options{
			Timeout: 5 * time.Second,
		},
		Bucket: []byte(app),
	}
}

func (c *Client) Set(key, value string) error {
	return c.commit(func(cache *config.Cache) error {
		var used usedKonfig
		var konfigs = make(config.Konfigs)

		if err := cache.GetValue("konfigs.used", &used); err != nil {
			return err
		}

		if err := cache.GetValue("konfigs", &konfigs); err != nil {
			return err
		}

		k, ok := konfigs[used.ID]
		if !ok {
			return storage.ErrKeyNotFound
		}

		if err := setKonfig(k, key, value); err != nil {
			return fmt.Errorf("failed to update %s=%s: %s", key, value, err)
		}

		return cache.SetValue("konfigs", konfigs)
	})
}

func (c *Client) init() {
	c.once.Do(c.initClient)
}

func (c *Client) initClient() {
	// TODO(rjeczalik): various migrations are perform in the init method
	// to ensure old kd / klients that has old boltdb databases
	// continue to work. When we're sure it's no longer needed, this
	// code should be removed.
	_ = c.commit(func(cache *config.Cache) error {
		return nonil(
			// Best-effort attempt to ensure data in klient.bolt is consistent.
			// Ignore any error, as there's no recovery from corrupted
			// configuration, other than reinstalling kd / klient.
			//
			// This migration must be executed before kite.key one.
			migrateKonfigBolt(cache),

			// Best-effort attemp to ensure /etc/kite/kite.key is stored
			// in ~/.config/koding/konfig.bolt, so it is possible to
			// use kd / konfig with koding deployments that sign with
			// different kontrol keys, e.g. production <-> sandbox or
			// production <-> self-hosted opensource version.
			migrateKiteKey(cache),
		)
	})
}

func (c *Client) boltFile(app string) string {
	if used, err := c.Used(); err == nil {
		return filepath.Join(config.KodingHome(), app+"."+used.ID()+".bolt")
	}
	return filepath.Join(config.KodingHome(), app+".bolt")
}

func (c *Client) cacheOpts() *config.CacheOptions {
	if c.CacheOpts != nil {
		return c.CacheOpts
	}
	return defaultCacheOpts
}

func (c *Client) commit(fn func(*config.Cache) error) error {
	cache := config.NewCache(c.cacheOpts())
	return nonil(fn(cache), cache.Close())
}

func (c *Client) home() string {
	if c.Home != "" {
		return c.Home
	}
	return config.KodingHome()
}

func (c *Client) owner() *config.User {
	if c.Owner != nil {
		return c.Owner
	}
	return config.CurrentUser
}

func makeUsedFunc(konfig *config.Konfig) func(cache *config.Cache) error {
	return func(cache *config.Cache) error {
		var used usedKonfig

		if err := cache.GetValue("konfigs.used", &used); err != nil {
			return err
		}

		var konfigs config.Konfigs

		if err := cache.GetValue("konfigs", &konfigs); err != nil {
			return err
		}

		if k, ok := konfigs[used.ID]; ok {
			*konfig = *k
			return nil
		}

		return errors.New("config not found - use one that exists")
	}
}

func makeUseFunc(konfig *config.Konfig) func(cache *config.Cache) error {
	return func(cache *config.Cache) error {
		konfigs := make(config.Konfigs)

		if err := cache.GetValue("konfigs", &konfigs); isFatal(err) {
			return err
		}

		id := konfig.ID()

		konfigs[id] = konfig

		return nonil(
			cache.SetValue("konfigs", konfigs),
			cache.SetValue("konfigs.used", &usedKonfig{ID: id}),
		)
	}
}

func migrateKonfigBolt(cache *config.Cache) error {
	var used usedKonfig
	var oldKonfig config.Konfig
	var konfigs = make(config.Konfigs)

	if err := cache.GetValue("konfig", &oldKonfig); isFatal(err) {
		return err
	}

	if err := cache.GetValue("konfigs", &konfigs); isFatal(err) {
		return err
	}

	if err := cache.GetValue("konfigs.used", &used); isFatal(err) {
		return err
	}

	// If old konfig exists, try to migrate it over to konfigs.
	if oldKonfig.Valid() == nil {
		id := oldKonfig.ID()

		if _, ok := konfigs[id]; !ok {
			konfigs[id] = &oldKonfig

			_ = cache.SetValue("konfigs", konfigs)
		}
	}

	// If no konfig is in use (e.g. we just migrated one),
	// try to set to the default one.
	if used.ID == "" && len(konfigs) == 1 {
		for id, konfig := range konfigs {
			if konfig.Valid() == nil {
				_ = cache.SetValue("konfigs.used", &usedKonfig{ID: id})
			}
			break
		}
	}

	return nil
}

func migrateKiteKey(cache *config.Cache) error {
	var konfig config.Konfig

	if err := makeUsedFunc(&konfig)(cache); err != nil {
		return err
	}

	// KiteKey already exists in the DB - we don't care
	// whether it's our one or user overriden it explictely
	// as long as it's there.
	if konfig.KiteKey != "" {
		return nil
	}

	defaultKitekey := config.NewKonfig(&config.Environments{Env: konfig.Environment}).KiteKeyFile
	kitekey := konfig.KiteKeyFile

	if kitekey == "" {
		kitekey = defaultKitekey
	}

	if _, err := os.Stat(kitekey); err != nil {
		// Either no access to the file or it does not exist,
		// in either case nothing to do here.
		return nil
	}

	p, err := ioutil.ReadFile(kitekey)
	if err != nil {
		return err
	}

	if konfig.KiteKeyFile == defaultKitekey {
		konfig.KiteKeyFile = ""
	}

	konfig.KiteKey = string(p)

	return makeUseFunc(&konfig)(cache)
}

func isFatal(err error) bool {
	return err != nil && err != storage.ErrKeyNotFound
}

func mergeIn(kfg, mixin *config.Konfig) error {
	p, err := json.Marshal(object.Inline(mixin, kfg))
	if err != nil {
		return err
	}

	return json.Unmarshal(p, kfg)
}

func setFlatKeyValue(m map[string]interface{}, key, value string) error {
	keys := strings.Split(key, ".")
	it := m
	last := len(keys) - 1

	for _, key := range keys[:last] {
		switch v := it[key].(type) {
		case map[string]interface{}:
			it = v
		case nil:
			newV := make(map[string]interface{})
			it[key] = newV
			it = newV
		default:
			return errors.New("key is not an object")
		}
	}

	if value == "" {
		delete(it, keys[last])
	} else {
		it[keys[last]] = value
	}

	return nil
}

func setKonfig(cfg *config.Konfig, key, value string) error {
	m := make(map[string]interface{})

	p, err := json.Marshal(cfg)
	if err != nil {
		return err
	}

	if err := json.Unmarshal(p, &m); err != nil {
		return err
	}

	if err := setFlatKeyValue(m, key, value); err != nil {
		return err
	}

	if p, err = json.Marshal(m); err != nil {
		return err
	}

	if value == "" {
		*cfg = config.Konfig{}
	}

	return json.Unmarshal(p, cfg)
}

func nonil(err ...error) error {
	for _, e := range err {
		if e != nil {
			return e
		}
	}
	return nil
}

func CacheOptions(app string) *config.CacheOptions { return DefaultClient.CacheOptions(app) }
func List() config.Konfigs                         { return DefaultClient.List() }
func Read(e *config.Environments) *config.Konfig   { return DefaultClient.Read(e) }
func Set(key, value string) error                  { return DefaultClient.Set(key, value) }
func Use(k *config.Konfig) error                   { return DefaultClient.Use(k) }
func Used() (*config.Konfig, error)                { return DefaultClient.Used() }
<|endoftext|>


<commit_before>package main

// This is *awful*.

import (
	"fmt"
	"io/ioutil"
	"regexp"
)

var gpioRE = regexp.MustCompile(`^gpio(\d+)$`)

func forciblyUnwedgeGPIO() {
	println("Forcibly unwedging GPIO")

	info, err := ioutil.ReadDir("/sys/class/gpio")
	if err != nil {
		fmt.Printf("Unwedging GPIO failed: %v.  Proceeding in hope anyway.", err)
		return
	}

	for _, i := range info {
		matches := gpioRE.FindStringSubmatch(i.Name())
		if len(matches) > 1 {
			fmt.Printf("Unwedging %v", i.Name())
		}
	}

	println("Dinod *might* work now.")
}
<commit_msg>Make it actually unwedge<commit_after>package main

// This is *awful*.

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
)

var gpioRE = regexp.MustCompile(`^gpio(\d+)$`)

func unwedgePin(pin string) error {
	fh, err := os.OpenFile("/sys/class/gpio/unexport", os.O_WRONLY, os.ModeExclusive)
	if err != nil {
		return err
	}
	defer fh.Close()
	_, err = fh.WriteString(pin)
	return err
}

func forciblyUnwedgeGPIO() {
	println("Forcibly unwedging GPIO")

	info, err := ioutil.ReadDir("/sys/class/gpio")
	if err != nil {
		fmt.Printf("Unwedging GPIO failed: %v.  Proceeding in hope anyway.\n", err)
		return
	}

	for _, i := range info {
		matches := gpioRE.FindStringSubmatch(i.Name())
		if len(matches) > 1 {
			fmt.Printf("Unwedging %v\n", matches[1])
			err := unwedgePin(matches[1])
			if err != nil {
				fmt.Printf("Unwedging pin %v failed: %v.\n", matches[1], err)
			}
		}
	}

	println("Dinod *might* work now.")
}
<|endoftext|>


<commit_before>package hood

const (
	ValidationErrorValueNotSet = 0x8000 + iota
	ValidationErrorValueTooSmall
	ValidationErrorValueTooBig
	ValidationErrorValueTooShort
	ValidationErrorValueTooLong
)

// Validation error type
type ValidationError struct {
	id int
	s  string
}

// NewValidationError returns a new validation error with the specified id and
// text. The id's purpose is to distinguish different validation error types.
// Built-in validation error ids start at 0x8000.
func NewValidationError(id int, text string) error {
	return &ValidationError{id, text}
}

func (e *ValidationError) Error() string {
	return e.s
}

func (e *ValidationError) Id() int {
	return e.id
}
<commit_msg>increase built-in error start id<commit_after>package hood

const (
	ValidationErrorValueNotSet = (1<<16 + iota)
	ValidationErrorValueTooSmall
	ValidationErrorValueTooBig
	ValidationErrorValueTooShort
	ValidationErrorValueTooLong
)

// Validation error type
type ValidationError struct {
	id int
	s  string
}

// NewValidationError returns a new validation error with the specified id and
// text. The id's purpose is to distinguish different validation error types.
// Built-in validation error ids start at 65536, so you should keep your custom
// ids under that value.
func NewValidationError(id int, text string) error {
	return &ValidationError{id, text}
}

func (e *ValidationError) Error() string {
	return e.s
}

func (e *ValidationError) Id() int {
	return e.id
}
<|endoftext|>


<commit_before>package rtime

import (
	"net/http"
	"strings"
	"time"

	"github.com/inconshreveable/log15"
	"github.com/juju/errors"
)

type CodeWriter struct {
	code int
	w    http.ResponseWriter
}

func (c *CodeWriter) Header() http.Header {
	return c.w.Header()
}

func (c *CodeWriter) Write(b []byte) (int, error) {
	return c.w.Write(b)
}

func (c *CodeWriter) WriteHeader(code int) {
	c.code = code
	c.w.WriteHeader(code)
}

func Midddleware(w http.ResponseWriter, r *http.Request) {
	clientIP := r.RemoteAddr
	if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
		clientIP = clientIP[:colon]
	}

	w2 := &CodeWriter{w: w, code: 200}

	start := time.Now()
	logger := LOGGER.New(
		"url", r.RequestURI, "method", r.Method, "ip", clientIP,
	)
	logger.Info("http_started")
	logger = logger.New(
		"time", log15.Lazy{func() interface{} { return time.Since(start) }},
		"code", log15.Lazy{func() interface{} { return w2.code }},
	)

	defer func() {
		if err := recover(); err != nil {
			err2, ok := err.(error)
			if ok {
				logger.Error(
					"server_error", "err", errors.ErrorStack(err2),
				)
			} else {
				logger.Error(
					"server_uerror", "err", err, "ip", clientIP,
				)
			}
			http.Error(w, http.StatusText(500), 500)
		}
	}()

	ctx := r.Context()
	r = r.WithContext(ctx)

	w.Header().Set("X-Frame-Options", "DENY")
	w.Header().Set("X-Content-Type-Options", "nosniff")
	w.Header().Set("X-XSS-Protection", "1; mode=block")

	http.DefaultServeMux.ServeHTTP(w2, r.WithContext(ctx))

	logger.Info("http_served")
}
<commit_msg>minor<commit_after>package rtime

import (
	"net/http"
	"strings"
	"time"

	"github.com/inconshreveable/log15"
	"github.com/juju/errors"
)

type CodeWriter struct {
	code int
	http.ResponseWriter
}

func (c *CodeWriter) WriteHeader(code int) {
	c.code = code
	c.ResponseWriter.WriteHeader(code)
}

func Midddleware(w http.ResponseWriter, r *http.Request) {
	clientIP := r.RemoteAddr
	if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
		clientIP = clientIP[:colon]
	}

	w2 := &CodeWriter{200, w}

	start := time.Now()
	logger := LOGGER.New(
		"url", r.RequestURI, "method", r.Method, "ip", clientIP,
	)
	logger.Info("http_started")
	logger = logger.New(
		"time", log15.Lazy{func() interface{} { return time.Since(start) }},
		"code", log15.Lazy{func() interface{} { return w2.code }},
	)

	defer func() {
		if err := recover(); err != nil {
			err2, ok := err.(error)
			if ok {
				logger.Error(
					"server_error", "err", errors.ErrorStack(err2),
				)
			} else {
				logger.Error(
					"server_uerror", "err", err, "ip", clientIP,
				)
			}
			http.Error(w, http.StatusText(500), 500)
		}
	}()

	ctx := r.Context()
	r = r.WithContext(ctx)

	w.Header().Set("X-Frame-Options", "DENY")
	w.Header().Set("X-Content-Type-Options", "nosniff")
	w.Header().Set("X-XSS-Protection", "1; mode=block")

	http.DefaultServeMux.ServeHTTP(w2, r.WithContext(ctx))

	logger.Info("http_served")
}
<|endoftext|>