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

package main

/*
#include <utmp.h>
*/
import "C"

import (
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/locksmith/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/Godeps/_workspace/src/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/pkg/timeutil"
	"github.com/coreos/locksmith/updateengine"
)

const (
	initialInterval   = time.Second * 5
	maxInterval       = time.Minute * 5
	loginsRebootDelay = time.Minute * 5
)

var (
	etcdServices = []string{
		"etcd.service",
		"etcd2.service",
	}
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
	StrategyOff        = "off"
)

// attempt to broadcast msg to all lines registered in utmp
// returns count of lines successfully opened (and likely broadcasted to)
func broadcast(msg string) uint {
	var cnt uint
	C.setutent()

	for {
		var utmp *C.struct_utmp
		utmp = C.getutent()
		if utmp == nil {
			break
		}

		line := C.GoString(&utmp.ut_line[0])
		tty, _ := os.OpenFile("/dev/"+line, os.O_WRONLY, 0)
		if tty == nil {
			// ignore errors, this is just a best-effort courtesy notice
			continue
		}
		cnt++
		go func() {
			fmt.Fprintf(tty, "\r%79s\r\n", " ")
			fmt.Fprintf(tty, "%-79.79s\007\007\r\n", fmt.Sprintf("Broadcast message from locksmithd at %s:", time.Now()))
			fmt.Fprintf(tty, "%-79.79s\r\n", msg) // msg is assumed to be short and not require wrapping
			fmt.Fprintf(tty, "\r%79s\r\n", " ")
			tty.Close()
		}()
	}

	return cnt
}

func expBackoff(interval time.Duration) time.Duration {
	interval = interval * 2
	if interval > maxInterval {
		interval = maxInterval
	}
	return interval
}

func rebootAndSleep(lgn *login1.Conn) {
	// Broadcast a notice, if broadcast found lines to notify, delay the reboot.
	delaymins := loginsRebootDelay / time.Minute
	lines := broadcast(fmt.Sprintf("System reboot in %d minutes!", delaymins))
	if 0 != lines {
		fmt.Printf("Logins detected, delaying reboot for %d minutes.\n", delaymins)
		time.Sleep(loginsRebootDelay)
	}
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	interval := initialInterval
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			interval = expBackoff(interval)
			fmt.Printf("Retrying in %v. Error locking: %v\n", interval, err)
			time.Sleep(interval)

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := getClient()
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (active bool, name string, err error) {
	active = false
	name = ""

	sys, err := dbus.New()
	if err != nil {
		return
	}
	defer sys.Close()

	for _, service := range etcdServices {
		prop, err := sys.GetUnitProperty(service, "ActiveState")
		if err != nil {
			continue
		}

		switch prop.Value.Value().(string) {
		case "inactive":
			continue
		default:
			active = true
			name = service
			break
		}
	}

	return
}

type rebooter struct {
	strategy string
	lgn      *login1.Conn
}

func (r rebooter) useLock() (useLock bool, err error) {
	switch r.strategy {
	case StrategyBestEffort:
		active, name, err := etcdActive()
		if err != nil {
			return false, err
		}
		if active {
			fmt.Printf("%s is active\n", name)
			useLock = true
		} else {
			fmt.Printf("%v are inactive\n", etcdServices)
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", r.strategy)
	}

	return useLock, nil
}

func (r rebooter) reboot() int {
	useLock, err := r.useLock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(stop chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	interval := initialInterval
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(interval):
			active, _, err := etcdActive()
			if err != nil {
				reason = fmt.Sprintf("error checking status of %v", etcdServices)
				break
			}
			if !active {
				reason = fmt.Sprintf("%v are inactive", etcdServices)
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock: " + err.Error()
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		interval = expBackoff(interval)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, interval)
	}
}

// runDaemon waits for the reboot needed signal coming out of update engine and
// attempts to acquire the reboot lock. If the reboot lock is acquired then the
// machine will reboot.
func runDaemon() int {
	var period *timeutil.Periodic

	strategy := os.Getenv("REBOOT_STRATEGY")

	if strategy == "" {
		strategy = StrategyBestEffort
	}

	if strategy == StrategyOff {
		fmt.Fprintf(os.Stderr, "Reboot strategy is %q - shutting down.\n", strategy)
		return 0
	}

	startw := os.Getenv("REBOOT_WINDOW_START")
	lengthw := os.Getenv("REBOOT_WINDOW_LENGTH")
	if (startw == "") != (lengthw == "") {
		fmt.Fprintln(os.Stderr, "either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set")
		return 1
	}

	if startw != "" && lengthw != "" {
		p, err := timeutil.ParsePeriodic(startw, lengthw)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing reboot window: %s\n", err)
			return 1
		}

		period = p
	}

	shutdown := make(chan os.Signal, 1)
	stop := make(chan struct{}, 1)

	go func() {
		<-shutdown
		fmt.Fprintln(os.Stderr, "Received interrupt/termination signal - shutting down.")
		os.Exit(0)
	}()
	signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	var wg sync.WaitGroup
	if strategy != StrategyReboot {
		wg.Add(1)
		go unlockHeldLocks(stop, &wg)
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch, stop)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stop)
	wg.Wait()

	if period != nil {
		now := time.Now()
		sleeptime := period.DurationToStart(now)
		if sleeptime > 0 {
			fmt.Printf("Waiting for %s to reboot.\n", sleeptime)
			time.Sleep(sleeptime)
		}
	}

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

package main

/*
#include <utmp.h>
*/
import "C"

import (
	"fmt"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/coreos/locksmith/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/Godeps/_workspace/src/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/pkg/timeutil"
	"github.com/coreos/locksmith/updateengine"
)

const (
	initialInterval   = time.Second * 5
	maxInterval       = time.Minute * 5
	loginsRebootDelay = time.Minute * 5
)

var (
	etcdServices = []string{
		"etcd.service",
		"etcd2.service",
	}
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
	StrategyOff        = "off"
)

// attempt to broadcast msg to all lines registered in utmp
// returns count of lines successfully opened (and likely broadcasted to)
func broadcast(msg string) uint {
	var cnt uint
	C.setutent()

	for {
		var utmp *C.struct_utmp
		utmp = C.getutent()
		if utmp == nil {
			break
		}

		line := C.GoString(&utmp.ut_line[0])
		tty, _ := os.OpenFile("/dev/"+line, os.O_WRONLY, 0)
		if tty == nil {
			// ignore errors, this is just a best-effort courtesy notice
			continue
		}
		cnt++
		go func() {
			fmt.Fprintf(tty, "\r%79s\r\n", " ")
			fmt.Fprintf(tty, "%-79.79s\007\007\r\n", fmt.Sprintf("Broadcast message from locksmithd at %s:", time.Now()))
			fmt.Fprintf(tty, "%-79.79s\r\n", msg) // msg is assumed to be short and not require wrapping
			fmt.Fprintf(tty, "\r%79s\r\n", " ")
			tty.Close()
		}()
	}

	return cnt
}

func expBackoff(interval time.Duration) time.Duration {
	interval = interval * 2
	if interval > maxInterval {
		interval = maxInterval
	}
	return interval
}

func rebootAndSleep(lgn *login1.Conn) {
	// Broadcast a notice, if broadcast found lines to notify, delay the reboot.
	delaymins := loginsRebootDelay / time.Minute
	lines := broadcast(fmt.Sprintf("System reboot in %d minutes!", delaymins))
	if 0 != lines {
		fmt.Printf("Logins detected, delaying reboot for %d minutes.\n", delaymins)
		time.Sleep(loginsRebootDelay)
	}
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	interval := initialInterval
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			interval = expBackoff(interval)
			fmt.Printf("Retrying in %v. Error locking: %v\n", interval, err)
			time.Sleep(interval)

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := getClient()
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (active bool, name string, err error) {
	active = false
	name = ""

	sys, err := dbus.New()
	if err != nil {
		return
	}
	defer sys.Close()

	for _, service := range etcdServices {
		prop, err := sys.GetUnitProperty(service, "ActiveState")
		if err != nil {
			continue
		}

		switch prop.Value.Value().(string) {
		case "inactive":
			continue
		default:
			active = true
			name = service
			break
		}
	}

	return
}

type rebooter struct {
	strategy string
	lgn      *login1.Conn
}

func (r rebooter) reboot() int {
	useLock, err := useLock(r.strategy)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// useLock returns whether locksmith should attempt to take a lock before
// rebooting or release a lock afterwards, based on the given strategy.
// If strategy is set to best effort, this will be dependent on whether the
// local instance of etcd is active. Otherwise, the lock will always be
// attempted (in the case of strategy = etcd lock) or never be attempted (in
// the case of strategy = reboot)
func useLock(strategy string) (useLock bool, err error) {
	switch strategy {
	case StrategyBestEffort:
		active, name, err := etcdActive()
		if err != nil {
			return false, err
		}
		if active {
			fmt.Printf("%s is active\n", name)
			useLock = true
		} else {
			fmt.Printf("%v are inactive\n", etcdServices)
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", strategy)
	}

	return useLock, nil
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(strategy string, stop chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	interval := initialInterval
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(interval):
			// Here we assume that the strategy used by locksmith
			// is consistent with that used before the previous
			// reboot (if any), and use that to decide whether to
			// attempt to unlock.
			shouldUnlock, err := useLock(strategy)
			if err != nil {
				reason = fmt.Sprintf("error checking whether lock should be released: %v", err)
				break
			}
			if !shouldUnlock {
				reason = fmt.Sprintf("%v are inactive", etcdServices)
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock: " + err.Error()
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		interval = expBackoff(interval)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, interval)
	}
}

// runDaemon waits for the reboot needed signal coming out of update engine and
// attempts to acquire the reboot lock. If the reboot lock is acquired then the
// machine will reboot.
func runDaemon() int {
	var period *timeutil.Periodic

	strategy := os.Getenv("REBOOT_STRATEGY")

	if strategy == "" {
		strategy = StrategyBestEffort
	}

	if strategy == StrategyOff {
		fmt.Fprintf(os.Stderr, "Reboot strategy is %q - shutting down.\n", strategy)
		return 0
	}

	startw := os.Getenv("REBOOT_WINDOW_START")
	lengthw := os.Getenv("REBOOT_WINDOW_LENGTH")
	if (startw == "") != (lengthw == "") {
		fmt.Fprintln(os.Stderr, "either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set")
		return 1
	}

	if startw != "" && lengthw != "" {
		p, err := timeutil.ParsePeriodic(startw, lengthw)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing reboot window: %s\n", err)
			return 1
		}

		period = p
	}

	shutdown := make(chan os.Signal, 1)
	stop := make(chan struct{}, 1)

	go func() {
		<-shutdown
		fmt.Fprintln(os.Stderr, "Received interrupt/termination signal - shutting down.")
		os.Exit(0)
	}()
	signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	var wg sync.WaitGroup
	if strategy != StrategyReboot {
		wg.Add(1)
		go unlockHeldLocks(strategy, stop, &wg)
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch, stop)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stop)
	wg.Wait()

	if period != nil {
		now := time.Now()
		sleeptime := period.DurationToStart(now)
		if sleeptime > 0 {
			fmt.Printf("Waiting for %s to reboot.\n", sleeptime)
			time.Sleep(sleeptime)
		}
	}

	return r.reboot()
}
<|endoftext|>


<commit_before>/***************************************************************************
 Copyright 2017 William Knox Carey

 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 beacon

// Specific implementations for version 0.3 beacons

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Type alias for this version
type beaconV3 beaconStruct

// Register this version's type
func init() {
	var nilStruct *beaconV3
	beaconType["0.3"] = reflect.TypeOf(nilStruct).Elem()
}

// Initialize the beacon with defaults appropriate for this version
func (beacon *beaconV3) initialize() {
	beacon.QueryMap = make(map[string]string)
	beacon.QueryMap["chromosome"]     = "chromosome"
	beacon.QueryMap["start"]          = "start"
	beacon.QueryMap["alternateBases"] = "alternateBases"
	beacon.QueryMap["referenceBases"] = "referenceBases"
	beacon.QueryMap["datasetIds"]     = "datasetIds"
	beacon.QueryMap["assemblyId"]     = "assemblyId"
	beacon.QueryMap["GRCh37"]         = "GRCh37"
	beacon.QueryMap["GRCh38"]         = "GRCh38"
}

func (beacon *beaconV3) parseResponse(status int, raw []byte, err error) *BeaconResponse {
	response := &BeaconResponse{Name: beacon.Name,
		Icon: beacon.Icon,
		Responses: make(map[string]string),
		Error: make(map[string]string)}

	if err != nil {
		addResponseError(response, 400, "could not reach beacon")
		return response
	}

	if status/100 != 2 {
		addResponseError(response, status, "beacon error")
		return response
	}

	var v3 struct {
		BeaconId                string                    `json:"beaconId"`
		Exists                  bool                      `json:"exists"`
		Error                   map[string]string         `json:"error,omitempty"`
		AlleleRequest           map [string]interface{}   `json:"alleleRequest,omitempty"`
		DatasetAlleleResponses  []map[string]interface{}  `json:"datasetAlleleResponses,omitempty"`
	}

	if err := json.Unmarshal(raw, &v3); err == nil {
		if v3.Error == nil {
			response.Status = status
			for _, r := range v3.DatasetAlleleResponses {
				var ex string
				if r["exists"].(bool) {
					ex = "true"
				} else {
					ex = "false"
				}

				id := r["datasetId"].(string)
				addResponseResult(response, id, ex)
			}
		} else {
			code, _ := strconv.Atoi(v3.Error["errorCode"])
			addResponseError(response, code, v3.Error["message"])
		}
	} else {
		addResponseError(response, 400, "malformed reply from beacon")
	}

	return response
}

func (beacon *beaconV3) query(query *BeaconQuery, accessToken string, idToken string, ch chan<- BeaconResponse) {
	qs := beacon.queryString(query)
	uri := fmt.Sprintf("%s?%s", beacon.Endpoint, qs)

	status, body, err := httpGet(uri, accessToken, idToken)
	resp := beacon.parseResponse(status, body, err)

	ch <- *resp
}

// Construct the query string
func (beacon *beaconV3) queryString(query *BeaconQuery) string {
	ql := make([]string, 0, 20)

	for _, d := range beacon.DatasetIds {
		ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap["datasetIds"], d))
	}

	for k, v := range *query {
		if k == "assemblyId" {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], beacon.QueryMap[v[0]]))
		} else {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], v[0]))
		}
	}

	for k2, v2 := range beacon.AdditionalFields {
		ql = append(ql, fmt.Sprintf("%s=%s", k2, v2))
	}

	return strings.Join(ql, "&")
}

<commit_msg>Nothing changed<commit_after>/***************************************************************************
 Copyright 2017 William Knox Carey

 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 beacon

// Specific implementations for version 0.3 beacons

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Type alias for this version
type beaconV3 beaconStruct

// Register this version's type
func init() {
	var nilStruct *beaconV3
	beaconType["0.3"] = reflect.TypeOf(nilStruct).Elem()
}

// Initialize the beacon with defaults appropriate for this version
func (beacon *beaconV3) initialize() {
	beacon.QueryMap = make(map[string]string)
	beacon.QueryMap["chromosome"]     = "chromosome"
	beacon.QueryMap["start"]          = "start"
	beacon.QueryMap["alternateBases"] = "alternateBases"
	beacon.QueryMap["referenceBases"] = "referenceBases"
	beacon.QueryMap["datasetIds"]     = "datasetIds"
	beacon.QueryMap["assemblyId"]     = "assemblyId"
	beacon.QueryMap["GRCh37"]         = "GRCh37"
	beacon.QueryMap["GRCh38"]         = "GRCh38"
}

func (beacon *beaconV3) parseResponse(status int, raw []byte, err error) *BeaconResponse {
	response := &BeaconResponse{Name: beacon.Name,
		Icon: beacon.Icon,
		Responses: make(map[string]string),
		Error: make(map[string]string)}

	if err != nil {
		addResponseError(response, 400, "could not reach beacon")
		return response
	}

	if status/100 != 2 {
		addResponseError(response, status, "beacon error")
		return response
	}

	var v3 struct {
		BeaconId                string                    `json:"beaconId"`
		Exists                  bool                      `json:"exists"`
		Error                   map[string]string         `json:"error,omitempty"`
		AlleleRequest           map [string]interface{}   `json:"alleleRequest,omitempty"`
		DatasetAlleleResponses  []map[string]interface{}  `json:"datasetAlleleResponses,omitempty"`
	}

	if err := json.Unmarshal(raw, &v3); err == nil {
		if v3.Error == nil {
			response.Status = status
			for _, r := range v3.DatasetAlleleResponses {
				var ex string
				if r["exists"].(bool) {
					ex = "true"
				} else {
					ex = "false"
				}

				id := r["datasetId"].(string)
				addResponseResult(response, id, ex)
			}
		} else {
			code, _ := strconv.Atoi(v3.Error["errorCode"])
			addResponseError(response, code, v3.Error["message"])
		}
	} else {
		addResponseError(response, 400, "malformed reply from beacon")
	}

	return response
}

func (beacon *beaconV3) query(query *BeaconQuery, accessToken string, idToken string, ch chan<- BeaconResponse) {
	qs := beacon.queryString(query)
	uri := fmt.Sprintf("%s?%s", beacon.Endpoint, qs)

	status, body, err := httpGet(uri, accessToken, idToken)
	resp := beacon.parseResponse(status, body, err)

	ch <- *resp
}

// Construct the query string
func (beacon *beaconV3) queryString(query *BeaconQuery) string {
	ql := make([]string, 0, 20)

	for _, d := range beacon.DatasetIds {
		ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap["datasetIds"], d))
	}

	for k, v := range *query {
		if k == "assemblyId" {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], beacon.QueryMap[v[0]]))
		} else {
			ql = append(ql, fmt.Sprintf("%s=%s", beacon.QueryMap[k], v[0]))
		}
	}

	for k2, v2 := range beacon.AdditionalFields {
		ql = append(ql, fmt.Sprintf("%s=%s", k2, v2))
	}

	return strings.Join(ql, "&")
}

<|endoftext|>


<commit_before>package mocker

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

	"github.com/tsaikd/gin"
)

func outputJSON(c *gin.Context, code int, data interface{}) {
	pretty := false
	if queryPretty, exist := c.GetQuery("pretty"); exist {
		pretty, _ = strconv.ParseBool(queryPretty)
	}

	if pretty {
		jsondata, err := json.MarshalIndent(data, "", "\t")
		if err != nil {
			c.AbortWithError(http.StatusBadRequest, err)
			return
		}
		c.Data(code, "", jsondata)
	} else {
		c.JSON(code, data)
	}
}
<commit_msg>pretty format endup with newline<commit_after>package mocker

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/tsaikd/gin"
)

func outputJSON(c *gin.Context, code int, data interface{}) {
	pretty := false
	if queryPretty, exist := c.GetQuery("pretty"); exist {
		pretty, _ = strconv.ParseBool(queryPretty)
	}

	if pretty {
		jsondata, err := json.MarshalIndent(data, "", "\t")
		if err != nil {
			c.AbortWithError(http.StatusBadRequest, err)
			return
		}
		buffer := bytes.NewBuffer(jsondata)
		if err = buffer.WriteByte('\n'); err != nil {
			c.AbortWithError(http.StatusBadRequest, err)
			return
		}
		c.Data(code, "", buffer.Bytes())
	} else {
		c.JSON(code, data)
	}
}
<|endoftext|>


<commit_before>package svg

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
	"sync"

	mt "github.com/rustyoz/Mtransform"
)

// DrawingInstructionParser allow getting segments and drawing
// instructions from them. All SVG elements should implement this
// interface.
type DrawingInstructionParser interface {
	ParseDrawingInstructions() (chan *DrawingInstruction, chan error)
}

// Tuple is an X,Y coordinate
type Tuple [2]float64

// Svg represents an SVG file containing at least a top level group or a
// number of Paths
type Svg struct {
	Title        string  `xml:"title"`
	Groups       []Group `xml:"g"`
	ViewBox      string  `xml:"viewBox,attr"`
	Elements     []DrawingInstructionParser
	Name         string
	Transform    *mt.Transform
	scale        float64
	instructions chan *DrawingInstruction
	errors       chan error
	segments     chan Segment
}

// Group represents an SVG group (usually located in a 'g' XML element)
type Group struct {
	ID              string
	Stroke          string
	StrokeWidth     int32
	Fill            string
	FillRule        string
	Elements        []DrawingInstructionParser
	TransformString string
	Transform       *mt.Transform // row, column
	Parent          *Group
	Owner           *Svg
	instructions    chan *DrawingInstruction
	errors          chan error
	segments        chan Segment
}

// ParseDrawingInstructions implements the DrawingInstructionParser interface
//
// This method makes it easier to get all the drawing instructions.
func (g *Group) ParseDrawingInstructions() (chan *DrawingInstruction, chan error) {
	g.instructions = make(chan *DrawingInstruction, 100)
	g.errors = make(chan error, 100)

	errWg := &sync.WaitGroup{}

	go func() {
		defer close(g.instructions)
		defer func() { errWg.Wait(); close(g.errors) }()
		for _, e := range g.Elements {
			instrs, errs := e.ParseDrawingInstructions()
			errWg.Add(1)
			go func() {
				for er := range errs {
					g.errors <- er
				}
				errWg.Done()
			}()
			for is := range instrs {
				g.instructions <- is
			}
		}
	}()

	return g.instructions, g.errors
}

// UnmarshalXML implements the encoding.xml.Unmarshaler interface
func (g *Group) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
	for _, attr := range start.Attr {
		switch attr.Name.Local {
		case "id":
			g.ID = attr.Value
		case "stroke":
			g.Stroke = attr.Value
		case "stroke-width":
			intValue, err := strconv.ParseInt(attr.Value, 10, 32)
			if err != nil {
				return err
			}
			g.StrokeWidth = int32(intValue)
		case "fill":
			g.Fill = attr.Value
		case "fill-rule":
			g.FillRule = attr.Value
		case "transform":
			g.TransformString = attr.Value
			t, err := parseTransform(g.TransformString)
			if err != nil {
				fmt.Println(err)
			}
			g.Transform = &t
		}
	}

	for {
		token, err := decoder.Token()
		if err != nil {
			return err
		}

		switch tok := token.(type) {
		case xml.StartElement:
			var elementStruct DrawingInstructionParser

			switch tok.Name.Local {
			case "g":
				elementStruct = &Group{Parent: g, Owner: g.Owner, Transform: mt.NewTransform()}
			case "rect":
				elementStruct = &Rect{group: g}
			case "circle":
				elementStruct = &Circle{group: g}
			case "path":
				elementStruct = &Path{group: g, StrokeWidth: float64(g.StrokeWidth), Stroke: &g.Stroke, Fill: &g.Fill}
			default:
				continue
			}
			if err = decoder.DecodeElement(elementStruct, &tok); err != nil {
				return fmt.Errorf("error decoding element of Group: %s", err)
			}
			g.Elements = append(g.Elements, elementStruct)
		case xml.EndElement:
			if tok.Name.Local == "g" {
				return nil
			}
		}
	}
}

// ParseDrawingInstructions implements the DrawingInstructionParser interface
//
// This method makes it easier to get all the drawing instructions.
func (s *Svg) ParseDrawingInstructions() (chan *DrawingInstruction, chan error) {
	s.instructions = make(chan *DrawingInstruction, 100)
	s.errors = make(chan error, 100)

	go func() {
		errWg := &sync.WaitGroup{}
		var elecount int
		defer close(s.instructions)
		defer func() { errWg.Wait(); close(s.errors) }()
		for _, e := range s.Elements {
			elecount++
			instrs, errs := e.ParseDrawingInstructions()
			errWg.Add(1)
			go func(count int) {
				for er := range errs {
					s.errors <- fmt.Errorf("error when parsing element nr. %d: %s", count, er)
				}
				errWg.Done()
			}(elecount)

			for is := range instrs {
				s.instructions <- is
			}
		}

		for _, g := range s.Groups {
			instrs, errs := g.ParseDrawingInstructions()
			errWg.Add(1)
			go func() {
				for er := range errs {
					s.errors <- er
				}
				errWg.Done()
			}()
			for is := range instrs {
				s.instructions <- is
			}
		}
	}()

	return s.instructions, s.errors
}

// UnmarshalXML implements the encoding.xml.Unmarshaler interface
func (s *Svg) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
	for {
		for _, attr := range start.Attr {
			if attr.Name.Local == "viewBox" {
				s.ViewBox = attr.Value
				break
			}
		}

		token, err := decoder.Token()
		if err != nil {
			return err
		}

		switch tok := token.(type) {
		case xml.StartElement:
			var dip DrawingInstructionParser

			switch tok.Name.Local {
			case "g":
				g := &Group{Owner: s, Transform: mt.NewTransform()}
				if err = decoder.DecodeElement(g, &tok); err != nil {
					return fmt.Errorf("error decoding group element within SVG struct: %s", err)
				}
				s.Groups = append(s.Groups, *g)
				continue
			case "rect":
				dip = &Rect{}
			case "circle":
				dip = &Circle{}
			case "path":
				dip = &Path{}

			default:
				continue
			}

			if err = decoder.DecodeElement(dip, &tok); err != nil {
				return fmt.Errorf("error decoding element of SVG struct: %s", err)
			}

			s.Elements = append(s.Elements, dip)

		case xml.EndElement:
			if tok.Name.Local == "svg" {
				return nil
			}
		}
	}
}

// ParseSvg parses an SVG string into an SVG struct
func ParseSvg(str string, name string, scale float64) (*Svg, error) {
	var svg Svg
	svg.Name = name
	svg.Transform = mt.NewTransform()
	if scale > 0 {
		svg.Transform.Scale(scale, scale)
		svg.scale = scale
	}
	if scale < 0 {
		svg.Transform.Scale(1.0/-scale, 1.0/-scale)
		svg.scale = 1.0 / -scale
	}

	err := xml.Unmarshal([]byte(str), &svg)
	if err != nil {
		return nil, fmt.Errorf("ParseSvg Error: %v", err)
	}

	for i := range svg.Groups {
		svg.Groups[i].SetOwner(&svg)
		if svg.Groups[i].Transform == nil {
			svg.Groups[i].Transform = mt.NewTransform()
		}
	}
	return &svg, nil
}

// ParseSvgFromReader parses an SVG struct from an io.Reader
func ParseSvgFromReader(r io.Reader, name string, scale float64) (*Svg, error) {
	var svg Svg
	svg.Name = name
	svg.Transform = mt.NewTransform()
	if scale > 0 {
		svg.Transform.Scale(scale, scale)
		svg.scale = scale
	}
	if scale < 0 {
		svg.Transform.Scale(1.0/-scale, 1.0/-scale)
		svg.scale = 1.0 / -scale
	}

	if err := xml.NewDecoder(r).Decode(&svg); err != nil {
		return nil, fmt.Errorf("ParseSvg Error: %v", err)
	}

	for i := range svg.Groups {
		svg.Groups[i].SetOwner(&svg)
		if svg.Groups[i].Transform == nil {
			svg.Groups[i].Transform = mt.NewTransform()
		}
	}
	return &svg, nil
}

// ViewBoxValues returns all the numerical values in the viewBox
// attribute.
func (s *Svg) ViewBoxValues() ([]float64, error) {
	var vals []float64

	if s.ViewBox == "" {
		return vals, errors.New("viewBox attribute is empty")
	}

	split := strings.Split(s.ViewBox, " ")

	for _, val := range split {
		ival, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return vals, err
		}
		vals = append(vals, ival)
	}

	return vals, nil
}

// SetOwner sets the owner of a SVG Group
func (g *Group) SetOwner(svg *Svg) {
	g.Owner = svg
	for _, gn := range g.Elements {
		switch gn.(type) {
		case *Group:
			gn.(*Group).Owner = g.Owner
			gn.(*Group).SetOwner(svg)
		case *Path:
			gn.(*Path).group = g
		}
	}
}
<commit_msg>Stroke can be float<commit_after>package svg

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
	"sync"

	mt "github.com/rustyoz/Mtransform"
)

// DrawingInstructionParser allow getting segments and drawing
// instructions from them. All SVG elements should implement this
// interface.
type DrawingInstructionParser interface {
	ParseDrawingInstructions() (chan *DrawingInstruction, chan error)
}

// Tuple is an X,Y coordinate
type Tuple [2]float64

// Svg represents an SVG file containing at least a top level group or a
// number of Paths
type Svg struct {
	Title        string  `xml:"title"`
	Groups       []Group `xml:"g"`
	ViewBox      string  `xml:"viewBox,attr"`
	Elements     []DrawingInstructionParser
	Name         string
	Transform    *mt.Transform
	scale        float64
	instructions chan *DrawingInstruction
	errors       chan error
	segments     chan Segment
}

// Group represents an SVG group (usually located in a 'g' XML element)
type Group struct {
	ID              string
	Stroke          string
	StrokeWidth     float64
	Fill            string
	FillRule        string
	Elements        []DrawingInstructionParser
	TransformString string
	Transform       *mt.Transform // row, column
	Parent          *Group
	Owner           *Svg
	instructions    chan *DrawingInstruction
	errors          chan error
	segments        chan Segment
}

// ParseDrawingInstructions implements the DrawingInstructionParser interface
//
// This method makes it easier to get all the drawing instructions.
func (g *Group) ParseDrawingInstructions() (chan *DrawingInstruction, chan error) {
	g.instructions = make(chan *DrawingInstruction, 100)
	g.errors = make(chan error, 100)

	errWg := &sync.WaitGroup{}

	go func() {
		defer close(g.instructions)
		defer func() { errWg.Wait(); close(g.errors) }()
		for _, e := range g.Elements {
			instrs, errs := e.ParseDrawingInstructions()
			errWg.Add(1)
			go func() {
				for er := range errs {
					g.errors <- er
				}
				errWg.Done()
			}()
			for is := range instrs {
				g.instructions <- is
			}
		}
	}()

	return g.instructions, g.errors
}

// UnmarshalXML implements the encoding.xml.Unmarshaler interface
func (g *Group) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
	for _, attr := range start.Attr {
		switch attr.Name.Local {
		case "id":
			g.ID = attr.Value
		case "stroke":
			g.Stroke = attr.Value
		case "stroke-width":
			floatValue, err := strconv.ParseFloat(attr.Value, 64)
			if err != nil {
				return err
			}
			g.StrokeWidth = floatValue
		case "fill":
			g.Fill = attr.Value
		case "fill-rule":
			g.FillRule = attr.Value
		case "transform":
			g.TransformString = attr.Value
			t, err := parseTransform(g.TransformString)
			if err != nil {
				fmt.Println(err)
			}
			g.Transform = &t
		}
	}

	for {
		token, err := decoder.Token()
		if err != nil {
			return err
		}

		switch tok := token.(type) {
		case xml.StartElement:
			var elementStruct DrawingInstructionParser

			switch tok.Name.Local {
			case "g":
				elementStruct = &Group{Parent: g, Owner: g.Owner, Transform: mt.NewTransform()}
			case "rect":
				elementStruct = &Rect{group: g}
			case "circle":
				elementStruct = &Circle{group: g}
			case "path":
				elementStruct = &Path{group: g, StrokeWidth: float64(g.StrokeWidth), Stroke: &g.Stroke, Fill: &g.Fill}
			default:
				continue
			}
			if err = decoder.DecodeElement(elementStruct, &tok); err != nil {
				return fmt.Errorf("error decoding element of Group: %s", err)
			}
			g.Elements = append(g.Elements, elementStruct)
		case xml.EndElement:
			if tok.Name.Local == "g" {
				return nil
			}
		}
	}
}

// ParseDrawingInstructions implements the DrawingInstructionParser interface
//
// This method makes it easier to get all the drawing instructions.
func (s *Svg) ParseDrawingInstructions() (chan *DrawingInstruction, chan error) {
	s.instructions = make(chan *DrawingInstruction, 100)
	s.errors = make(chan error, 100)

	go func() {
		errWg := &sync.WaitGroup{}
		var elecount int
		defer close(s.instructions)
		defer func() { errWg.Wait(); close(s.errors) }()
		for _, e := range s.Elements {
			elecount++
			instrs, errs := e.ParseDrawingInstructions()
			errWg.Add(1)
			go func(count int) {
				for er := range errs {
					s.errors <- fmt.Errorf("error when parsing element nr. %d: %s", count, er)
				}
				errWg.Done()
			}(elecount)

			for is := range instrs {
				s.instructions <- is
			}
		}

		for _, g := range s.Groups {
			instrs, errs := g.ParseDrawingInstructions()
			errWg.Add(1)
			go func() {
				for er := range errs {
					s.errors <- er
				}
				errWg.Done()
			}()
			for is := range instrs {
				s.instructions <- is
			}
		}
	}()

	return s.instructions, s.errors
}

// UnmarshalXML implements the encoding.xml.Unmarshaler interface
func (s *Svg) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
	for {
		for _, attr := range start.Attr {
			if attr.Name.Local == "viewBox" {
				s.ViewBox = attr.Value
				break
			}
		}

		token, err := decoder.Token()
		if err != nil {
			return err
		}

		switch tok := token.(type) {
		case xml.StartElement:
			var dip DrawingInstructionParser

			switch tok.Name.Local {
			case "g":
				g := &Group{Owner: s, Transform: mt.NewTransform()}
				if err = decoder.DecodeElement(g, &tok); err != nil {
					return fmt.Errorf("error decoding group element within SVG struct: %s", err)
				}
				s.Groups = append(s.Groups, *g)
				continue
			case "rect":
				dip = &Rect{}
			case "circle":
				dip = &Circle{}
			case "path":
				dip = &Path{}

			default:
				continue
			}

			if err = decoder.DecodeElement(dip, &tok); err != nil {
				return fmt.Errorf("error decoding element of SVG struct: %s", err)
			}

			s.Elements = append(s.Elements, dip)

		case xml.EndElement:
			if tok.Name.Local == "svg" {
				return nil
			}
		}
	}
}

// ParseSvg parses an SVG string into an SVG struct
func ParseSvg(str string, name string, scale float64) (*Svg, error) {
	var svg Svg
	svg.Name = name
	svg.Transform = mt.NewTransform()
	if scale > 0 {
		svg.Transform.Scale(scale, scale)
		svg.scale = scale
	}
	if scale < 0 {
		svg.Transform.Scale(1.0/-scale, 1.0/-scale)
		svg.scale = 1.0 / -scale
	}

	err := xml.Unmarshal([]byte(str), &svg)
	if err != nil {
		return nil, fmt.Errorf("ParseSvg Error: %v", err)
	}

	for i := range svg.Groups {
		svg.Groups[i].SetOwner(&svg)
		if svg.Groups[i].Transform == nil {
			svg.Groups[i].Transform = mt.NewTransform()
		}
	}
	return &svg, nil
}

// ParseSvgFromReader parses an SVG struct from an io.Reader
func ParseSvgFromReader(r io.Reader, name string, scale float64) (*Svg, error) {
	var svg Svg
	svg.Name = name
	svg.Transform = mt.NewTransform()
	if scale > 0 {
		svg.Transform.Scale(scale, scale)
		svg.scale = scale
	}
	if scale < 0 {
		svg.Transform.Scale(1.0/-scale, 1.0/-scale)
		svg.scale = 1.0 / -scale
	}

	if err := xml.NewDecoder(r).Decode(&svg); err != nil {
		return nil, fmt.Errorf("ParseSvg Error: %v", err)
	}

	for i := range svg.Groups {
		svg.Groups[i].SetOwner(&svg)
		if svg.Groups[i].Transform == nil {
			svg.Groups[i].Transform = mt.NewTransform()
		}
	}
	return &svg, nil
}

// ViewBoxValues returns all the numerical values in the viewBox
// attribute.
func (s *Svg) ViewBoxValues() ([]float64, error) {
	var vals []float64

	if s.ViewBox == "" {
		return vals, errors.New("viewBox attribute is empty")
	}

	split := strings.Split(s.ViewBox, " ")

	for _, val := range split {
		ival, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return vals, err
		}
		vals = append(vals, ival)
	}

	return vals, nil
}

// SetOwner sets the owner of a SVG Group
func (g *Group) SetOwner(svg *Svg) {
	g.Owner = svg
	for _, gn := range g.Elements {
		switch gn.(type) {
		case *Group:
			gn.(*Group).Owner = g.Owner
			gn.(*Group).SetOwner(svg)
		case *Path:
			gn.(*Path).group = g
		}
	}
}
<|endoftext|>


<commit_before>package blake2

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha512"
	"hash"
	"testing"
)

// timings are all per-MiB

func benchmarkHash(b *testing.B, hash func() hash.Hash) {
	data := make([]byte, 1024)
	for i := 0; i < b.N; i++ {
		h := hash()
		for j := 0; j < 1024; j++ {
			h.Write(data)
		}
		h.Sum(nil)
	}
}

func BenchmarkBlake2B(b *testing.B) {
	benchmarkHash(b, NewBlake2B)
}

func BenchmarkMD5(b *testing.B) {
	benchmarkHash(b, md5.New)
}

func BenchmarkSHA1(b *testing.B) {
	benchmarkHash(b, sha1.New)
}

func BenchmarkSHA512(b *testing.B) {
	benchmarkHash(b, sha512.New)
}
<commit_msg>Benchmark in MB/sec.<commit_after>package blake2

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha512"
	"hash"
	"testing"
)

func benchmarkHash(b *testing.B, hash func() hash.Hash) {
	b.SetBytes(1024 * 1024)
	data := make([]byte, 1024)
	for i := 0; i < b.N; i++ {
		h := hash()
		for j := 0; j < 1024; j++ {
			h.Write(data)
		}
		h.Sum(nil)
	}
}

func BenchmarkBlake2B(b *testing.B) {
	benchmarkHash(b, NewBlake2B)
}

func BenchmarkMD5(b *testing.B) {
	benchmarkHash(b, md5.New)
}

func BenchmarkSHA1(b *testing.B) {
	benchmarkHash(b, sha1.New)
}

func BenchmarkSHA512(b *testing.B) {
	benchmarkHash(b, sha512.New)
}
<|endoftext|>


<commit_before><commit_msg>dita: disable promotion to shorter titles.<commit_after><|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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 main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/GoogleContainerTools/kpt-functions-catalog/scripts/patch_reader/pkg/latestpatch"
	"gopkg.in/yaml.v2"
)

var (
	// pattern of release branches, e.g. apply-setters/v1.0
	releaseBranchPattern = regexp.MustCompile(`[-\w]*/(v\d*\.\d*)`)
	// pattern for version tags, e.g. unstable, v0.1.1, v0.1
	versionGroup = `unstable|v\d*\.\d*\.\d*|v\d*\.\d*`
)

func dirExists(path string) bool {
	if stat, err := os.Stat(path); err == nil && stat.IsDir() {
		return true
	}
	return false
}

func fileExists(path string) bool {
	if _, err := os.Stat(path); err == nil {
		return true
	}
	return false
}

type functionExample struct {
	ExamplePath string
	ExampleName string
}

type functionExamples []functionExample

// exampleNames returns a list of the functionExample names
func (fe functionExamples) exampleNames() []string {
	var exampleNames []string
	for _, example := range fe {
		exampleNames = append(exampleNames, example.ExampleName)
	}
	return exampleNames
}

type functionRelease struct {
	FunctionName       string
	MinorVersion       string
	Language           string
	LatestPatchVersion string
	FunctionPath       string
	Examples           functionExamples
	IsContrib          bool
}

// newFunctionRelease allocates and initializes a functionRelease
func newFunctionRelease(branch string) (*functionRelease, error) {
	fr := &functionRelease{}
	if !releaseBranchPattern.MatchString(branch) {
		return nil, fmt.Errorf("invalid branch format")
	}
	segments := strings.Split(branch, "/")
	// assume branch format: */<func_name>/<minor_version>
	fr.MinorVersion = segments[len(segments)-1]
	fr.FunctionName = segments[len(segments)-2]
	if err := fr.readLatestPatchVersion(); err != nil {
		return nil, err
	}
	if err := fr.readDocPaths(); err != nil {
		return nil, err
	}
	return fr, nil
}

// readLatestPatchVersion of the release from git tags
func (fr *functionRelease) readLatestPatchVersion() error {
	if fr.FunctionName == "" || fr.MinorVersion == "" {
		return fmt.Errorf("missing function name and/or minor version")
	}
	patch, err := latestpatch.GetLatestPatch(fr.FunctionName, fr.MinorVersion)
	if err != nil {
		return err
	}
	fr.Language = patch.Lang
	fr.LatestPatchVersion = patch.LatestPatch
	return nil
}

// readDocPaths and set documentation paths
func (fr *functionRelease) readDocPaths() error {
	executablePath, err := os.Executable()
	if err != nil {
		return err
	}
	repoBase := filepath.Dir(filepath.Dir(filepath.Dir(executablePath)))
	pathsToTry := []struct {
		functionPath string
		examplesPath string
		isContrib    bool
	}{
		{
			functionPath: filepath.Join(repoBase, "functions", fr.Language, fr.FunctionName),
			examplesPath: filepath.Join(repoBase, "examples"),
			isContrib:    false,
		},
		{
			functionPath: filepath.Join(repoBase, "contrib", "functions", fr.Language, fr.FunctionName),
			examplesPath: filepath.Join(repoBase, "contrib", "examples"),
			isContrib:    true,
		},
	}
	var examplesPath string
	for _, pathToTry := range pathsToTry {
		if dirExists(pathToTry.functionPath) {
			fr.FunctionPath = pathToTry.functionPath
			fr.IsContrib = pathToTry.isContrib
			examplesPath = pathToTry.examplesPath
			break
		}
	}
	if fr.FunctionPath == "" {
		return fmt.Errorf("function doc paths not found from %+v", pathsToTry)
	}
	if err = fr.parseMetadata(examplesPath); err != nil {
		return err
	}
	return nil
}

// parseMetadata from metadata.yaml and set example paths
func (fr *functionRelease) parseMetadata(examplesPath string) error {
	type metadata struct {
		ExamplePackageUrls []string `yaml:"examplePackageURLs"`
	}
	if fr.FunctionPath == "" {
		return fmt.Errorf("expected FunctionPath in parseMetadata")
	}

	metadataPath := filepath.Join(fr.FunctionPath, "metadata.yaml")
	var md metadata
	yamlFile, err := ioutil.ReadFile(metadataPath)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(yamlFile, &md)
	if err != nil {
		return err
	}
	for _, exampleURL := range md.ExamplePackageUrls {
		segments := strings.Split(exampleURL, "/")
		exampleName := segments[len(segments)-1]
		examplePath := filepath.Join(examplesPath, exampleName)
		if !dirExists(examplePath) {
			return fmt.Errorf("example dir does not exist: %s", examplePath)
		}
		fr.Examples = append(fr.Examples, functionExample{
			ExamplePath: examplePath,
			ExampleName: exampleName,
		})
	}
	return nil
}

// updateDocs updates all the docs for the functionRelease on the filesystem
func (fr *functionRelease) updateDocs() error {
	if err := fr.updateFunctionDoc(); err != nil {
		return err
	}
	if err := fr.updateExampleDocs(); err != nil {
		return err
	}
	return nil
}

// updateFunctionDoc updates the function docs for the functionRelease
func (fr *functionRelease) updateFunctionDoc() error {
	functionReadme := filepath.Join(fr.FunctionPath, "README.md")
	if err := fr.updateDoc(functionReadme); err != nil {
		return err
	}
	functionMetadata := filepath.Join(fr.FunctionPath, "metadata.yaml")
	if err := fr.updateDoc(functionMetadata); err != nil {
		return err
	}
	return nil
}

// updateExampleDocs updates the example docs for the functionRelease
func (fr *functionRelease) updateExampleDocs() error {
	for _, example := range fr.Examples {
		exampleReadme := filepath.Join(example.ExamplePath, "README.md")
		if err := fr.updateDoc(exampleReadme); err != nil {
			return err
		}
		exampleKptfile := filepath.Join(example.ExamplePath, "Kptfile")
		if fileExists(exampleKptfile) {
			if err := fr.updateDoc(exampleKptfile); err != nil {
				return err
			}
		}
	}
	return nil
}

// Perform in place search/replace operations on a documentation file
func (fr *functionRelease) updateDoc(filePath string) error {
	contents, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	contents = fr.replaceTags(contents)
	contents = fr.replaceURLs(contents)
	contents = fr.replaceKptPackages(contents)
	contents = fr.replaceGithubURLs(contents)
	if err = os.WriteFile(filePath, contents, 0644); err != nil {
		return err
	}
	return nil
}

// replace tags with patch e.g. apply-setters:v1.0.1, apply-setters/v1.0.1
func (fr *functionRelease) replaceTags(contents []byte) []byte {
	tagPattern := regexp.MustCompile(
		fmt.Sprintf(`(%s)(:|/)(%s)`, fr.FunctionName, versionGroup))
	contents = tagPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}${2}%s`, fr.LatestPatchVersion)))
	return contents
}

// replace url with minor e.g. https://catalog.kpt.dev/apply-setters/v1.0
func (fr *functionRelease) replaceURLs(contents []byte) []byte {
	urlPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://catalog\.kpt\.dev/%s/)(%s)`, fr.FunctionName, versionGroup))
	contents = urlPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}%s`, fr.MinorVersion)))
	return contents
}

// get sub-path to examples e.g. examples, contrib/examples
func (fr *functionRelease) exampleSubPath() string {
	exampleSubPath := "examples"
	if fr.IsContrib {
		exampleSubPath = "contrib/examples"
	}
	return exampleSubPath
}

// replace kpt package names for all examples, e.g.
// https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/apply-setters-simple ->
// https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/apply-setters-simple@apply-setters/v1.0.1
func (fr *functionRelease) replaceKptPackages(contents []byte) []byte {
	exampleGroup := strings.Join(fr.Examples.exampleNames(), "|")
	exampleSubPath := fr.exampleSubPath()
	kptPkgPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://github\.com/GoogleContainerTools/kpt-functions-catalog\.git/%s/)(%s)(\s+)`,
			exampleSubPath, exampleGroup))
	contents = kptPkgPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}${2}@%s/%s${3}`, fr.FunctionName, fr.LatestPatchVersion)))
	return contents
}

// replace branch name with release branch for all GitHub URLs, e.g.
// https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/master/examples/set-namespace-simple ->
// https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/set-namespace/v0.2/examples/set-namespace-simple
func (fr *functionRelease) replaceGithubURLs(contents []byte) []byte {
	exampleSubPath := fr.exampleSubPath()
	sourceUrlSuffix := fmt.Sprintf(`/functions/%s/%s`, fr.Language, fr.FunctionName)
	if fr.IsContrib {
		sourceUrlSuffix = fmt.Sprintf(`/contrib/functions/%s/%s`, fr.Language, fr.FunctionName)
	}
	suffixes := []string{
		sourceUrlSuffix,
	}
	for _, ex := range fr.Examples.exampleNames() {
		suffixes = append(suffixes, fmt.Sprintf(`/%s/%s`, exampleSubPath, ex))
	}
	suffixGroup := strings.Join(suffixes, "|")
	refGroup := fmt.Sprintf(`master|%s/v\d*\.\d*`, fr.FunctionName)
	githubURLPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://github\.com/GoogleContainerTools/kpt-functions-catalog/tree/)(%s)(%s)`,
			refGroup, suffixGroup))
	contents = githubURLPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}%s/%s${3}`, fr.FunctionName, fr.MinorVersion)))
	return contents
}
<commit_msg>fix: properly set github urls to minor version (#821)<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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 main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/GoogleContainerTools/kpt-functions-catalog/scripts/patch_reader/pkg/latestpatch"
	"gopkg.in/yaml.v2"
)

var (
	// pattern of release branches, e.g. apply-setters/v1.0
	releaseBranchPattern = regexp.MustCompile(`[-\w]*/(v\d*\.\d*)`)
	// pattern for version tags, e.g. unstable, v0.1.1, v0.1
	versionGroup = `unstable|v\d*\.\d*\.\d*|v\d*\.\d*`
)

func dirExists(path string) bool {
	if stat, err := os.Stat(path); err == nil && stat.IsDir() {
		return true
	}
	return false
}

func fileExists(path string) bool {
	if _, err := os.Stat(path); err == nil {
		return true
	}
	return false
}

type functionExample struct {
	ExamplePath string
	ExampleName string
}

type functionExamples []functionExample

// exampleNames returns a list of the functionExample names
func (fe functionExamples) exampleNames() []string {
	var exampleNames []string
	for _, example := range fe {
		exampleNames = append(exampleNames, example.ExampleName)
	}
	return exampleNames
}

type functionRelease struct {
	FunctionName       string
	MinorVersion       string
	Language           string
	LatestPatchVersion string
	FunctionPath       string
	Examples           functionExamples
	IsContrib          bool
}

// newFunctionRelease allocates and initializes a functionRelease
func newFunctionRelease(branch string) (*functionRelease, error) {
	fr := &functionRelease{}
	if !releaseBranchPattern.MatchString(branch) {
		return nil, fmt.Errorf("invalid branch format")
	}
	segments := strings.Split(branch, "/")
	// assume branch format: */<func_name>/<minor_version>
	fr.MinorVersion = segments[len(segments)-1]
	fr.FunctionName = segments[len(segments)-2]
	if err := fr.readLatestPatchVersion(); err != nil {
		return nil, err
	}
	if err := fr.readDocPaths(); err != nil {
		return nil, err
	}
	return fr, nil
}

// readLatestPatchVersion of the release from git tags
func (fr *functionRelease) readLatestPatchVersion() error {
	if fr.FunctionName == "" || fr.MinorVersion == "" {
		return fmt.Errorf("missing function name and/or minor version")
	}
	patch, err := latestpatch.GetLatestPatch(fr.FunctionName, fr.MinorVersion)
	if err != nil {
		return err
	}
	fr.Language = patch.Lang
	fr.LatestPatchVersion = patch.LatestPatch
	return nil
}

// readDocPaths and set documentation paths
func (fr *functionRelease) readDocPaths() error {
	executablePath, err := os.Executable()
	if err != nil {
		return err
	}
	repoBase := filepath.Dir(filepath.Dir(filepath.Dir(executablePath)))
	pathsToTry := []struct {
		functionPath string
		examplesPath string
		isContrib    bool
	}{
		{
			functionPath: filepath.Join(repoBase, "functions", fr.Language, fr.FunctionName),
			examplesPath: filepath.Join(repoBase, "examples"),
			isContrib:    false,
		},
		{
			functionPath: filepath.Join(repoBase, "contrib", "functions", fr.Language, fr.FunctionName),
			examplesPath: filepath.Join(repoBase, "contrib", "examples"),
			isContrib:    true,
		},
	}
	var examplesPath string
	for _, pathToTry := range pathsToTry {
		if dirExists(pathToTry.functionPath) {
			fr.FunctionPath = pathToTry.functionPath
			fr.IsContrib = pathToTry.isContrib
			examplesPath = pathToTry.examplesPath
			break
		}
	}
	if fr.FunctionPath == "" {
		return fmt.Errorf("function doc paths not found from %+v", pathsToTry)
	}
	if err = fr.parseMetadata(examplesPath); err != nil {
		return err
	}
	return nil
}

// parseMetadata from metadata.yaml and set example paths
func (fr *functionRelease) parseMetadata(examplesPath string) error {
	type metadata struct {
		ExamplePackageUrls []string `yaml:"examplePackageURLs"`
	}
	if fr.FunctionPath == "" {
		return fmt.Errorf("expected FunctionPath in parseMetadata")
	}

	metadataPath := filepath.Join(fr.FunctionPath, "metadata.yaml")
	var md metadata
	yamlFile, err := ioutil.ReadFile(metadataPath)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(yamlFile, &md)
	if err != nil {
		return err
	}
	for _, exampleURL := range md.ExamplePackageUrls {
		segments := strings.Split(exampleURL, "/")
		exampleName := segments[len(segments)-1]
		examplePath := filepath.Join(examplesPath, exampleName)
		if !dirExists(examplePath) {
			return fmt.Errorf("example dir does not exist: %s", examplePath)
		}
		fr.Examples = append(fr.Examples, functionExample{
			ExamplePath: examplePath,
			ExampleName: exampleName,
		})
	}
	return nil
}

// updateDocs updates all the docs for the functionRelease on the filesystem
func (fr *functionRelease) updateDocs() error {
	if err := fr.updateFunctionDoc(); err != nil {
		return err
	}
	if err := fr.updateExampleDocs(); err != nil {
		return err
	}
	return nil
}

// updateFunctionDoc updates the function docs for the functionRelease
func (fr *functionRelease) updateFunctionDoc() error {
	functionReadme := filepath.Join(fr.FunctionPath, "README.md")
	if err := fr.updateDoc(functionReadme); err != nil {
		return err
	}
	functionMetadata := filepath.Join(fr.FunctionPath, "metadata.yaml")
	if err := fr.updateDoc(functionMetadata); err != nil {
		return err
	}
	return nil
}

// updateExampleDocs updates the example docs for the functionRelease
func (fr *functionRelease) updateExampleDocs() error {
	for _, example := range fr.Examples {
		exampleReadme := filepath.Join(example.ExamplePath, "README.md")
		if err := fr.updateDoc(exampleReadme); err != nil {
			return err
		}
		exampleKptfile := filepath.Join(example.ExamplePath, "Kptfile")
		if fileExists(exampleKptfile) {
			if err := fr.updateDoc(exampleKptfile); err != nil {
				return err
			}
		}
	}
	return nil
}

// Perform in place search/replace operations on a documentation file
func (fr *functionRelease) updateDoc(filePath string) error {
	contents, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	contents = fr.replaceTags(contents)
	contents = fr.replaceURLs(contents)
	contents = fr.replaceKptPackages(contents)
	contents = fr.replaceGithubURLs(contents)
	if err = os.WriteFile(filePath, contents, 0644); err != nil {
		return err
	}
	return nil
}

// replace tags with patch e.g. apply-setters:v1.0.1, apply-setters/v1.0.1
func (fr *functionRelease) replaceTags(contents []byte) []byte {
	tagPattern := regexp.MustCompile(
		fmt.Sprintf(`(%s)(:|/)(%s)`, fr.FunctionName, versionGroup))
	contents = tagPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}${2}%s`, fr.LatestPatchVersion)))
	return contents
}

// replace url with minor e.g. https://catalog.kpt.dev/apply-setters/v1.0
func (fr *functionRelease) replaceURLs(contents []byte) []byte {
	urlPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://catalog\.kpt\.dev/%s/)(%s)`, fr.FunctionName, versionGroup))
	contents = urlPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}%s`, fr.MinorVersion)))
	return contents
}

// get sub-path to examples e.g. examples, contrib/examples
func (fr *functionRelease) exampleSubPath() string {
	exampleSubPath := "examples"
	if fr.IsContrib {
		exampleSubPath = "contrib/examples"
	}
	return exampleSubPath
}

// replace kpt package names for all examples, e.g.
// https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/apply-setters-simple ->
// https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/apply-setters-simple@apply-setters/v1.0.1
func (fr *functionRelease) replaceKptPackages(contents []byte) []byte {
	exampleGroup := strings.Join(fr.Examples.exampleNames(), "|")
	exampleSubPath := fr.exampleSubPath()
	kptPkgPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://github\.com/GoogleContainerTools/kpt-functions-catalog\.git/%s/)(%s)(\s+)`,
			exampleSubPath, exampleGroup))
	contents = kptPkgPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}${2}@%s/%s${3}`, fr.FunctionName, fr.LatestPatchVersion)))
	return contents
}

// replace branch name with release branch for all GitHub URLs, e.g.
// https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/master/examples/set-namespace-simple ->
// https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/set-namespace/v0.2/examples/set-namespace-simple
func (fr *functionRelease) replaceGithubURLs(contents []byte) []byte {
	exampleSubPath := fr.exampleSubPath()
	sourceUrlSuffix := fmt.Sprintf(`/functions/%s/%s`, fr.Language, fr.FunctionName)
	if fr.IsContrib {
		sourceUrlSuffix = fmt.Sprintf(`/contrib/functions/%s/%s`, fr.Language, fr.FunctionName)
	}
	suffixes := []string{
		sourceUrlSuffix,
	}
	for _, ex := range fr.Examples.exampleNames() {
		suffixes = append(suffixes, fmt.Sprintf(`/%s/%s`, exampleSubPath, ex))
	}
	suffixGroup := strings.Join(suffixes, "|")
	refGroup := fmt.Sprintf(`master|%[1]s/v\d*\.\d*\.\d*|%[1]s/v\d*\.\d*`, fr.FunctionName)
	githubURLPattern := regexp.MustCompile(
		fmt.Sprintf(`(https://github\.com/GoogleContainerTools/kpt-functions-catalog/tree/)(%s)(%s)`,
			refGroup, suffixGroup))
	contents = githubURLPattern.ReplaceAll(contents,
		[]byte(fmt.Sprintf(`${1}%s/%s${3}`, fr.FunctionName, fr.MinorVersion)))
	return contents
}
<|endoftext|>


<commit_before>package main

//package memdb

import (
	"bytes"
	"fmt"
	"strconv"
	"time"
	"github.com/Workiva/go-datastructures/common"
	"github.com/Workiva/go-datastructures/btree/palm"

)

type iKey []byte

func NewKey(b... []byte) *iKey{
	buf := new(bytes.Buffer)
	buf.Write(int2byte(len(b[0])));
	if len(b) == 2 {
		buf.Write(int2byte(len(b[1])));
		}
	buf.Write(b[0]);
	if len(b) == 2 {
		buf.Write(b[1]);
		}
	ikey := iKey(buf.Bytes())
	return &ikey
}

func (i *iKey) To(key,value []byte) int {
	buf := new(bytes.Buffer)
	buf.Write(int2byte(len(key)))
	buf.Write(int2byte(len(value)))
	buf.Write(key)
	buf.Write(value)
	return buf.Len();
	}

func (i *iKey) From() (int,int,[]byte,[]byte) {
	k := byte2int((*i)[:4])
	v := byte2int((*i)[4:8])
	key := (*i)[8:8+k]
	value := (*i)[8+k:8+k+v]
	return k,v, key,value
	}

func (i *iKey) Key() []byte {
	//fmt.Println("Key:",i.iData)
	k := byte2int((*i)[:4])
	return (*i)[8:8+k]
	}

func (i *iKey) Value() []byte {
	k := byte2int((*i)[:4])
	v := byte2int((*i)[4:8])
	return (*i)[8+k:8+k+v]
	}

func (i iKey) Reset(){
	i=i[:0]
	}

func byte2int(b []byte) int {
	_ = b[3]
	return int(b[0]) | int(b[1])<<8 | int(b[2])<<15 | int(b[3])<<24
}

func int2byte(i int) []byte {
	b := make([]byte, 4)
	b[0] = byte(i)
	b[1] = byte(i >> 8)
	b[2] = byte(i >> 16)
	b[3] = byte(i >> 24)
	return b
}

func (a *iKey) Compare(b common.Comparator) int {
	return bytes.Compare(a.Key(),b.(*iKey).Key())
	}

type iKeys []iKey

type DB struct{
	tr palm.BTree
	}

func (db *DB) Delete(key []byte) []byte {
	db.tr.Delete(NewKey(key))
	return key;
	}

func (db *DB) Has(key []byte) bool {
	return db.tr.Get(NewKey(key))[0] != nil
	}

func (db *DB) Get(key []byte) []byte {
	fmt.Println("Get:",string(key));
	val := db.tr.Get(NewKey(key))
	fmt.Println("VAL:",val);
	if val[0] != nil {
		return val[0].(*iKey).Value()
		}
	return nil
	}

func (db *DB) Put(key,value []byte) {
	db.tr.Insert(NewKey(key,value))
	}

func NewDB() *DB {
	return &DB{tr:palm.New(1 << 12,1<<8)}

	}

func main() {

	rc := 333333
	db := NewDB()
	tp0 := time.Now()
	for i := 0; i < rc; i++ {
		s := strconv.Itoa(i)
		a, b := []byte("Iiiiiiiiiiii-"+s), []byte("Vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv-"+s)
		db.Put(a, b)
		a, b = []byte("Jjjjjjjjjjjjj-"+s), []byte("Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-"+s)
		db.Put(a, b)
		//fmt.Println("A,B:",d.iData)
		a, b = []byte("Kkkkkkkkkkkkk-"+s), []byte("Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy-"+s)
		db.Put(a, b)
	}
	m := make([][2]string, 0)
	m = append(m, [2]string{"abc2", "1234+2babc"})
	m = append(m, [2]string{"abc21", "1234_12babc"})
	m = append(m, [2]string{"abc", "1234"})
	m = append(m, [2]string{"abc85", "1234+85"})
	m = append(m, [2]string{"abc3", "1234+3"})
	m = append(m, [2]string{"abc7", "1234+7"})
	for i := range m {
		a := []byte(m[i][0])
		b := []byte(m[i][1])
		db.Put(a, b)
	}
	tp1 := time.Now()
	fmt.Printf("The call puted %v to run.\n", tp1.Sub(tp0))
	//sort.Sort(&ByKey{*n});
	a,b := []byte("Zzzzzzzzzzzzzzzzzzzz-" + strconv.Itoa(1)),[]byte("1234567890")
	db.Put(a,b)
	v := db.Get(a)
	fmt.Println("V:k", v)
	db.Delete(a)
	v = db.Get(a)
	fmt.Println("V:kd", v)
	a, b = []byte("abc2"), []byte("1234+2wwwwwwwwwwwwwwwwww")
	db.Put(a,b)
	v = db.Get(a)
	fmt.Println("V:a", v)
	a, b = []byte("abc2"), []byte("1234+23")
	db.Put(a,b)
	v = db.Get(a)
	fmt.Println("V:a", v)
	ln:=db.tr.Len()
	fmt.Println("Len():",ln);
	_=db.tr.Query(NewKey([]byte("abc")),NewKey([]byte("Zzzzzzzzzzzzzzzzzzzz-" + strconv.Itoa(1))));
	for i,j := 0,int(ln); i < j; i++ {
		//fmt.Println("Q:",string(q[i].(*iKey).Key()),string(q[i].(*iKey).Value()));
		}
}
<commit_msg>Add database prototype functions<commit_after>package main

//package memdb

import (
	"bytes"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"time"
	"github.com/Workiva/go-datastructures/common"
	"github.com/Workiva/go-datastructures/btree/palm"

)

type iKey []byte

type iKV struct{
	k,v []byte
}

func NewKey(b... []byte) *iKey{
	buf := new(bytes.Buffer)
	buf.Write(int2byte(len(b[0])));
	if len(b) == 2 {
		buf.Write(int2byte(len(b[1])));
		}
	buf.Write(b[0]);
	if len(b) == 2 {
		buf.Write(b[1]);
		}
	ikey := iKey(buf.Bytes())
	return &ikey
}

func (i *iKey) To(key,value []byte) int {
	buf := new(bytes.Buffer)
	buf.Write(int2byte(len(key)))
	buf.Write(int2byte(len(value)))
	buf.Write(key)
	buf.Write(value)
	return buf.Len();
	}

func (i *iKey) From() (int,int,[]byte,[]byte) {
	k := byte2int((*i)[:4])
	v := byte2int((*i)[4:8])
	key := (*i)[8:8+k]
	value := (*i)[8+k:8+k+v]
	return k,v, key,value
	}

func (i *iKey) Key() []byte {
	//fmt.Println("Key:",i.iData)
	k := byte2int((*i)[:4])
	return (*i)[8:8+k]
	}

func (i *iKey) Value() []byte {
	k := byte2int((*i)[:4])
	v := byte2int((*i)[4:8])
	return (*i)[8+k:8+k+v]
	}

func (i iKey) Reset(){
	i=i[:0]
	}

func byte2int(b []byte) int {
	_ = b[3]
	return int(b[0]) | int(b[1])<<8 | int(b[2])<<15 | int(b[3])<<24
}

func int2byte(i int) []byte {
	b := make([]byte, 4)
	b[0] = byte(i)
	b[1] = byte(i >> 8)
	b[2] = byte(i >> 16)
	b[3] = byte(i >> 24)
	return b
}

func (a *iKey) Compare(b common.Comparator) int {
	return bytes.Compare(a.Key(),b.(*iKey).Key())
	}

type iKeys []iKey

type DB struct{
	tr palm.BTree
	file *os.File
	}

func (db *DB) Open(path string) (error) {
	return nil
	}

func (db *DB) Close() {
	}

func (db *DB) load() (error) {
	return nil
	}

func (db *DB) save() (error) {
	return nil
	}

func (db *DB) sync() (error) {
	return nil
	}

func (db *DB) Delete(r ...iKV) {
	l := len(r)
	k := make([]common.Comparator,l);
	for i := 0; i < l; i++ {
		d := r[i]
		k[i] = NewKey(d.k,d.v)
		}
	db.tr.Delete(k...)
	}

func (db *DB) Get(r ...iKV) common.Comparators {
	l := len(r)
	k := make([]common.Comparator,l);
	for i := 0; i < l; i++ {
		d := r[i]
		k[i] = NewKey(d.k,d.v)
		}
	return db.tr.Get(k...)
	}

func (db *DB) Put(r ...iKV) {
	l := len(r)
	k := make([]common.Comparator,l);
	for i := 0; i < l; i++ {
		d := r[i]
		k[i] = NewKey(d.k,d.v)
		}
	db.tr.Insert(k...)
	}

type Options struct {
	bufSize uint64
	ary uint64
}

func defaultOptions() *Options {
	return &Options{bufSize:uint64(os.Getpagesize()),ary:uint64(runtime.NumCPU() << 2)}
}

func NewDB(opt *Options) *DB {
	return &DB{tr:palm.New(opt.bufSize,opt.ary)}

	}

func roundUp(v uint64) uint64 {
	v--
	v |= v >> 1
	v |= v >> 2
	v |= v >> 4
	v |= v >> 8
	v |= v >> 16
	v |= v >> 32
	v++
	return v
}

func main() {
	rc := 333
	opt := defaultOptions()
	//opt.bufSize = 1<<24
	fmt.Println("ROUNDUP",roundUp(1<<12),*opt);
	db := NewDB(opt)
	keys := make([]iKV,0);
	for i := 0; i < rc; i++ {
		s := strconv.Itoa(i)
		a, b := []byte("Iiiiiiiiiiii-"+s), []byte("Vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv-"+s)
		keys = append(keys,iKV{a,b});
		a, b = []byte("Jjjjjjjjjjjjj-"+s), []byte("Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-"+s)
		keys = append(keys,iKV{a,b});
		//fmt.Println("A,B:",d.iData)
		a, b = []byte("Kkkkkkkkkkkkk-"+s), []byte("Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy-"+s)
		keys = append(keys,iKV{a,b});
	}
	tp0 := time.Now()
	m := make([][2]string, 0)
	m = append(m, [2]string{"abc2", "1234+2babc"})
	m = append(m, [2]string{"abc21", "1234_12babc"})
	m = append(m, [2]string{"abc", "1234"})
	m = append(m, [2]string{"abc85", "1234+85"})
	m = append(m, [2]string{"abc3", "1234+3"})
	m = append(m, [2]string{"abc7", "1234+7"})
	for i := range m {
		a := []byte(m[i][0])
		b := []byte(m[i][1])
		keys = append(keys,iKV{a,b});
	}
	db.Put(keys...)
	tp1 := time.Now()
	fmt.Printf("The call puted %v to run.\n", tp1.Sub(tp0))
	//sort.Sort(&ByKey{*n});
	a,b := []byte("Iiiiiiiiiiii-" + strconv.Itoa(1)),[]byte("1234567890")
	v := db.Get(iKV{a,b})
	fmt.Println("V:k", v)
	db.Delete(iKV{a,b})
	v = db.Get(iKV{a,b})
	fmt.Println("V:kd", v)
	a, b = []byte("abc2"), []byte("1234+2wwwwwwwwwwwwwwwwww")
	keys = append(keys,iKV{a,b});
	v = db.Get(iKV{a,b})
	fmt.Println("V:a", string(v[0].(*iKey).Value()))
	a, b = []byte("abc2"), []byte("1234+23")
	keys = append(keys,iKV{a,b});
	v = db.Get(iKV{a,b})
	fmt.Println("V:a", string(v[0].(*iKey).Value()))
	ln:=db.tr.Len()
	fmt.Println("Len():",ln);
	_=db.tr.Query(NewKey([]byte("abc")),NewKey([]byte("Zzzzzzzzzzzzzzzzzzzz-" + strconv.Itoa(1))));
	for i,j := 0,int(ln); i < j; i++ {
		//fmt.Println("Q:",string(q[i].(*iKey).Key()),string(q[i].(*iKey).Value()));
		}
}
<|endoftext|>


<commit_before>package system

import (
	"fmt"
	"syscall"
)

func VersionDump() (string, error) {
	dll := syscall.MustLoadDLL("kernel32.dll")
	p := dll.MustFindProc("GetVersion")
	v, _, _ := p.Call()

	return fmt.Sprintf("Windows version %d.%d (Build %d)\n", byte(v), uint8(v>>8), uint16(v>>16)), nil
}
<commit_msg>Update VersionDump signature for windows<commit_after>package system

import (
	"fmt"
	"syscall"

	"github.com/buildkite/agent/logger"
)

func VersionDump(_ *logger.Logger) (string, error) {
	dll := syscall.MustLoadDLL("kernel32.dll")
	p := dll.MustFindProc("GetVersion")
	v, _, _ := p.Call()

	return fmt.Sprintf("Windows version %d.%d (Build %d)\n", byte(v), uint8(v>>8), uint16(v>>16)), nil
}
<|endoftext|>


<commit_before>package procstat

import (
	"fmt"
	"io/ioutil"
	"log"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"github.com/shirou/gopsutil/process"

	"github.com/influxdb/telegraf/plugins"
)

type Specification struct {
	PidFile string `toml:"pid_file"`
	Exe     string
	Prefix  string
}

type Procstat struct {
	Specifications []*Specification
}

func NewProcstat() *Procstat {
	return &Procstat{}
}

var sampleConfig = `
	[[procstat.specifications]]
	prefix = "" # optional string to prefix measurements
	# Use one of pid_file or exe to find process
	pid_file = "/var/run/nginx.pid"
	# executable name (used by pgrep)
	# exe = "nginx"
`

func (_ *Procstat) SampleConfig() string {
	return sampleConfig
}

func (_ *Procstat) Description() string {
	return "Monitor process cpu and memory usage"
}

func (p *Procstat) Gather(acc plugins.Accumulator) error {
	var wg sync.WaitGroup

	for _, specification := range p.Specifications {
		wg.Add(1)
		go func(spec *Specification, acc plugins.Accumulator) {
			defer wg.Done()
			procs, err := spec.createProcesses()
			if err != nil {
				log.Printf("Error: procstat getting process, exe: %s, pidfile: %s, %s",
					spec.Exe, spec.PidFile, err.Error())
			} else {
				for _, proc := range procs {
					p := NewSpecProcessor(spec.Prefix, acc, proc)
					p.pushMetrics()
				}
			}
		}(specification, acc)
	}
	wg.Wait()

	return nil
}

func (spec *Specification) createProcesses() ([]*process.Process, error) {
	var out []*process.Process
	var errstring string
	var outerr error
	var pids []int32

	if spec.PidFile != "" {
		pid, err := pidFromFile(spec.PidFile)
		if err != nil {
			errstring += err.Error() + " "
		} else {
			pids = append(pids, int32(pid))
		}
	} else if spec.Exe != "" {
		exepids, err := pidsFromExe(spec.Exe)
		if err != nil {
			errstring += err.Error() + " "
		}
		pids = append(pids, exepids...)
	} else {
		errstring += fmt.Sprintf("Either exe or pid_file has to be specified")
	}

	for _, pid := range pids {
		p, err := process.NewProcess(int32(pid))
		if err == nil {
			out = append(out, p)
		} else {
			errstring += err.Error() + " "
		}
	}

	if errstring != "" {
		outerr = fmt.Errorf("%s", errstring)
	}

	return out, outerr
}

func pidFromFile(file string) (int, error) {
	pidString, err := ioutil.ReadFile(file)
	if err != nil {
		return -1, fmt.Errorf("Failed to read pidfile '%s'. Error: '%s'", file, err)
	} else {
		return strconv.Atoi(strings.TrimSpace(string(pidString)))
	}
}

func pidsFromExe(exe string) ([]int32, error) {
	var out []int32
	var outerr error
	pgrep, err := exec.Command("pgrep", exe).Output()
	if err != nil {
		return out, fmt.Errorf("Failed to execute pgrep. Error: '%s'", err)
	} else {
		pids := strings.Fields(string(pgrep))
		for _, pid := range pids {
			ipid, err := strconv.Atoi(pid)
			if err == nil {
				out = append(out, int32(ipid))
			} else {
				outerr = err
			}
		}
	}
	return out, outerr
}

func init() {
	plugins.Add("procstat", func() plugins.Plugin {
		return NewProcstat()
	})
}
<commit_msg>procstat plugin, consolidate PID-getting<commit_after>package procstat

import (
	"fmt"
	"io/ioutil"
	"log"
	"os/exec"
	"strconv"
	"strings"
	"sync"

	"github.com/shirou/gopsutil/process"

	"github.com/influxdb/telegraf/plugins"
)

type Specification struct {
	PidFile string `toml:"pid_file"`
	Exe     string
	Prefix  string
}

type Procstat struct {
	Specifications []*Specification
}

func NewProcstat() *Procstat {
	return &Procstat{}
}

var sampleConfig = `
	[[procstat.specifications]]
	prefix = "" # optional string to prefix measurements
	# Use one of pid_file or exe to find process
	pid_file = "/var/run/nginx.pid"
	# executable name (used by pgrep)
	# exe = "nginx"
`

func (_ *Procstat) SampleConfig() string {
	return sampleConfig
}

func (_ *Procstat) Description() string {
	return "Monitor process cpu and memory usage"
}

func (p *Procstat) Gather(acc plugins.Accumulator) error {
	var wg sync.WaitGroup

	for _, specification := range p.Specifications {
		wg.Add(1)
		go func(spec *Specification, acc plugins.Accumulator) {
			defer wg.Done()
			procs, err := spec.createProcesses()
			if err != nil {
				log.Printf("Error: procstat getting process, exe: [%s] pidfile: [%s] %s",
					spec.Exe, spec.PidFile, err.Error())
			} else {
				for _, proc := range procs {
					p := NewSpecProcessor(spec.Prefix, acc, proc)
					p.pushMetrics()
				}
			}
		}(specification, acc)
	}
	wg.Wait()

	return nil
}

func (spec *Specification) createProcesses() ([]*process.Process, error) {
	var out []*process.Process
	var errstring string
	var outerr error

	pids, err := spec.getAllPids()
	if err != nil {
		errstring += err.Error() + " "
	}

	for _, pid := range pids {
		p, err := process.NewProcess(int32(pid))
		if err == nil {
			out = append(out, p)
		} else {
			errstring += err.Error() + " "
		}
	}

	if errstring != "" {
		outerr = fmt.Errorf("%s", errstring)
	}

	return out, outerr
}

func (spec *Specification) getAllPids() ([]int32, error) {
	var pids []int32
	var err error

	if spec.PidFile != "" {
		pids, err = pidsFromFile(spec.PidFile)
	} else if spec.Exe != "" {
		pids, err = pidsFromExe(spec.Exe)
	} else {
		err = fmt.Errorf("Either exe or pid_file has to be specified")
	}

	return pids, err
}

func pidsFromFile(file string) ([]int32, error) {
	var out []int32
	var outerr error
	pidString, err := ioutil.ReadFile(file)
	if err != nil {
		outerr = fmt.Errorf("Failed to read pidfile '%s'. Error: '%s'", file, err)
	} else {
		pid, err := strconv.Atoi(strings.TrimSpace(string(pidString)))
		if err != nil {
			outerr = err
		} else {
			out = append(out, int32(pid))
		}
	}
	return out, outerr
}

func pidsFromExe(exe string) ([]int32, error) {
	var out []int32
	var outerr error
	pgrep, err := exec.Command("pgrep", exe).Output()
	if err != nil {
		return out, fmt.Errorf("Failed to execute pgrep. Error: '%s'", err)
	} else {
		pids := strings.Fields(string(pgrep))
		for _, pid := range pids {
			ipid, err := strconv.Atoi(pid)
			if err == nil {
				out = append(out, int32(ipid))
			} else {
				outerr = err
			}
		}
	}
	return out, outerr
}

func init() {
	plugins.Add("procstat", func() plugins.Plugin {
		return NewProcstat()
	})
}
<|endoftext|>


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

package models

type AccessMode int

const (
	ACCESS_MODE_NONE AccessMode = iota
	ACCESS_MODE_READ
	ACCESS_MODE_WRITE
	ACCESS_MODE_ADMIN
	ACCESS_MODE_OWNER
)

// Access represents the highest access level of a user to the repository. The only access type
// that is not in this table is the real owner of a repository. In case of an organization
// repository, the members of the owners team are in this table.
type Access struct {
	ID     int64 `xorm:"pk autoincr"`
	UserID int64 `xorm:"UNIQUE(s)"`
	RepoID int64 `xorm:"UNIQUE(s)"`
	Mode   AccessMode
}

// Return the Access a user has to a repository. Will return NoneAccess if the
// user does not have access. User can be nil!
func AccessLevel(u *User, r *Repository) (AccessMode, error) {
	mode := ACCESS_MODE_NONE
	if !r.IsPrivate {
		mode = ACCESS_MODE_READ
	}

	if u != nil {
		if u.Id == r.OwnerId {
			return ACCESS_MODE_OWNER, nil
		}

		a := &Access{UserID: u.Id, RepoID: r.Id}
		if has, err := x.Get(a); !has || err != nil {
			return mode, err
		}
		return a.Mode, nil
	}

	return mode, nil
}

// HasAccess returns true if someone has the request access level. User can be nil!
func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) {
	mode, err := AccessLevel(u, r)
	return testMode <= mode, err
}

// GetAccessibleRepositories finds all repositories where a user has access to,
// besides his own.
func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
	accesses := make([]*Access, 0, 10)
	if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
		return nil, err
	}

	repos := make(map[*Repository]AccessMode, len(accesses))
	for _, access := range accesses {
		repo, err := GetRepositoryById(access.RepoID)
		if err != nil {
			return nil, err
		}
		if err = repo.GetOwner(); err != nil {
			return nil, err
		} else if repo.OwnerId == u.Id {
			continue
		}
		repos[repo] = access.Mode
	}

	return repos, nil
}

func maxAccessMode(modes ...AccessMode) AccessMode {
	max := ACCESS_MODE_NONE
	for _, mode := range modes {
		if mode > max {
			max = mode
		}
	}
	return max
}

func (repo *Repository) recalculateAccesses(e Engine) error {
	accessMap := make(map[int64]AccessMode, 20)

	// Give all collaborators write access
	collaborators, err := repo.getCollaborators(e)
	if err != nil {
		return err
	}
	for _, c := range collaborators {
		accessMap[c.Id] = ACCESS_MODE_WRITE
	}

	if err := repo.getOwner(e); err != nil {
		return err
	}
	if repo.Owner.IsOrganization() {
		if err = repo.Owner.getTeams(e); err != nil {
			return err
		}

		for _, team := range repo.Owner.Teams {
			if !(team.IsOwnerTeam() || team.HasRepository(repo)) {
				continue
			}

			if err = team.getMembers(e); err != nil {
				return err
			}
			for _, u := range team.Members {
				accessMap[u.Id] = maxAccessMode(accessMap[u.Id], team.Authorize)
			}
		}
	}

	minMode := ACCESS_MODE_READ
	if !repo.IsPrivate {
		minMode = ACCESS_MODE_WRITE
	}

	newAccesses := make([]Access, 0, len(accessMap))
	for userID, mode := range accessMap {
		if userID == repo.OwnerId || mode <= minMode {
			continue
		}
		newAccesses = append(newAccesses, Access{
			UserID: userID,
			RepoID: repo.Id,
			Mode:   mode})
	}

	// Delete old accesses for repository
	if _, err = e.Delete(&Access{RepoID: repo.Id}); err != nil {
		return err
	}

	// And insert the new ones
	if _, err = e.Insert(newAccesses); err != nil {
		return err
	}

	return nil
}

// RecalculateAccesses recalculates all accesses for repository.
func (r *Repository) RecalculateAccesses() error {
	return r.recalculateAccesses(x)
}
<commit_msg>some fixes, but not done yet!<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models

type AccessMode int

const (
	ACCESS_MODE_NONE AccessMode = iota
	ACCESS_MODE_READ
	ACCESS_MODE_WRITE
	ACCESS_MODE_ADMIN
	ACCESS_MODE_OWNER
)

// Access represents the highest access level of a user to the repository. The only access type
// that is not in this table is the real owner of a repository. In case of an organization
// repository, the members of the owners team are in this table.
type Access struct {
	ID     int64 `xorm:"pk autoincr"`
	UserID int64 `xorm:"UNIQUE(s)"`
	RepoID int64 `xorm:"UNIQUE(s)"`
	Mode   AccessMode
}

// Return the Access a user has to a repository. Will return NoneAccess if the
// user does not have access. User can be nil!
func AccessLevel(u *User, r *Repository) (AccessMode, error) {
	mode := ACCESS_MODE_NONE
	if !r.IsPrivate {
		mode = ACCESS_MODE_READ
	}

	if u != nil {
		if u.Id == r.OwnerId {
			return ACCESS_MODE_OWNER, nil
		}

		a := &Access{UserID: u.Id, RepoID: r.Id}
		if has, err := x.Get(a); !has || err != nil {
			return mode, err
		}
		return a.Mode, nil
	}

	return mode, nil
}

// HasAccess returns true if someone has the request access level. User can be nil!
func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) {
	mode, err := AccessLevel(u, r)
	return testMode <= mode, err
}

// GetAccessibleRepositories finds all repositories where a user has access to,
// besides his own.
func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
	accesses := make([]*Access, 0, 10)
	if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
		return nil, err
	}

	repos := make(map[*Repository]AccessMode, len(accesses))
	for _, access := range accesses {
		repo, err := GetRepositoryById(access.RepoID)
		if err != nil {
			return nil, err
		}
		if err = repo.GetOwner(); err != nil {
			return nil, err
		} else if repo.OwnerId == u.Id {
			continue
		}
		repos[repo] = access.Mode
	}

	return repos, nil
}

func maxAccessMode(modes ...AccessMode) AccessMode {
	max := ACCESS_MODE_NONE
	for _, mode := range modes {
		if mode > max {
			max = mode
		}
	}
	return max
}

func (repo *Repository) recalculateTeamAccesses(e Engine, mode AccessMode) error {

	return nil
}

func (repo *Repository) recalculateAccesses(e Engine) error {
	accessMap := make(map[int64]AccessMode, 20)

	// Give all collaborators write access
	collaborators, err := repo.getCollaborators(e)
	if err != nil {
		return err
	}
	for _, c := range collaborators {
		accessMap[c.Id] = ACCESS_MODE_WRITE
	}

	if err := repo.getOwner(e); err != nil {
		return err
	}
	if repo.Owner.IsOrganization() {
		if err = repo.Owner.getTeams(e); err != nil {
			return err
		}

		for _, team := range repo.Owner.Teams {
			if !(team.IsOwnerTeam() || team.HasRepository(repo)) {
				continue
			} else if team.IsOwnerTeam() {
				team.Authorize = ACCESS_MODE_OWNER
			}

			if err = team.getMembers(e); err != nil {
				return err
			}
			for _, u := range team.Members {
				accessMap[u.Id] = maxAccessMode(accessMap[u.Id], team.Authorize)
			}
		}
	}

	minMode := ACCESS_MODE_READ
	if !repo.IsPrivate {
		minMode = ACCESS_MODE_WRITE
	}

	newAccesses := make([]Access, 0, len(accessMap))
	for userID, mode := range accessMap {
		if mode < minMode {
			continue
		}
		newAccesses = append(newAccesses, Access{
			UserID: userID,
			RepoID: repo.Id,
			Mode:   mode,
		})
	}

	// Delete old accesses and insert new ones for repository.
	if _, err = e.Delete(&Access{RepoID: repo.Id}); err != nil {
		return err
	} else if _, err = e.Insert(newAccesses); err != nil {
		return err
	}

	return nil
}

// RecalculateAccesses recalculates all accesses for repository.
func (r *Repository) RecalculateAccesses() error {
	return r.recalculateAccesses(x)
}
<|endoftext|>


<commit_before>package available_topics

import (
	"log"

	"github.com/bulletind/khabar/db"
	"github.com/bulletind/khabar/dbapi/topics"
	"github.com/bulletind/khabar/utils"
)

func GetAppTopics(app_name, org string) []string {
	session := db.Conn.Session.Copy()
	defer session.Close()

	query := utils.M{"app_name": app_name}
	topics := []string{}

	err := db.Conn.GetCursor(session, db.AvailableTopicCollection, query).Distinct("ident", &topics)
	if err != nil {
		log.Println(err)
	}

	return topics
}

type ChotaTopic map[string]string

func GetAll(user, app_name, org string, channels []string) (map[string]ChotaTopic, error) {
	appTopics := GetAppTopics(app_name, org)
	topicMap := map[string]ChotaTopic{}

	for _, ident := range appTopics {
		ct := ChotaTopic{"topic": ident}
		for _, channel := range channels {
			ct[channel] = "true"
		}

		topicMap[ident] = ct
	}

	disabled := new(topics.Topic)

	session := db.Conn.Session.Copy()
	defer session.Close()

	query := utils.M{
		"ident": utils.M{"$in": appTopics},
		"user":  user,
		"org":   org,
	}

	userBlacklisted := db.Conn.GetCursor(session, db.TopicCollection, query).Iter()
	for userBlacklisted.Next(disabled) {
		if _, ok := topicMap[disabled.Ident]; ok {
			for _, blocked := range disabled.Channels {
				topicMap[disabled.Ident][blocked] = "false"
			}
		}
	}

	query["user"] = db.BLANK

	orgBlacklisted := db.Conn.GetCursor(session, db.TopicCollection, query).Iter()
	for orgBlacklisted.Next(disabled) {
		if _, ok := topicMap[disabled.Ident]; ok {
			for _, blocked := range disabled.Channels {
				topicMap[disabled.Ident][blocked] = "disabled"
			}
		}
	}

	return topicMap, nil
}

func Get(topic string) (found *db.AvailableTopic, err error) {
	found = new(db.AvailableTopic)

	err = db.Conn.GetOne(db.AvailableTopicCollection, utils.M{"ident": topic}, found)

	if err != nil {
		return nil, err
	}

	return found, nil
}

func Insert(newTopic *db.AvailableTopic) string {
	return db.Conn.Insert(db.AvailableTopicCollection, newTopic)
}

func Delete(doc *utils.M) error {
	return db.Conn.Delete(db.AvailableTopicCollection, *doc)
}
<commit_msg>Merging file from upstream<commit_after>package available_topics

import (
	"log"

	"github.com/bulletind/khabar/db"
	"github.com/bulletind/khabar/dbapi/topics"
	"github.com/bulletind/khabar/utils"
)

const falseState = "false"
const disabledState = "disabled"

type ChotaTopic map[string]string

func GetAppTopics(app_name, org string) []string {
	session := db.Conn.Session.Copy()
	defer session.Close()

	query := utils.M{"app_name": app_name}
	topics := []string{}

	err := db.Conn.GetCursor(session, db.AvailableTopicCollection, query).Distinct("ident", &topics)
	if err != nil {
		log.Println(err)
	}

	return topics
}

func GetAll(user, app_name, org string, channels []string) (map[string]ChotaTopic, error) {
	appTopics := GetAppTopics(app_name, org)
	topicMap := map[string]ChotaTopic{}

	for _, ident := range appTopics {
		ct := ChotaTopic{"topic": ident}
		for _, channel := range channels {
			ct[channel] = "true"
		}

		topicMap[ident] = ct
	}

	disabled := new(topics.Topic)

	session := db.Conn.Session.Copy()
	defer session.Close()

	query := utils.M{
		"ident": utils.M{"$in": appTopics},
		"user":  user,
		"org":   org,
	}

	pass1 := db.Conn.GetCursor(session, db.TopicCollection, query).Iter()
	for pass1.Next(disabled) {
		if _, ok := topicMap[disabled.Ident]; ok {
			for _, blocked := range disabled.Channels {
				topicMap[disabled.Ident][blocked] = falseState
			}
		}
	}

	if user != db.BLANK {
		//Only execute this if the user was indeed passed.

		query["user"] = db.BLANK

		pass2 := db.Conn.GetCursor(session, db.TopicCollection, query).Iter()
		for pass2.Next(disabled) {
			if _, ok := topicMap[disabled.Ident]; ok {
				for _, blocked := range disabled.Channels {
					topicMap[disabled.Ident][blocked] = disabledState
				}
			}
		}
	}

	return topicMap, nil
}

func Get(topic string) (found *db.AvailableTopic, err error) {
	found = new(db.AvailableTopic)

	err = db.Conn.GetOne(db.AvailableTopicCollection, utils.M{"ident": topic}, found)

	if err != nil {
		return nil, err
	}

	return found, nil
}

func Insert(newTopic *db.AvailableTopic) string {
	return db.Conn.Insert(db.AvailableTopicCollection, newTopic)
}

func Delete(doc *utils.M) error {
	return db.Conn.Delete(db.AvailableTopicCollection, *doc)
}
<|endoftext|>