<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/BurntSushi/toml"
)

//VERSION of the program
var version = "undefined-autogenerated"

var globalScanRange string
var globalScanIntervall int

//Config data struct to read the config file
type Config struct {
	NMAPRange     string
	HTTPPort      int
	ScanIntervall int //seconds
}

//ReadConfig reads the config file
func ReadConfig() Config {
	var configfile = "/etc/lan-monitor.conf"
	_, err := os.Stat(configfile)
	if err != nil {
		log.Fatal("Config file is missing: ", configfile)
	}

	var config Config
	if _, err := toml.DecodeFile(configfile, &config); err != nil {
		log.Fatal(err)
	}
	return config
}

func callNMAP() {
	log.Println("Starting nmap caller")
	var Counter = 1
	var tempScanFileName = "temp_scan.xml"
	var scanResultsFileName = "scan.xml"
	for {
		log.Println("Init NMAP scan no:", Counter)
		cmd := exec.Command("nmap", "-p", "22,80", "-oX", tempScanFileName, globalScanRange)
		cmd.Stdin = strings.NewReader("some input")
		var out bytes.Buffer
		cmd.Stdout = &out
		err := cmd.Run()
		if err != nil {
			log.Println(err)
		}
		log.Println("Scan no.", Counter, "complete")
		//log.Printf("in all caps: %q\n", out.String())
		Counter = Counter + 1

		//copy to the scan.xml
		r, err := os.Open(tempScanFileName)
		if err != nil {
			panic(err)
		}
		defer r.Close()

		w, err := os.Create(scanResultsFileName)
		if err != nil {
			panic(err)
		}
		defer w.Close()

		// do the actual work
		n, err := io.Copy(w, r)
		if err != nil {
			panic(err)
		}
		log.Printf("Scan results saved %v bytes\n", n)
		<-time.After(time.Duration(globalScanIntervall) * time.Second)
	}
}

func pageHandler(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path[1:]
	log.Println("URL path: " + path)

	//in case we have no path refer/redirect to index.html
	if len(path) == 0 {
		path = "index.html"
	}

	f, err := os.Open(path)
	if err == nil {
		Reader := bufio.NewReader(f)

		var contentType string

		if strings.HasSuffix(path, "css") {
			contentType = "text/css"
		} else if strings.HasSuffix(path, ".html") {
			contentType = "text/html"
		} else if strings.HasSuffix(path, ".js") {
			contentType = "application/javascript"
		} else if strings.HasSuffix(path, ".png") {
			contentType = "image/png"
		} else if strings.HasSuffix(path, ".svg") {
			contentType = "image/svg+xml"
		} else {
			contentType = "text/plain"
		}

		w.Header().Add("Content Type", contentType)
		Reader.WriteTo(w)
	} else {
		w.WriteHeader(404)
		fmt.Fprintln(w, "404 - Page not found"+http.StatusText(404))
	}
}

func main() {
	log.Println("Starting lan-monitor-server ver: " + version)

	//process the config
	//first the config file is read if parameters not set the defaults are used
	//if command line parameters are set the config file will be ignored

	//defaults
	var config Config
	config.HTTPPort = 8080
	config.NMAPRange = "192.168.1.1/24"
	config.ScanIntervall = 120 //seconds

	//read the configfile
	config = ReadConfig()

	displayVersion := flag.Bool("version", false, "Prints the version number")
	httpPort := flag.Int("port", config.HTTPPort, "HTTP port for the webserver (some ports e.g. 80 require su permissions)")
	nmapScanRange := flag.String("range", config.NMAPRange, "The range NMAP should scan e.g. 192.168.1.1/24 it has to be nmap compatible")
	scanIntervall := flag.Int("scan_rate", config.ScanIntervall, "The intervall of the scans in seconds")
	flag.Parse()

	globalScanRange = *nmapScanRange
	globalScanIntervall = *scanIntervall
	log.Println("Config - range:", globalScanRange, "port:", *httpPort, "intervall:", globalScanIntervall, "sec")

	if *displayVersion == true {
		fmt.Println("Version: " + version)
		return
	}

	//changing working dir
	log.Println("Changing working dir to: ")
	err := os.Chdir("../www")
	if err != nil {
		log.Fatalln("Unable to switch working dir")
	}

	workingDir, _ := os.Getwd()
	log.Println("Dir:" + workingDir)

	//init the scanning routine
	go callNMAP()

	//starting the webserver
	http.HandleFunc("/", pageHandler)
	err = http.ListenAndServe(":"+strconv.Itoa(*httpPort), nil)
	if err != nil {
		log.Println("Server error - " + err.Error())
	}
}
<commit_msg>config file and comd line parsing<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/BurntSushi/toml"
)

//VERSION of the program
var version = "undefined-autogenerated"

var globalScanRange string
var globalScanIntervall int

//Config data struct to read the config file
type Config struct {
	NMAPRange     string
	HTTPPort      int
	ScanIntervall int //seconds
}

//ReadConfig reads the config file
func ReadConfig(configfile string) Config {
	_, err := os.Stat(configfile)
	if err != nil {
		log.Fatal("Config file is missing: ", configfile)
	}

	var config Config
	if _, err := toml.DecodeFile(configfile, &config); err != nil {
		log.Fatal(err)
	}
	return config
}

func callNMAP() {
	log.Println("Starting nmap caller")
	var Counter = 1
	var tempScanFileName = "temp_scan.xml"
	var scanResultsFileName = "scan.xml"
	for {
		log.Println("Init NMAP scan no:", Counter)
		cmd := exec.Command("nmap", "-p", "22,80", "-oX", tempScanFileName, globalScanRange)
		cmd.Stdin = strings.NewReader("some input")
		var out bytes.Buffer
		cmd.Stdout = &out
		err := cmd.Run()
		if err != nil {
			log.Println(err)
		}
		log.Println("Scan no.", Counter, "complete")
		//log.Printf("in all caps: %q\n", out.String())
		Counter = Counter + 1

		//copy to the scan.xml
		r, err := os.Open(tempScanFileName)
		if err != nil {
			panic(err)
		}
		defer r.Close()

		w, err := os.Create(scanResultsFileName)
		if err != nil {
			panic(err)
		}
		defer w.Close()

		// do the actual work
		n, err := io.Copy(w, r)
		if err != nil {
			panic(err)
		}
		log.Printf("Scan results saved %v bytes\n", n)
		<-time.After(time.Duration(globalScanIntervall) * time.Second)
	}
}

func pageHandler(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path[1:]
	log.Println("URL path: " + path)

	//in case we have no path refer/redirect to index.html
	if len(path) == 0 {
		path = "index.html"
	}

	f, err := os.Open(path)
	if err == nil {
		Reader := bufio.NewReader(f)

		var contentType string

		if strings.HasSuffix(path, "css") {
			contentType = "text/css"
		} else if strings.HasSuffix(path, ".html") {
			contentType = "text/html"
		} else if strings.HasSuffix(path, ".js") {
			contentType = "application/javascript"
		} else if strings.HasSuffix(path, ".png") {
			contentType = "image/png"
		} else if strings.HasSuffix(path, ".svg") {
			contentType = "image/svg+xml"
		} else {
			contentType = "text/plain"
		}

		w.Header().Add("Content Type", contentType)
		Reader.WriteTo(w)
	} else {
		w.WriteHeader(404)
		fmt.Fprintln(w, "404 - Page not found"+http.StatusText(404))
	}
}

func main() {
	log.Println("Starting lan-monitor-server ver: " + version)

	//process the config
	//1st the config file is read and set parameters applied
	//2nd the command line parameters are interpreted,
	//if they are set they will overrule the config file
	//3rd if none of the above is applied the program reverts to the hardcoded defaults

	//defaults
	var config Config
	defaultConfigFileLocation := "/etc/lan-monitor/config"
	config.HTTPPort = 8080
	config.NMAPRange = "192.168.1.1/24"
	config.ScanIntervall = 120 //seconds

	displayVersion := flag.Bool("version", false, "Prints the version number")
	cmdlineHTTPPort := flag.Int("port", config.HTTPPort, "HTTP port for the webserver")
	cmdlineNMAPScanRange := flag.String("range", config.NMAPRange, "The range NMAP should scan e.g. 192.168.1.1/24 it has to be nmap compatible")
	cmdlineScanIntervall := flag.Int("scan-rate", config.ScanIntervall, "The intervall of the scans in seconds")
	configFileLocation := flag.String("config-file", defaultConfigFileLocation, "Location of the config file")
	flag.Parse()

	//read the configfile
	config = ReadConfig(*configFileLocation)

	//if no range is defined in the config file
	if config.NMAPRange == "" {
		globalScanRange = *cmdlineNMAPScanRange
	} else {
		globalScanRange = config.NMAPRange
	}

	//if no port is defined in the config file
	if config.HTTPPort == 0 {
		config.HTTPPort = *cmdlineHTTPPort
	}

	//if no scan intervall is defined in the config file
	if config.ScanIntervall == 0 {
		globalScanIntervall = *cmdlineScanIntervall
	} else {
		globalScanIntervall = config.ScanIntervall
	}

	log.Println("Config - range:", globalScanRange, "port:", config.HTTPPort, "intervall:", globalScanIntervall, "sec")

	if *displayVersion == true {
		fmt.Println("Version: " + version)
		return
	}

	//changing working dir
	log.Println("Changing working dir to: ")
	err := os.Chdir("../www")
	if err != nil {
		log.Fatalln("Unable to switch working dir")
	}

	workingDir, _ := os.Getwd()
	log.Println("Dir:" + workingDir)

	//init the scanning routine
	go callNMAP()

	//starting the webserver
	http.HandleFunc("/", pageHandler)
	err = http.ListenAndServe(":"+strconv.Itoa(config.HTTPPort), nil)
	if err != nil {
		log.Println("Server error - " + err.Error())
	}
}
<|endoftext|>


<commit_before>package ebpf

import (
	"bytes"
	"encoding"
	"encoding/binary"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"sync"
	"unsafe"

	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
)

// marshalPtr converts an arbitrary value into a pointer suitable
// to be passed to the kernel.
//
// As an optimization, it returns the original value if it is an
// unsafe.Pointer.
func marshalPtr(data interface{}, length int) (sys.Pointer, error) {
	if ptr, ok := data.(unsafe.Pointer); ok {
		return sys.NewPointer(ptr), nil
	}

	buf, err := marshalBytes(data, length)
	if err != nil {
		return sys.Pointer{}, err
	}

	return sys.NewSlicePointer(buf), nil
}

// marshalBytes converts an arbitrary value into a byte buffer.
//
// Prefer using Map.marshalKey and Map.marshalValue if possible, since
// those have special cases that allow more types to be encoded.
//
// Returns an error if the given value isn't representable in exactly
// length bytes.
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
	if data == nil {
		return nil, errors.New("can't marshal a nil value")
	}

	switch value := data.(type) {
	case encoding.BinaryMarshaler:
		buf, err = value.MarshalBinary()
	case string:
		buf = []byte(value)
	case []byte:
		buf = value
	case unsafe.Pointer:
		err = errors.New("can't marshal from unsafe.Pointer")
	case Map, *Map, Program, *Program:
		err = fmt.Errorf("can't marshal %T", value)
	default:
		var wr bytes.Buffer
		err = binary.Write(&wr, internal.NativeEndian, value)
		if err != nil {
			err = fmt.Errorf("encoding %T: %v", value, err)
		}
		buf = wr.Bytes()
	}
	if err != nil {
		return nil, err
	}

	if len(buf) != length {
		return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
	}
	return buf, nil
}

func makeBuffer(dst interface{}, length int) (sys.Pointer, []byte) {
	if ptr, ok := dst.(unsafe.Pointer); ok {
		return sys.NewPointer(ptr), nil
	}

	buf := make([]byte, length)
	return sys.NewSlicePointer(buf), buf
}

var bytesReaderPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Reader)
	},
}

// unmarshalBytes converts a byte buffer into an arbitrary value.
//
// Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
// those have special cases that allow more types to be encoded.
//
// The common int32 and int64 types are directly handled to avoid
// unnecessary heap allocations as happening in the default case.
func unmarshalBytes(data interface{}, buf []byte) error {
	switch value := data.(type) {
	case unsafe.Pointer:
		var dst []byte
		// Use unsafe.Slice when we drop support for pre1.17 (https://github.com/golang/go/issues/19367)
		// We could opt for removing unsafe.Pointer support in the lib as well
		sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
		sh.Data = uintptr(value)
		sh.Len = len(buf)
		sh.Cap = len(buf)

		copy(dst, buf)
		runtime.KeepAlive(value)
		return nil
	case Map, *Map, Program, *Program:
		return fmt.Errorf("can't unmarshal into %T", value)
	case encoding.BinaryUnmarshaler:
		return value.UnmarshalBinary(buf)
	case *string:
		*value = string(buf)
		return nil
	case *[]byte:
		*value = buf
		return nil
	case *int32:
		if len(buf) < 4 {
			return errors.New("int32 requires 4 bytes")
		}
		*value = int32(internal.NativeEndian.Uint32(buf))
		return nil
	case *uint32:
		if len(buf) < 4 {
			return errors.New("uint32 requires 4 bytes")
		}
		*value = internal.NativeEndian.Uint32(buf)
		return nil
	case *int64:
		if len(buf) < 8 {
			return errors.New("int64 requires 8 bytes")
		}
		*value = int64(internal.NativeEndian.Uint64(buf))
		return nil
	case *uint64:
		if len(buf) < 8 {
			return errors.New("uint64 requires 8 bytes")
		}
		*value = internal.NativeEndian.Uint64(buf)
		return nil
	case string:
		return errors.New("require pointer to string")
	case []byte:
		return errors.New("require pointer to []byte")
	default:
		rd := bytesReaderPool.Get().(*bytes.Reader)
		rd.Reset(buf)
		defer bytesReaderPool.Put(rd)
		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
			return fmt.Errorf("decoding %T: %v", value, err)
		}
		return nil
	}
}

// marshalPerCPUValue encodes a slice containing one value per
// possible CPU into a buffer of bytes.
//
// Values are initialized to zero if the slice has less elements than CPUs.
//
// slice must have a type like []elementType.
func marshalPerCPUValue(slice interface{}, elemLength int) (sys.Pointer, error) {
	sliceType := reflect.TypeOf(slice)
	if sliceType.Kind() != reflect.Slice {
		return sys.Pointer{}, errors.New("per-CPU value requires slice")
	}

	possibleCPUs, err := internal.PossibleCPUs()
	if err != nil {
		return sys.Pointer{}, err
	}

	sliceValue := reflect.ValueOf(slice)
	sliceLen := sliceValue.Len()
	if sliceLen > possibleCPUs {
		return sys.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
	}

	alignedElemLength := internal.Align(elemLength, 8)
	buf := make([]byte, alignedElemLength*possibleCPUs)

	for i := 0; i < sliceLen; i++ {
		elem := sliceValue.Index(i).Interface()
		elemBytes, err := marshalBytes(elem, elemLength)
		if err != nil {
			return sys.Pointer{}, err
		}

		offset := i * alignedElemLength
		copy(buf[offset:offset+elemLength], elemBytes)
	}

	return sys.NewSlicePointer(buf), nil
}

// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
// possible CPU.
//
// valueOut must have a type like *[]elementType
func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
	slicePtrType := reflect.TypeOf(slicePtr)
	if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
		return fmt.Errorf("per-cpu value requires pointer to slice")
	}

	possibleCPUs, err := internal.PossibleCPUs()
	if err != nil {
		return err
	}

	sliceType := slicePtrType.Elem()
	slice := reflect.MakeSlice(sliceType, possibleCPUs, possibleCPUs)

	sliceElemType := sliceType.Elem()
	sliceElemIsPointer := sliceElemType.Kind() == reflect.Ptr
	if sliceElemIsPointer {
		sliceElemType = sliceElemType.Elem()
	}

	step := len(buf) / possibleCPUs
	if step < elemLength {
		return fmt.Errorf("per-cpu element length is larger than available data")
	}
	for i := 0; i < possibleCPUs; i++ {
		var elem interface{}
		if sliceElemIsPointer {
			newElem := reflect.New(sliceElemType)
			slice.Index(i).Set(newElem)
			elem = newElem.Interface()
		} else {
			elem = slice.Index(i).Addr().Interface()
		}

		// Make a copy, since unmarshal can hold on to itemBytes
		elemBytes := make([]byte, elemLength)
		copy(elemBytes, buf[:elemLength])

		err := unmarshalBytes(elem, elemBytes)
		if err != nil {
			return fmt.Errorf("cpu %d: %w", i, err)
		}

		buf = buf[step:]
	}

	reflect.ValueOf(slicePtr).Elem().Set(slice)
	return nil
}
<commit_msg>use unsafe.Slice instead of reflect.SliceHeader<commit_after>package ebpf

import (
	"bytes"
	"encoding"
	"encoding/binary"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"sync"
	"unsafe"

	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
)

// marshalPtr converts an arbitrary value into a pointer suitable
// to be passed to the kernel.
//
// As an optimization, it returns the original value if it is an
// unsafe.Pointer.
func marshalPtr(data interface{}, length int) (sys.Pointer, error) {
	if ptr, ok := data.(unsafe.Pointer); ok {
		return sys.NewPointer(ptr), nil
	}

	buf, err := marshalBytes(data, length)
	if err != nil {
		return sys.Pointer{}, err
	}

	return sys.NewSlicePointer(buf), nil
}

// marshalBytes converts an arbitrary value into a byte buffer.
//
// Prefer using Map.marshalKey and Map.marshalValue if possible, since
// those have special cases that allow more types to be encoded.
//
// Returns an error if the given value isn't representable in exactly
// length bytes.
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
	if data == nil {
		return nil, errors.New("can't marshal a nil value")
	}

	switch value := data.(type) {
	case encoding.BinaryMarshaler:
		buf, err = value.MarshalBinary()
	case string:
		buf = []byte(value)
	case []byte:
		buf = value
	case unsafe.Pointer:
		err = errors.New("can't marshal from unsafe.Pointer")
	case Map, *Map, Program, *Program:
		err = fmt.Errorf("can't marshal %T", value)
	default:
		var wr bytes.Buffer
		err = binary.Write(&wr, internal.NativeEndian, value)
		if err != nil {
			err = fmt.Errorf("encoding %T: %v", value, err)
		}
		buf = wr.Bytes()
	}
	if err != nil {
		return nil, err
	}

	if len(buf) != length {
		return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
	}
	return buf, nil
}

func makeBuffer(dst interface{}, length int) (sys.Pointer, []byte) {
	if ptr, ok := dst.(unsafe.Pointer); ok {
		return sys.NewPointer(ptr), nil
	}

	buf := make([]byte, length)
	return sys.NewSlicePointer(buf), buf
}

var bytesReaderPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Reader)
	},
}

// unmarshalBytes converts a byte buffer into an arbitrary value.
//
// Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
// those have special cases that allow more types to be encoded.
//
// The common int32 and int64 types are directly handled to avoid
// unnecessary heap allocations as happening in the default case.
func unmarshalBytes(data interface{}, buf []byte) error {
	switch value := data.(type) {
	case unsafe.Pointer:
		dst := unsafe.Slice((*byte)(value), len(buf))
		copy(dst, buf)
		runtime.KeepAlive(value)
		return nil
	case Map, *Map, Program, *Program:
		return fmt.Errorf("can't unmarshal into %T", value)
	case encoding.BinaryUnmarshaler:
		return value.UnmarshalBinary(buf)
	case *string:
		*value = string(buf)
		return nil
	case *[]byte:
		*value = buf
		return nil
	case *int32:
		if len(buf) < 4 {
			return errors.New("int32 requires 4 bytes")
		}
		*value = int32(internal.NativeEndian.Uint32(buf))
		return nil
	case *uint32:
		if len(buf) < 4 {
			return errors.New("uint32 requires 4 bytes")
		}
		*value = internal.NativeEndian.Uint32(buf)
		return nil
	case *int64:
		if len(buf) < 8 {
			return errors.New("int64 requires 8 bytes")
		}
		*value = int64(internal.NativeEndian.Uint64(buf))
		return nil
	case *uint64:
		if len(buf) < 8 {
			return errors.New("uint64 requires 8 bytes")
		}
		*value = internal.NativeEndian.Uint64(buf)
		return nil
	case string:
		return errors.New("require pointer to string")
	case []byte:
		return errors.New("require pointer to []byte")
	default:
		rd := bytesReaderPool.Get().(*bytes.Reader)
		rd.Reset(buf)
		defer bytesReaderPool.Put(rd)
		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
			return fmt.Errorf("decoding %T: %v", value, err)
		}
		return nil
	}
}

// marshalPerCPUValue encodes a slice containing one value per
// possible CPU into a buffer of bytes.
//
// Values are initialized to zero if the slice has less elements than CPUs.
//
// slice must have a type like []elementType.
func marshalPerCPUValue(slice interface{}, elemLength int) (sys.Pointer, error) {
	sliceType := reflect.TypeOf(slice)
	if sliceType.Kind() != reflect.Slice {
		return sys.Pointer{}, errors.New("per-CPU value requires slice")
	}

	possibleCPUs, err := internal.PossibleCPUs()
	if err != nil {
		return sys.Pointer{}, err
	}

	sliceValue := reflect.ValueOf(slice)
	sliceLen := sliceValue.Len()
	if sliceLen > possibleCPUs {
		return sys.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
	}

	alignedElemLength := internal.Align(elemLength, 8)
	buf := make([]byte, alignedElemLength*possibleCPUs)

	for i := 0; i < sliceLen; i++ {
		elem := sliceValue.Index(i).Interface()
		elemBytes, err := marshalBytes(elem, elemLength)
		if err != nil {
			return sys.Pointer{}, err
		}

		offset := i * alignedElemLength
		copy(buf[offset:offset+elemLength], elemBytes)
	}

	return sys.NewSlicePointer(buf), nil
}

// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
// possible CPU.
//
// valueOut must have a type like *[]elementType
func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
	slicePtrType := reflect.TypeOf(slicePtr)
	if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
		return fmt.Errorf("per-cpu value requires pointer to slice")
	}

	possibleCPUs, err := internal.PossibleCPUs()
	if err != nil {
		return err
	}

	sliceType := slicePtrType.Elem()
	slice := reflect.MakeSlice(sliceType, possibleCPUs, possibleCPUs)

	sliceElemType := sliceType.Elem()
	sliceElemIsPointer := sliceElemType.Kind() == reflect.Ptr
	if sliceElemIsPointer {
		sliceElemType = sliceElemType.Elem()
	}

	step := len(buf) / possibleCPUs
	if step < elemLength {
		return fmt.Errorf("per-cpu element length is larger than available data")
	}
	for i := 0; i < possibleCPUs; i++ {
		var elem interface{}
		if sliceElemIsPointer {
			newElem := reflect.New(sliceElemType)
			slice.Index(i).Set(newElem)
			elem = newElem.Interface()
		} else {
			elem = slice.Index(i).Addr().Interface()
		}

		// Make a copy, since unmarshal can hold on to itemBytes
		elemBytes := make([]byte, elemLength)
		copy(elemBytes, buf[:elemLength])

		err := unmarshalBytes(elem, elemBytes)
		if err != nil {
			return fmt.Errorf("cpu %d: %w", i, err)
		}

		buf = buf[step:]
	}

	reflect.ValueOf(slicePtr).Elem().Set(slice)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/dmathieu/gofire/gofire"
)

func streaming() {

	client := gofire.NewClient("<your API token>", "<your subdomain>", true)
	room := client.NewRoom("<your room id (not it's name)>")

	channel := room.Listen()
	for {
		msg := <-channel
		fmt.Println(msg.Body)
	}
}
<commit_msg>use an integer in the listen example<commit_after>package main

import (
	"fmt"
	"github.com/dmathieu/gofire/gofire"
)

func streaming() {

	client := gofire.NewClient("<your API token>", "<your subdomain>", true)
	room := client.NewRoom(15) //15 being your room id (not it's name)>

	channel := room.Listen()
	for {
		msg := <-channel
		fmt.Println(msg.Body)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"image"
	"image/color"
	"image/draw"
	"log"
	"math"
	"os"
	"runtime"
	"time"

	"github.com/go-gl/gl/v2.1/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/manyminds/tmx"
)

type chipset struct {
	handle   uint32
	width    int
	height   int
	tilesize int
}

const screenWidth = 640
const screenHeight = 480

func init() {
	runtime.LockOSThread()
}

type openGLCanvas struct {
	width, height int
	sets          map[string]chipset
	scaleX        float32
	scaleY        float32
}

func (o *openGLCanvas) Draw(tile image.Rectangle, where image.Rectangle, f tmx.FlipMode, tileset string) {
	if _, ok := o.sets[tileset]; !ok {
		o.sets[tileset] = newChipset(tileset, tile.Max.X-tile.Min.X)
	}

	c := o.sets[tileset]
	gl.BindTexture(gl.TEXTURE_2D, c.handle)

	// Texture coords
	fts := float32(c.tilesize)
	tileWidthPixels := fts / float32(c.width)
	tileHeightPixels := fts / float32(c.height)
	startX := (float32(tile.Min.X) / fts) * tileWidthPixels
	startY := (float32(tile.Min.Y) / fts) * tileHeightPixels
	endX := startX + tileWidthPixels
	endY := startY + tileHeightPixels

	// Draw coords
	drawX := float32(where.Min.X)
	drawY := float32(where.Min.Y)

	gl.Begin(gl.QUADS)
	{
		gl.TexCoord2f(startX, startY)
		gl.Vertex3f(drawX*o.scaleX, drawY*o.scaleY, 0)

		gl.TexCoord2f(startX, endY)
		gl.Vertex3f(drawX*o.scaleX, (drawY+fts)*o.scaleY, 0)

		gl.TexCoord2f(endX, endY)
		gl.Vertex3f((drawX+fts)*o.scaleX, (drawY+fts)*o.scaleY, 0)

		gl.TexCoord2f(endX, startY)
		gl.Vertex3f((drawX+fts)*o.scaleX, (drawY)*o.scaleY, 0)
	}
	gl.End()
}

func (o openGLCanvas) FillRect(what color.Color, where image.Rectangle) {
	return
	drawX := float32(where.Min.X) * o.scaleX
	drawY := float32(where.Min.Y) * o.scaleY
	endX := float32(where.Max.X) * o.scaleX
	endY := float32(where.Max.Y) * o.scaleY
	r, g, b, a := what.RGBA()
	gl.Color4f(float32(r)/0xFF, float32(g)/0xFF, float32(b)/0xFF, float32(a)/0xFF)
	gl.Begin(gl.QUADS)
	{
		gl.Vertex3f(drawX, drawY, 0)
		gl.Vertex3f(drawX, endX, 0)
		gl.Vertex3f(endX, endY, 0)
		gl.Vertex3f(endX, drawY, 0)
	}
	gl.End()
}

func (o openGLCanvas) Bounds() image.Rectangle {
	return image.Rectangle{Min: image.ZP, Max: image.Pt(o.width, o.height)}
}

func newOpenGLCanvas(width, height int, scaleX, scaleY float32) tmx.Canvas {
	return &openGLCanvas{width: width, height: height, sets: map[string]chipset{}, scaleX: scaleX, scaleY: scaleY}
}

func main() {
	err := glfw.Init()
	if err != nil {
		panic(err)
	}
	defer glfw.Terminate()
	fp, err := os.Open("example.tmx")
	if err != nil {
		panic(err)
	}

	m, err := tmx.NewMap(fp)
	if err != nil {
		panic(err)
	}

	var monitor *glfw.Monitor
	window, err := glfw.CreateWindow(screenWidth, screenHeight, "Map Renderer", monitor, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}

	width, height := window.GetFramebufferSize()
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)
	gl.Viewport(0, 0, int32(width), int32(height))
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(width), float64(height), 0, -1, 1)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	canvas := newOpenGLCanvas(width, height, float32(width)/float32(screenWidth), float32(height)/float32(screenHeight))
	renderer := tmx.NewRenderer(*m, canvas)
	fps := 0
	startTime := time.Now().UnixNano()
	timer := tmx.CreateTimer()
	timer.Start()
	for !window.ShouldClose() {
		elapsed := float64(timer.GetElapsedTime()) / (1000 * 1000)
		renderer.Render(int64(math.Ceil(elapsed)))
		fps++
		if time.Now().UnixNano()-startTime > 1000*1000*1000 {
			log.Println(fps)
			startTime = time.Now().UnixNano()
			fps = 0
		}

		window.SwapBuffers()
		glfw.PollEvents()
		timer.UpdateTime()
	}
}

func newChipset(file string, tilesize int) chipset {
	imgFile, err := os.Open(file)
	if err != nil {
		log.Fatalf("texture %q not found on disk: %v\n", file, err)
	}
	img, _, err := image.Decode(imgFile)
	if err != nil {
		panic(err)
	}

	rgba := image.NewRGBA(img.Bounds())
	draw.Draw(rgba, rgba.Bounds(), img, image.ZP, draw.Src)

	var texture uint32
	gl.Enable(gl.TEXTURE_2D)
	gl.GenTextures(1, &texture)
	gl.BindTexture(gl.TEXTURE_2D, texture)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0, gl.RGBA,
		int32(rgba.Rect.Size().X),
		int32(rgba.Rect.Size().Y),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(rgba.Pix))

	return chipset{width: rgba.Bounds().Dx(), height: rgba.Bounds().Dy(), handle: texture, tilesize: tilesize}
}
<commit_msg>Add disclaimer to example code<commit_after>package main

/*
 * Disclaimer:
 * this is just exemplary code
 * please do not use this for anything
 * I have no clue of opengl
 * this code also has many issues and open bugs
 */

import (
	"image"
	"image/color"
	"image/draw"
	"log"
	"math"
	"os"
	"runtime"
	"time"

	"github.com/go-gl/gl/v2.1/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/manyminds/tmx"
)

type chipset struct {
	handle   uint32
	width    int
	height   int
	tilesize int
}

const screenWidth = 640
const screenHeight = 480

func init() {
	runtime.LockOSThread()
}

type openGLCanvas struct {
	width, height int
	sets          map[string]chipset
	scaleX        float32
	scaleY        float32
}

func (o *openGLCanvas) Draw(tile image.Rectangle, where image.Rectangle, f tmx.FlipMode, tileset string) {
	if _, ok := o.sets[tileset]; !ok {
		o.sets[tileset] = newChipset(tileset, tile.Max.X-tile.Min.X)
	}

	c := o.sets[tileset]
	gl.BindTexture(gl.TEXTURE_2D, c.handle)

	// Texture coords
	fts := float32(c.tilesize)
	tileWidthPixels := fts / float32(c.width)
	tileHeightPixels := fts / float32(c.height)
	startX := (float32(tile.Min.X) / fts) * tileWidthPixels
	startY := (float32(tile.Min.Y) / fts) * tileHeightPixels
	endX := startX + tileWidthPixels
	endY := startY + tileHeightPixels

	// Draw coords
	drawX := float32(where.Min.X)
	drawY := float32(where.Min.Y)

	gl.Begin(gl.QUADS)
	{
		gl.TexCoord2f(startX, startY)
		gl.Vertex3f(drawX*o.scaleX, drawY*o.scaleY, 0)

		gl.TexCoord2f(startX, endY)
		gl.Vertex3f(drawX*o.scaleX, (drawY+fts)*o.scaleY, 0)

		gl.TexCoord2f(endX, endY)
		gl.Vertex3f((drawX+fts)*o.scaleX, (drawY+fts)*o.scaleY, 0)

		gl.TexCoord2f(endX, startY)
		gl.Vertex3f((drawX+fts)*o.scaleX, (drawY)*o.scaleY, 0)
	}
	gl.End()
}

func (o openGLCanvas) FillRect(what color.Color, where image.Rectangle) {
	return //this does not work at all... makes the whole image red
	drawX := float32(where.Min.X) * o.scaleX
	drawY := float32(where.Min.Y) * o.scaleY
	endX := float32(where.Max.X) * o.scaleX
	endY := float32(where.Max.Y) * o.scaleY
	r, g, b, a := what.RGBA()
	gl.Color4f(float32(r)/0xFF, float32(g)/0xFF, float32(b)/0xFF, float32(a)/0xFF)
	gl.Begin(gl.QUADS)
	{
		gl.Vertex3f(drawX, drawY, 0)
		gl.Vertex3f(drawX, endX, 0)
		gl.Vertex3f(endX, endY, 0)
		gl.Vertex3f(endX, drawY, 0)
	}
	gl.End()
}

func (o openGLCanvas) Bounds() image.Rectangle {
	return image.Rectangle{Min: image.ZP, Max: image.Pt(o.width, o.height)}
}

func newOpenGLCanvas(width, height int, scaleX, scaleY float32) tmx.Canvas {
	return &openGLCanvas{width: width, height: height, sets: map[string]chipset{}, scaleX: scaleX, scaleY: scaleY}
}

func main() {
	err := glfw.Init()
	if err != nil {
		panic(err)
	}
	defer glfw.Terminate()
	fp, err := os.Open("example.tmx")
	if err != nil {
		panic(err)
	}

	m, err := tmx.NewMap(fp)
	if err != nil {
		panic(err)
	}

	var monitor *glfw.Monitor
	window, err := glfw.CreateWindow(screenWidth, screenHeight, "Map Renderer", monitor, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}

	width, height := window.GetFramebufferSize()
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)
	gl.Viewport(0, 0, int32(width), int32(height))
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(width), float64(height), 0, -1, 1)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	canvas := newOpenGLCanvas(width, height, float32(width)/float32(screenWidth), float32(height)/float32(screenHeight))
	renderer := tmx.NewRenderer(*m, canvas)
	fps := 0
	startTime := time.Now().UnixNano()
	timer := tmx.CreateTimer()
	timer.Start()
	for !window.ShouldClose() {
		elapsed := float64(timer.GetElapsedTime()) / (1000 * 1000)
		renderer.Render(int64(math.Ceil(elapsed)))
		fps++
		if time.Now().UnixNano()-startTime > 1000*1000*1000 {
			log.Println(fps)
			startTime = time.Now().UnixNano()
			fps = 0
		}

		window.SwapBuffers()
		glfw.PollEvents()
		timer.UpdateTime()
	}
}

func newChipset(file string, tilesize int) chipset {
	imgFile, err := os.Open(file)
	if err != nil {
		log.Fatalf("texture %q not found on disk: %v\n", file, err)
	}
	img, _, err := image.Decode(imgFile)
	if err != nil {
		panic(err)
	}

	rgba := image.NewRGBA(img.Bounds())
	draw.Draw(rgba, rgba.Bounds(), img, image.ZP, draw.Src)

	var texture uint32
	gl.Enable(gl.TEXTURE_2D)
	gl.GenTextures(1, &texture)
	gl.BindTexture(gl.TEXTURE_2D, texture)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0, gl.RGBA,
		int32(rgba.Rect.Size().X),
		int32(rgba.Rect.Size().Y),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(rgba.Pix))

	return chipset{width: rgba.Bounds().Dx(), height: rgba.Bounds().Dy(), handle: texture, tilesize: tilesize}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	ggio "github.com/gogo/protobuf/io"
	p2p_host "github.com/libp2p/go-libp2p-host"
	p2p_net "github.com/libp2p/go-libp2p-net"
	p2p_peer "github.com/libp2p/go-libp2p-peer"
	p2p_pstore "github.com/libp2p/go-libp2p-peerstore"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	"log"
	"os"
	"sync"
)

type Directory struct {
	mc.PeerIdentity
	host  p2p_host.Host
	peers map[p2p_peer.ID]p2p_pstore.PeerInfo
	mx    sync.Mutex
}

func (dir *Directory) registerHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("directory/register: new stream from %s\n", pid.Pretty())

	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	req := new(pb.RegisterPeer)

	for {
		err := r.ReadMsg(req)
		if err != nil {
			break
		}

		if req.Info == nil {
			log.Printf("directory/register: empty peer info from %s\n", pid.Pretty())
			break
		}

		pinfo, err := mc.PBToPeerInfo(req.Info)
		if err != nil {
			log.Printf("directory/register: bad peer info from %s\n", pid.Pretty())
			break
		}

		if pinfo.ID != pid {
			log.Printf("directory/register: bogus peer info from %s\n", pid.Pretty())
			break
		}

		dir.registerPeer(pinfo)

		req.Reset()
	}

	dir.unregisterPeer(pid)
}

func (dir *Directory) lookupHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("directory/lookup: new stream from %s\n", pid.Pretty())

	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	w := ggio.NewDelimitedWriter(s)
	req := new(pb.LookupPeerRequest)
	resp := new(pb.LookupPeerResponse)

	for {
		err := r.ReadMsg(req)
		if err != nil {
			break
		}

		xid, err := p2p_peer.IDB58Decode(req.Id)
		if err != nil {
			log.Printf("directory/lookup: bad request from %s\n", pid.Pretty())
			break
		}

		pinfo, ok := dir.lookupPeer(xid)
		if ok {
			var pbpi pb.PeerInfo
			mc.PBFromPeerInfo(&pbpi, pinfo)
			resp.Peer = &pbpi
		}

		err = w.WriteMsg(resp)
		if err != nil {
			break
		}

		req.Reset()
		resp.Reset()
	}
}

func (dir *Directory) listHandler(s p2p_net.Stream) {

}

func (dir *Directory) registerPeer(info p2p_pstore.PeerInfo) {
	log.Printf("directory: register %s\n", info.ID.Pretty())
	dir.mx.Lock()
	dir.peers[info.ID] = info
	dir.mx.Unlock()
}

func (dir *Directory) unregisterPeer(pid p2p_peer.ID) {
	log.Printf("directory: unregister %s\n", pid.Pretty())
	dir.mx.Lock()
	delete(dir.peers, pid)
	dir.mx.Unlock()
}

func (dir *Directory) lookupPeer(pid p2p_peer.ID) (p2p_pstore.PeerInfo, bool) {
	dir.mx.Lock()
	pinfo, ok := dir.peers[pid]
	dir.mx.Unlock()
	return pinfo, ok
}

func main() {
	port := flag.Int("l", 9000, "Listen port")
	home := flag.String("d", "/tmp/mcdir", "Directory home")
	flag.Parse()

	err := os.MkdirAll(*home, 0755)
	if err != nil {
		log.Fatal(err)
	}

	id, err := mc.MakePeerIdentity(*home)
	if err != nil {
		log.Fatal(err)
	}

	addr, err := mc.ParseAddress(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", *port))
	if err != nil {
		log.Fatal(err)
	}

	host, err := mc.NewHost(id, addr)
	if err != nil {
		log.Fatal(err)
	}

	dir := &Directory{PeerIdentity: id, host: host, peers: make(map[p2p_peer.ID]p2p_pstore.PeerInfo)}
	host.SetStreamHandler("/mediachain/dir/register", dir.registerHandler)
	host.SetStreamHandler("/mediachain/dir/lookup", dir.lookupHandler)
	host.SetStreamHandler("/mediachain/dir/list", dir.listHandler)

	log.Printf("I am %s/%s", addr, id.Pretty())
	select {}
}
<commit_msg>mcdir: bind to INADDRY_ANY, print out all known self-handles<commit_after>package main

import (
	"flag"
	"fmt"
	ggio "github.com/gogo/protobuf/io"
	p2p_host "github.com/libp2p/go-libp2p-host"
	p2p_net "github.com/libp2p/go-libp2p-net"
	p2p_peer "github.com/libp2p/go-libp2p-peer"
	p2p_pstore "github.com/libp2p/go-libp2p-peerstore"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	"log"
	"os"
	"sync"
)

type Directory struct {
	mc.PeerIdentity
	host  p2p_host.Host
	peers map[p2p_peer.ID]p2p_pstore.PeerInfo
	mx    sync.Mutex
}

func (dir *Directory) registerHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("directory/register: new stream from %s\n", pid.Pretty())

	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	req := new(pb.RegisterPeer)

	for {
		err := r.ReadMsg(req)
		if err != nil {
			break
		}

		if req.Info == nil {
			log.Printf("directory/register: empty peer info from %s\n", pid.Pretty())
			break
		}

		pinfo, err := mc.PBToPeerInfo(req.Info)
		if err != nil {
			log.Printf("directory/register: bad peer info from %s\n", pid.Pretty())
			break
		}

		if pinfo.ID != pid {
			log.Printf("directory/register: bogus peer info from %s\n", pid.Pretty())
			break
		}

		dir.registerPeer(pinfo)

		req.Reset()
	}

	dir.unregisterPeer(pid)
}

func (dir *Directory) lookupHandler(s p2p_net.Stream) {
	defer s.Close()

	pid := s.Conn().RemotePeer()
	log.Printf("directory/lookup: new stream from %s\n", pid.Pretty())

	r := ggio.NewDelimitedReader(s, mc.MaxMessageSize)
	w := ggio.NewDelimitedWriter(s)
	req := new(pb.LookupPeerRequest)
	resp := new(pb.LookupPeerResponse)

	for {
		err := r.ReadMsg(req)
		if err != nil {
			break
		}

		xid, err := p2p_peer.IDB58Decode(req.Id)
		if err != nil {
			log.Printf("directory/lookup: bad request from %s\n", pid.Pretty())
			break
		}

		pinfo, ok := dir.lookupPeer(xid)
		if ok {
			var pbpi pb.PeerInfo
			mc.PBFromPeerInfo(&pbpi, pinfo)
			resp.Peer = &pbpi
		}

		err = w.WriteMsg(resp)
		if err != nil {
			break
		}

		req.Reset()
		resp.Reset()
	}
}

func (dir *Directory) listHandler(s p2p_net.Stream) {
	// Implement Me!
	s.Close()
}

func (dir *Directory) registerPeer(info p2p_pstore.PeerInfo) {
	log.Printf("directory: register %s\n", info.ID.Pretty())
	dir.mx.Lock()
	dir.peers[info.ID] = info
	dir.mx.Unlock()
}

func (dir *Directory) unregisterPeer(pid p2p_peer.ID) {
	log.Printf("directory: unregister %s\n", pid.Pretty())
	dir.mx.Lock()
	delete(dir.peers, pid)
	dir.mx.Unlock()
}

func (dir *Directory) lookupPeer(pid p2p_peer.ID) (p2p_pstore.PeerInfo, bool) {
	dir.mx.Lock()
	pinfo, ok := dir.peers[pid]
	dir.mx.Unlock()
	return pinfo, ok
}

func main() {
	port := flag.Int("l", 9000, "Listen port")
	home := flag.String("d", "/tmp/mcdir", "Directory home")
	flag.Parse()

	err := os.MkdirAll(*home, 0755)
	if err != nil {
		log.Fatal(err)
	}

	id, err := mc.MakePeerIdentity(*home)
	if err != nil {
		log.Fatal(err)
	}

	addr, err := mc.ParseAddress(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *port))
	if err != nil {
		log.Fatal(err)
	}

	host, err := mc.NewHost(id, addr)
	if err != nil {
		log.Fatal(err)
	}

	dir := &Directory{PeerIdentity: id, host: host, peers: make(map[p2p_peer.ID]p2p_pstore.PeerInfo)}
	host.SetStreamHandler("/mediachain/dir/register", dir.registerHandler)
	host.SetStreamHandler("/mediachain/dir/lookup", dir.lookupHandler)
	host.SetStreamHandler("/mediachain/dir/list", dir.listHandler)

	addrs, err := host.Network().InterfaceListenAddresses()
	if err != nil {
		log.Fatal(err)
	}

	for _, addr := range addrs {
		log.Printf("I am %s/%s", addr, id.Pretty())
	}
	select {}
}
<|endoftext|>


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

package jtl

// inbound plugins, currently only supported plugins are webhook and stdin,
// other plugins could be provided for websocket, kafka, sqs etc.

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	. "github.com/Comcast/eel/eel/util"
)

type InboundPlugin interface {
	StartPlugin(Context)
	GetSettings() *PluginSettings
	StopPlugin(Context)
	IsActive() bool
}

type PluginSettings struct {
	Type       string
	Name       string
	Active     bool
	RestartOk  bool
	Parameters map[string]interface{}
}

type NewInboundPlugin func(*PluginSettings) InboundPlugin

type PluginConfigList []*PluginSettings

// plugins by name
var inboundPluginMap = make(map[string]InboundPlugin, 0)

// plugins by type
var inboundPluginTypeMap = make(map[string]NewInboundPlugin, 0)

var pluginConfigList PluginConfigList

// RegisterInboundPlugin registers an (external) plugin implementation by plugin type
func RegisterInboundPluginType(newPlugin NewInboundPlugin, pluginType string) {
	inboundPluginTypeMap[pluginType] = newPlugin
}

func GetInboundPluginByType(pluginType string) InboundPlugin {
	// currently only one active plugin per type allowed!!!
	for _, v := range inboundPluginMap {
		if v.GetSettings().Type == pluginType {
			return v
		}
	}
	return nil
}

func GetInboundPluginByName(name string) InboundPlugin {
	return inboundPluginMap[name]
}

func PluginConfigHandler(w http.ResponseWriter, r *http.Request) {
	ctx := Gctx.SubContext()
	w.Header().Set("Content-Type", "application/json")
	state := make(map[string]interface{}, 0)
	state["Version"] = GetConfig(ctx).Version
	state["PluginConfigs"] = pluginConfigList
	buf, err := json.MarshalIndent(state, "", "\t")
	if err != nil {
		fmt.Fprintf(w, `{"error":"%s"}`, err.Error())
	} else {
		fmt.Fprintf(w, string(buf))
	}
}

func ManagePluginsUIHandler(w http.ResponseWriter, r *http.Request) {
	ctx := Gctx.SubContext()
	pluginsTemplate, err := template.ParseFiles("web/plugins.html")
	if err != nil {
		ctx.Log().Error("error_type", "manage_plugins", "cause", "template_parse_error", "error", err.Error())
	}
	operation := r.FormValue("operation")
	name := r.FormValue("name")
	if operation == "Start" && name != "" {
		p := GetInboundPluginByName(name)
		if p != nil && !p.IsActive() {
			go p.StartPlugin(ctx)
		}
	} else if operation == "Stop" && name != "" {
		p := GetInboundPluginByName(name)
		if p != nil && p.IsActive() {
			p.StopPlugin(ctx)
		}
	}
	psl := make([]*PluginSettings, 0)
	for _, p := range inboundPluginMap {
		psl = append(psl, p.GetSettings())
	}
	err = pluginsTemplate.Execute(w, psl)
	if err != nil {
		ctx.Log().Error("error_type", "manage_plugins", "cause", "template_exec_error", "error", err.Error())
	}
}

func GetPluginConfigList(ctx Context) PluginConfigList {
	configFile, err := os.Open(filepath.Join(filepath.Dir(ConfigPath), "plugins.json"))
	if err != nil {
		// csv-context-go may not be ready yet for logging
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "open_config", "error", err.Error())
		os.Exit(1)
	}
	defer configFile.Close()
	configData, err := ioutil.ReadAll(configFile)
	if err != nil {
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "read_config", "error", err.Error())
		os.Exit(1)
	}
	var config PluginConfigList
	err = json.Unmarshal(configData, &config)
	if err != nil {
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "parse_config", "error", err.Error())
		os.Exit(1)
	}
	return config
}

func LoadInboundPlugins(ctx Context) {
	// load plugin configs
	pluginConfigList = GetPluginConfigList(ctx)
	for _, e := range pluginConfigList {
		// dependency injection
		np := inboundPluginTypeMap[e.Type]
		if np == nil {
			ctx.Log().Error("error_type", "bad_plugin_config", "cause", "unknown_plugin_type", "plugin_type", e.Type)
		} else {
			inboundPluginMap[e.Name] = np(e)
		}
	}
	// launch plugins
	for k, v := range inboundPluginMap {
		if v.GetSettings().Active {
			ctx.Log().Info("action", "launching_inbound_plugin", "plugin_name", k, "pugin_type", v.GetSettings().Type)
			go v.StartPlugin(ctx)
		} else {
			ctx.Log().Info("action", "skipping_inactive_plugin", "plugin_name", k, "pugin_type", v.GetSettings().Type)
		}
	}
	// need sync path in inproc.go
	if GetInboundPluginByType("WEBHOOK") != nil {
		syncPath := GetInboundPluginByType("WEBHOOK").GetSettings().Parameters["EventProcPath"]
		Gctx.AddConfigValue(EelSyncPath, syncPath)
	} else {
		Gctx.AddConfigValue(EelSyncPath, "")
	}
}
<commit_msg>fine tuning plugins web ui<commit_after>/**
 * Copyright 2015 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jtl

// inbound plugins, currently only supported plugins are webhook and stdin,
// other plugins could be provided for websocket, kafka, sqs etc.

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"time"

	. "github.com/Comcast/eel/eel/util"
)

type InboundPlugin interface {
	StartPlugin(Context)
	GetSettings() *PluginSettings
	StopPlugin(Context)
	IsActive() bool
}

type PluginSettings struct {
	Type       string
	Name       string
	Active     bool
	RestartOk  bool
	Parameters map[string]interface{}
}

type NewInboundPlugin func(*PluginSettings) InboundPlugin

type PluginConfigList []*PluginSettings

// plugins by name
var inboundPluginMap = make(map[string]InboundPlugin, 0)

// plugins by type
var inboundPluginTypeMap = make(map[string]NewInboundPlugin, 0)

var pluginConfigList PluginConfigList

// RegisterInboundPlugin registers an (external) plugin implementation by plugin type
func RegisterInboundPluginType(newPlugin NewInboundPlugin, pluginType string) {
	inboundPluginTypeMap[pluginType] = newPlugin
}

func GetInboundPluginByType(pluginType string) InboundPlugin {
	// currently only one active plugin per type allowed!!!
	for _, v := range inboundPluginMap {
		if v.GetSettings().Type == pluginType {
			return v
		}
	}
	return nil
}

func GetInboundPluginByName(name string) InboundPlugin {
	return inboundPluginMap[name]
}

func PluginConfigHandler(w http.ResponseWriter, r *http.Request) {
	ctx := Gctx.SubContext()
	w.Header().Set("Content-Type", "application/json")
	state := make(map[string]interface{}, 0)
	state["Version"] = GetConfig(ctx).Version
	state["PluginConfigs"] = pluginConfigList
	buf, err := json.MarshalIndent(state, "", "\t")
	if err != nil {
		fmt.Fprintf(w, `{"error":"%s"}`, err.Error())
	} else {
		fmt.Fprintf(w, string(buf))
	}
}

func ManagePluginsUIHandler(w http.ResponseWriter, r *http.Request) {
	ctx := Gctx.SubContext()
	pluginsTemplate, err := template.ParseFiles("web/plugins.html")
	if err != nil {
		ctx.Log().Error("error_type", "manage_plugins", "cause", "template_parse_error", "error", err.Error())
	}
	operation := r.FormValue("operation")
	name := r.FormValue("name")
	if operation == "Start" && name != "" {
		p := GetInboundPluginByName(name)
		if p != nil && !p.IsActive() {
			go p.StartPlugin(ctx)
			time.Sleep(1 * time.Second)
		}
	} else if operation == "Stop" && name != "" {
		p := GetInboundPluginByName(name)
		if p != nil && p.IsActive() {
			p.StopPlugin(ctx)
		}
	}
	psl := make([]*PluginSettings, 0)
	for _, p := range inboundPluginMap {
		psl = append(psl, p.GetSettings())
	}
	err = pluginsTemplate.Execute(w, psl)
	if err != nil {
		ctx.Log().Error("error_type", "manage_plugins", "cause", "template_exec_error", "error", err.Error())
	}
}

func GetPluginConfigList(ctx Context) PluginConfigList {
	configFile, err := os.Open(filepath.Join(filepath.Dir(ConfigPath), "plugins.json"))
	if err != nil {
		// csv-context-go may not be ready yet for logging
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "open_config", "error", err.Error())
		os.Exit(1)
	}
	defer configFile.Close()
	configData, err := ioutil.ReadAll(configFile)
	if err != nil {
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "read_config", "error", err.Error())
		os.Exit(1)
	}
	var config PluginConfigList
	err = json.Unmarshal(configData, &config)
	if err != nil {
		fmt.Printf("{ \"error\" : \"%s\" }", err.Error())
		ctx.Log().Error("error_type", "get_plugin_config", "cause", "parse_config", "error", err.Error())
		os.Exit(1)
	}
	return config
}

func LoadInboundPlugins(ctx Context) {
	// load plugin configs
	pluginConfigList = GetPluginConfigList(ctx)
	for _, e := range pluginConfigList {
		// dependency injection
		np := inboundPluginTypeMap[e.Type]
		if np == nil {
			ctx.Log().Error("error_type", "bad_plugin_config", "cause", "unknown_plugin_type", "plugin_type", e.Type)
		} else {
			inboundPluginMap[e.Name] = np(e)
		}
	}
	// launch plugins
	for k, v := range inboundPluginMap {
		if v.GetSettings().Active {
			ctx.Log().Info("action", "launching_inbound_plugin", "plugin_name", k, "pugin_type", v.GetSettings().Type)
			go v.StartPlugin(ctx)
		} else {
			ctx.Log().Info("action", "skipping_inactive_plugin", "plugin_name", k, "pugin_type", v.GetSettings().Type)
		}
	}
	// need sync path in inproc.go
	if GetInboundPluginByType("WEBHOOK") != nil {
		syncPath := GetInboundPluginByType("WEBHOOK").GetSettings().Parameters["EventProcPath"]
		Gctx.AddConfigValue(EelSyncPath, syncPath)
	} else {
		Gctx.AddConfigValue(EelSyncPath, "")
	}
}
<|endoftext|>


<commit_before>package rcmgr

import (
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
)

// MetricsReporter is an interface for collecting metrics from resource manager actions
type MetricsReporter interface {
	// AllowConn is invoked when opening a connection is allowed
	AllowConn(dir network.Direction, usefd bool)
	// BlockConn is invoked when opening a connection is blocked
	BlockConn(dir network.Direction, usefd bool)

	// AllowStream is invoked when opening a stream is allowed
	AllowStream(p peer.ID, dir network.Direction)
	// BlockStream is invoked when opening a stream is blocked
	BlockStream(p peer.ID, dir network.Direction)

	// AllowPeer is invoked when attaching ac onnection to a peer is allowed
	AllowPeer(p peer.ID)
	// BlockPeer is invoked when attaching ac onnection to a peer is blocked
	BlockPeer(p peer.ID)

	// AllowProtocol is invoked when setting the protocol for a stream is allowed
	AllowProtocol(proto protocol.ID)
	// BlockProtocol is invoked when setting the protocol for a stream is blocked
	BlockProtocol(proto protocol.ID)
	// BlockProtocolPeer is invoked when setting the protocol for a stream is blocked at the per protocol peer scope
	BlockProtocolPeer(proto protocol.ID, p peer.ID)

	// AllowService is invoked when setting the protocol for a stream is allowed
	AllowService(svc string)
	// BlockService is invoked when setting the protocol for a stream is blocked
	BlockService(svc string)
	// BlockServicePeer is invoked when setting the service for a stream is blocked at the per service peer scope
	BlockServicePeer(svc string, p peer.ID)

	// AllowMemory is invoked when a memory reservation is allowed
	AllowMemory(size int)
	// BlockMemory is invoked when a memory reservation is blocked
	BlockMemory(size int)
}

type metrics struct {
	reporter MetricsReporter
}

// WithMetrics is a resource manager option to enable metrics collection. Can be
// called multiple times to add multiple reporters.
func WithMetrics(reporter MetricsReporter) Option {
	return func(r *resourceManager) error {
		if r.metrics == nil {
			r.metrics = &metrics{reporter: reporter}
		} else if multimetrics, ok := r.metrics.reporter.(*MultiMetricsReporter); ok {
			multimetrics.reporters = append(multimetrics.reporters, reporter)
		} else {
			// This was a single reporter. Lets convert it to a multimetrics reporter
			r.metrics = &metrics{
				reporter: &MultiMetricsReporter{reporters: []MetricsReporter{r.metrics.reporter, reporter}},
			}
		}
		return nil
	}
}

func (m *metrics) AllowConn(dir network.Direction, usefd bool) {
	if m == nil {
		return
	}

	m.reporter.AllowConn(dir, usefd)
}

func (m *metrics) BlockConn(dir network.Direction, usefd bool) {
	if m == nil {
		return
	}

	m.reporter.BlockConn(dir, usefd)
}

func (m *metrics) AllowStream(p peer.ID, dir network.Direction) {
	if m == nil {
		return
	}

	m.reporter.AllowStream(p, dir)
}

func (m *metrics) BlockStream(p peer.ID, dir network.Direction) {
	if m == nil {
		return
	}

	m.reporter.BlockStream(p, dir)
}

func (m *metrics) AllowPeer(p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.AllowPeer(p)
}

func (m *metrics) BlockPeer(p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockPeer(p)
}

func (m *metrics) AllowProtocol(proto protocol.ID) {
	if m == nil {
		return
	}

	m.reporter.AllowProtocol(proto)
}

func (m *metrics) BlockProtocol(proto protocol.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockProtocol(proto)
}

func (m *metrics) BlockProtocolPeer(proto protocol.ID, p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockProtocolPeer(proto, p)
}

func (m *metrics) AllowService(svc string) {
	if m == nil {
		return
	}

	m.reporter.AllowService(svc)
}

func (m *metrics) BlockService(svc string) {
	if m == nil {
		return
	}

	m.reporter.BlockService(svc)
}

func (m *metrics) BlockServicePeer(svc string, p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockServicePeer(svc, p)
}

func (m *metrics) AllowMemory(size int) {
	if m == nil {
		return
	}

	m.reporter.AllowMemory(size)
}

func (m *metrics) BlockMemory(size int) {
	if m == nil {
		return
	}

	m.reporter.BlockMemory(size)
}

// MultiMetricsReporter is a helper that allows you to report to multiple metrics reporters.
type MultiMetricsReporter struct {
	reporters []MetricsReporter
}

// AllowConn is invoked when opening a connection is allowed
func (mmr *MultiMetricsReporter) AllowConn(dir network.Direction, usefd bool) {
	for _, r := range mmr.reporters {
		r.AllowConn(dir, usefd)
	}
}

// BlockConn is invoked when opening a connection is blocked
func (mmr *MultiMetricsReporter) BlockConn(dir network.Direction, usefd bool) {
	for _, r := range mmr.reporters {
		r.BlockConn(dir, usefd)
	}
}

// AllowStream is invoked when opening a stream is allowed
func (mmr *MultiMetricsReporter) AllowStream(p peer.ID, dir network.Direction) {
	for _, r := range mmr.reporters {
		r.AllowStream(p, dir)
	}
}

// BlockStream is invoked when opening a stream is blocked
func (mmr *MultiMetricsReporter) BlockStream(p peer.ID, dir network.Direction) {
	for _, r := range mmr.reporters {
		r.BlockStream(p, dir)
	}
}

// AllowPeer is invoked when attaching ac onnection to a peer is allowed
func (mmr *MultiMetricsReporter) AllowPeer(p peer.ID) {
	for _, r := range mmr.reporters {
		r.AllowPeer(p)
	}
}

// BlockPeer is invoked when attaching ac onnection to a peer is blocked
func (mmr *MultiMetricsReporter) BlockPeer(p peer.ID) {
	for _, r := range mmr.reporters {
		r.BlockPeer(p)
	}
}

// AllowProtocol is invoked when setting the protocol for a stream is allowed
func (mmr *MultiMetricsReporter) AllowProtocol(proto protocol.ID) {
	for _, r := range mmr.reporters {
		r.AllowProtocol(proto)
	}
}

// BlockProtocol is invoked when setting the protocol for a stream is blocked
func (mmr *MultiMetricsReporter) BlockProtocol(proto protocol.ID) {
	for _, r := range mmr.reporters {
		r.BlockProtocol(proto)
	}
}

// BlockedProtocolPeer is invoekd when setting the protocol for a stream is blocked at the per protocol peer scope
func (mmr *MultiMetricsReporter) BlockProtocolPeer(proto protocol.ID, p peer.ID) {
	for _, r := range mmr.reporters {
		r.BlockProtocolPeer(proto, p)
	}
}

// AllowPService is invoked when setting the protocol for a stream is allowed
func (mmr *MultiMetricsReporter) AllowService(svc string) {
	for _, r := range mmr.reporters {
		r.AllowService(svc)
	}
}

// BlockPService is invoked when setting the protocol for a stream is blocked
func (mmr *MultiMetricsReporter) BlockService(svc string) {
	for _, r := range mmr.reporters {
		r.BlockService(svc)
	}
}

// BlockedServicePeer is invoked when setting the service for a stream is blocked at the per service peer scope
func (mmr *MultiMetricsReporter) BlockServicePeer(svc string, p peer.ID) {
	for _, r := range mmr.reporters {
		r.BlockServicePeer(svc, p)
	}
}

// AllowMemory is invoked when a memory reservation is allowed
func (mmr *MultiMetricsReporter) AllowMemory(size int) {
	for _, r := range mmr.reporters {
		r.AllowMemory(size)
	}
}

// BlockMemory is invoked when a memory reservation is blocked
func (mmr *MultiMetricsReporter) BlockMemory(size int) {
	for _, r := range mmr.reporters {
		r.BlockMemory(size)
	}
}
<commit_msg>Revert "Add multimetrics reporter"<commit_after>package rcmgr

import (
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/protocol"
)

// MetricsReporter is an interface for collecting metrics from resource manager actions
type MetricsReporter interface {
	// AllowConn is invoked when opening a connection is allowed
	AllowConn(dir network.Direction, usefd bool)
	// BlockConn is invoked when opening a connection is blocked
	BlockConn(dir network.Direction, usefd bool)

	// AllowStream is invoked when opening a stream is allowed
	AllowStream(p peer.ID, dir network.Direction)
	// BlockStream is invoked when opening a stream is blocked
	BlockStream(p peer.ID, dir network.Direction)

	// AllowPeer is invoked when attaching ac onnection to a peer is allowed
	AllowPeer(p peer.ID)
	// BlockPeer is invoked when attaching ac onnection to a peer is blocked
	BlockPeer(p peer.ID)

	// AllowProtocol is invoked when setting the protocol for a stream is allowed
	AllowProtocol(proto protocol.ID)
	// BlockProtocol is invoked when setting the protocol for a stream is blocked
	BlockProtocol(proto protocol.ID)
	// BlockProtocolPeer is invoked when setting the protocol for a stream is blocked at the per protocol peer scope
	BlockProtocolPeer(proto protocol.ID, p peer.ID)

	// AllowService is invoked when setting the protocol for a stream is allowed
	AllowService(svc string)
	// BlockService is invoked when setting the protocol for a stream is blocked
	BlockService(svc string)
	// BlockServicePeer is invoked when setting the service for a stream is blocked at the per service peer scope
	BlockServicePeer(svc string, p peer.ID)

	// AllowMemory is invoked when a memory reservation is allowed
	AllowMemory(size int)
	// BlockMemory is invoked when a memory reservation is blocked
	BlockMemory(size int)
}

type metrics struct {
	reporter MetricsReporter
}

// WithMetrics is a resource manager option to enable metrics collection
func WithMetrics(reporter MetricsReporter) Option {
	return func(r *resourceManager) error {
		r.metrics = &metrics{reporter: reporter}
		return nil
	}
}

func (m *metrics) AllowConn(dir network.Direction, usefd bool) {
	if m == nil {
		return
	}

	m.reporter.AllowConn(dir, usefd)
}

func (m *metrics) BlockConn(dir network.Direction, usefd bool) {
	if m == nil {
		return
	}

	m.reporter.BlockConn(dir, usefd)
}

func (m *metrics) AllowStream(p peer.ID, dir network.Direction) {
	if m == nil {
		return
	}

	m.reporter.AllowStream(p, dir)
}

func (m *metrics) BlockStream(p peer.ID, dir network.Direction) {
	if m == nil {
		return
	}

	m.reporter.BlockStream(p, dir)
}

func (m *metrics) AllowPeer(p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.AllowPeer(p)
}

func (m *metrics) BlockPeer(p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockPeer(p)
}

func (m *metrics) AllowProtocol(proto protocol.ID) {
	if m == nil {
		return
	}

	m.reporter.AllowProtocol(proto)
}

func (m *metrics) BlockProtocol(proto protocol.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockProtocol(proto)
}

func (m *metrics) BlockProtocolPeer(proto protocol.ID, p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockProtocolPeer(proto, p)
}

func (m *metrics) AllowService(svc string) {
	if m == nil {
		return
	}

	m.reporter.AllowService(svc)
}

func (m *metrics) BlockService(svc string) {
	if m == nil {
		return
	}

	m.reporter.BlockService(svc)
}

func (m *metrics) BlockServicePeer(svc string, p peer.ID) {
	if m == nil {
		return
	}

	m.reporter.BlockServicePeer(svc, p)
}

func (m *metrics) AllowMemory(size int) {
	if m == nil {
		return
	}

	m.reporter.AllowMemory(size)
}

func (m *metrics) BlockMemory(size int) {
	if m == nil {
		return
	}

	m.reporter.BlockMemory(size)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

func Sqrt(n int) int {
	var t uint
	var b uint
	var r uint
	t = uint(n)
	p := uint(1 << 30)
	for p > t {
		p >>= 2
	}
	for ; p != 0; p >>= 2 {
		b = r | p
		r >>= 1
		if t >= b {
			t -= b
			r |= p
		}
	}
	return int(r)
}

func getPrime(n int) int {
	var primeList = []int{2}
	var isPrime int = 1
	var num int = 3
	var sqrtNum int = 0
	for len(primeList) < n {
		sqrtNum = Sqrt(num)
		for i := 0; i < len(primeList); i++ {
			if num%primeList[i] == 0 {
				isPrime = 0
			}
			if primeList[i] > sqrtNum {
				i = len(primeList)
			}
		}
		if isPrime == 1 {
			primeList = append(primeList, num)
		} else {
			isPrime = 1
		}
		num = num + 2
	}
	return primeList[n-1]
}

func main() {
	if len(os.Args) == 1 {
		fmt.Println("start this application with the argument true to compute primenumbers parallel or false for serial")
		fmt.Println("you can configure the maximum processes/threads amount with: \"export GOMAXPROCS=$number\"")
	} else {
		if os.Args[1] == "true" {
			prime0 := make(chan int)
			prime1 := make(chan int)
			prime2 := make(chan int)
			prime3 := make(chan int)
			prime4 := make(chan int)
			prime5 := make(chan int)
			prime6 := make(chan int)
			prime7 := make(chan int)
			go func() {
				prime0 <- getPrime(200000)
			}()
			go func() {
				prime1 <- getPrime(500000)
			}()
			go func() {
				prime2 <- getPrime(100000)
			}()
			go func() {
				prime3 <- getPrime(250000)
			}()
			go func() {
				prime4 <- getPrime(550000)
			}()
			go func() {
				prime5 <- getPrime(150000)
			}()
			go func() {
				prime6 <- getPrime(350000)
			}()
			go func() {
				prime7 <- getPrime(300000)
			}()

			for i := 0; i < 8; i++ {
				select {
				case msg0 := <-prime0:
					fmt.Print("the 200000th prime number is: ")
					fmt.Println(msg0)
				case msg1 := <-prime1:
					fmt.Print("the 500000th prime number is: ")
					fmt.Println(msg1)
				case msg2 := <-prime2:
					fmt.Print("the 100000th prime number is: ")
					fmt.Println(msg2)
				case msg3 := <-prime3:
					fmt.Print("the 250000th prime number is: ")
					fmt.Println(msg3)
				case msg4 := <-prime4:
					fmt.Print("the 550000th prime number is: ")
					fmt.Println(msg4)
				case msg5 := <-prime5:
					fmt.Print("the 150000th prime number is: ")
					fmt.Println(msg5)
				case msg6 := <-prime6:
					fmt.Print("the 350000th prime number is: ")
					fmt.Println(msg6)
				case msg7 := <-prime7:
					fmt.Print("the 300000th prime number is: ")
					fmt.Println(msg7)
				}
			}
		}
		if os.Args[1] == "false" {
			fmt.Print("the 200000th prime number is: ")
			fmt.Println(getPrime(200000))
			fmt.Print("the 500000th prime number is: ")
			fmt.Println(getPrime(500000))
			fmt.Print("the 100000th prime number is: ")
			fmt.Println(getPrime(100000))
			fmt.Print("the 250000th prime number is: ")
			fmt.Println(getPrime(250000))
			fmt.Print("the 550000th prime number is: ")
			fmt.Println(getPrime(550000))
			fmt.Print("the 150000th prime number is: ")
			fmt.Println(getPrime(150000))
			fmt.Print("the 350000th prime number is: ")
			fmt.Println(getPrime(350000))
			fmt.Print("the 300000th prime number is: ")
			fmt.Println(getPrime(300000))
		}
	}
}
<commit_msg>refactor parallel for a more idiomatic approach<commit_after>package main

import (
	"fmt"
	"os"
)

var (
	// list of nth prime numbers to find
	requests = []int{200000, 500000, 100000, 250000, 550000, 150000, 350000, 300000}
)

func main() {
	if len(os.Args) == 1 {
		fmt.Println("start this application with the argument true to compute primenumbers parallel or false for serial")
		fmt.Println("you can configure the maximum processes/threads amount with: \"export GOMAXPROCS=$number\"")
		os.Exit(1)
	}

	if os.Args[1] == "true" {
		runParallel()
	} else {
		runSequential()
	}
}

func runSequential() {
	for _, index := range requests {
		fmt.Printf("the %dth prime number is: %d\n", index, getPrime(index))
	}
}

func runParallel() {
	// data struct that goroutines will send information
	// back to main thread
	type WorkerResponse struct {
		Index int
		Prime int
	}

	workerChan := make(chan WorkerResponse)
	defer close(workerChan)

	// send requests to n goroutines
	for _, index := range requests {
		// start this goroutine with the index in the loop
		// we must give this param, because index would be shared memory
		go func(idx int) {
			workerChan <- WorkerResponse{Index: idx, Prime: getPrime(idx)}
		}(index)
	}

	for i := 0; i < len(requests); i++ {
		response := <-workerChan
		fmt.Printf("the %dth prime number is: %d\n", response.Index, response.Prime)
	}
}

func Sqrt(n int) int {
	var t uint
	var b uint
	var r uint
	t = uint(n)
	p := uint(1 << 30)
	for p > t {
		p >>= 2
	}
	for ; p != 0; p >>= 2 {
		b = r | p
		r >>= 1
		if t >= b {
			t -= b
			r |= p
		}
	}
	return int(r)
}

func getPrime(n int) int {
	var primeList = []int{2}
	var isPrime int = 1
	var num int = 3
	var sqrtNum int = 0
	for len(primeList) < n {
		sqrtNum = Sqrt(num)
		for i := 0; i < len(primeList); i++ {
			if num%primeList[i] == 0 {
				isPrime = 0
			}
			if primeList[i] > sqrtNum {
				i = len(primeList)
			}
		}
		if isPrime == 1 {
			primeList = append(primeList, num)
		} else {
			isPrime = 1
		}
		num = num + 2
	}
	return primeList[n-1]
}
<|endoftext|>


<commit_before>package explosm

import (
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"time"

	"github.com/mmcdole/gofeed"
)

const (
	explosmFeedURL = "https://explosm.net/rss.xml"
)

var (
	// Compare the test and source on the website to see if this regex is still valid
	imgRegexp = regexp.MustCompile(`(?s)<div id="comic".*?>.*?(<img src.*?>).*?</div>`)
)

type Explosm struct {
	RefreshInterval time.Duration

	data    []byte
	rssData channel
}

func (e *Explosm) Run(abort chan struct{}) {
	// Execute it the first time
	if err := e.Do(); err != nil {
		log.Printf("could not run: %s", err)
	}
	for {
		select {
		case <-abort:
			return
		case <-time.After(e.RefreshInterval):
			if err := e.Do(); err != nil {
				log.Printf("could not run: %s", err)
			}
		}
	}
}

func (e *Explosm) Do() error {
	fp := gofeed.NewParser()
	feed, err := fp.ParseURL(explosmFeedURL)
	if err != nil {
		return err
	}
	var is []Item
	for _, i := range feed.Items {
		e := Explosm{}
		if err := e.GetData(i.Link); err != nil {
			// Tolerate bad entries and just log them
			log.Printf("could not get data from link: %s\n", err)
			continue
		}
		imgEle := FindComicURL(e.data)
		if imgEle == "" {
			// Tolerate bad entries and just log them
			log.Printf("could not find image link from feed item\n")
		}
		is = append(is, Item{
			Title:       i.Title,
			Link:        i.Link,
			Description: CDataTest{imgEle},
			Category:    i.Categories,
			Guid:        i.GUID,
			PubDate:     i.Published,
		})
	}
	e.rssData = channel{
		Title:       feed.Title,
		Description: feed.Description,
		Link:        feed.Link,
		Item:        is,
		Image: Image{
			URL:   "//files.explosm.net/img/favicons/site/favicon-96x96.png",
			Link:  feed.Link,
			Title: feed.Title,
		},
	}
	return nil
}

func (e *Explosm) GetData(url string) error {
	d, err := e.getDataFromNet(url)
	if err != nil {
		return err
	}
	e.data = d
	return nil
}

func FindComicURL(data []byte) string {
	matches := imgRegexp.FindSubmatch(data)
	if len(matches) > 1 {
		return string(matches[1])
	}
	return ""
}

func (e *Explosm) getDataFromNet(url string) ([]byte, error) {
	res, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (e *Explosm) Generate() string {
	if len(e.rssData.Item) == 0 {
		return "Please try again. There was an error retrieving the feeds: no feeds."
	}
	return generate(e.rssData)
}
<commit_msg>Fix image css by extracting the src only<commit_after>package explosm

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"time"

	"github.com/mmcdole/gofeed"
)

const (
	explosmFeedURL = "https://explosm.net/rss.xml"
)

var (
	// Compare the test and source on the website to see if this regex is still valid
	imgRegexp = regexp.MustCompile(`(?s)<div id="comic".*?>.*?<img src="(.*?)".*?>`)
)

type Explosm struct {
	RefreshInterval time.Duration

	data    []byte
	rssData channel
}

func (e *Explosm) Run(abort chan struct{}) {
	// Execute it the first time
	if err := e.Do(); err != nil {
		log.Printf("could not run: %s", err)
	}
	for {
		select {
		case <-abort:
			return
		case <-time.After(e.RefreshInterval):
			if err := e.Do(); err != nil {
				log.Printf("could not run: %s", err)
			}
		}
	}
}

func (e *Explosm) Do() error {
	fp := gofeed.NewParser()
	feed, err := fp.ParseURL(explosmFeedURL)
	if err != nil {
		return err
	}
	var is []Item
	for _, i := range feed.Items {
		e := Explosm{}
		if err := e.GetData(i.Link); err != nil {
			// Tolerate bad entries and just log them
			log.Printf("could not get data from link: %s\n", err)
			continue
		}
		imgSrc := FindComicURL(e.data)
		imgEle := fmt.Sprintf(`<img src="%s">`, imgSrc)
		if imgSrc == "" {
			// Tolerate bad entries and just log them
			log.Printf("could not find image link from feed item\n")
			imgEle = ""
		}
		is = append(is, Item{
			Title:       i.Title,
			Link:        i.Link,
			Description: CDataTest{imgEle},
			Category:    i.Categories,
			Guid:        i.GUID,
			PubDate:     i.Published,
		})
	}
	e.rssData = channel{
		Title:       feed.Title,
		Description: feed.Description,
		Link:        feed.Link,
		Item:        is,
		Image: Image{
			URL:   "//files.explosm.net/img/favicons/site/favicon-96x96.png",
			Link:  feed.Link,
			Title: feed.Title,
		},
	}
	return nil
}

func (e *Explosm) GetData(url string) error {
	d, err := e.getDataFromNet(url)
	if err != nil {
		return err
	}
	e.data = d
	return nil
}

func FindComicURL(data []byte) string {
	matches := imgRegexp.FindSubmatch(data)
	if len(matches) > 1 {
		return string(matches[1])
	}
	return ""
}

func (e *Explosm) getDataFromNet(url string) ([]byte, error) {
	res, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (e *Explosm) Generate() string {
	if len(e.rssData.Item) == 0 {
		return "Please try again. There was an error retrieving the feeds: no feeds."
	}
	return generate(e.rssData)
}
<|endoftext|>


<commit_before>package lazyexp

import (
	"sync"
	"testing"
)

type ConstNode struct {
	FetchValue func() int
	value      int
	once       sync.Once
}

func (c *ConstNode) Value() int {
	c.once.Do(func() {
		c.value = c.FetchValue()
	})
	return c.value
}

type SumNode struct {
	LHS  *ConstNode // must be pointers as we want to share nodes
	RHS  *ConstNode
	sum  int
	once sync.Once
}

func (s *SumNode) Value() int {
	s.once.Do(func() {
		var lhsVal, rhsVal int
		var wg sync.WaitGroup
		wg.Add(2)
		go func() {
			lhsVal = s.LHS.Value()
			wg.Done()
		}()
		go func() {
			rhsVal = s.RHS.Value()
			wg.Done()
		}()
		wg.Wait()
		s.sum = lhsVal + rhsVal
	})
	return s.sum
}

func TestShouldFetchLazilyOnce(t *testing.T) {
	oneFetchCount := 0
	one := ConstNode{
		FetchValue: func() int {
			oneFetchCount++
			return 1
		},
	}
	sum := SumNode{
		LHS: &one,
		RHS: &one,
	}
	if got := sum.Value(); got != 2 {
		t.Errorf("expected 1+1=2, got %d", got)
	}
	if oneFetchCount != 1 {
		t.Errorf("expected 1 fetch after getting sum initially, got %d", oneFetchCount)
	}
	if got := sum.Value(); got != 2 {
		t.Errorf("still expected 1+1=2, got %d", got)
	}
	if oneFetchCount != 1 {
		t.Errorf("still expected 1 fetch after getting sum again, got %d", oneFetchCount)
	}
}
<commit_msg>add test verifying parallel execution<commit_after>package lazyexp

import (
	"sync"
	"testing"
)

type ConstNode struct {
	FetchValue func() int
	value      int
	once       sync.Once
}

func (c *ConstNode) Value() int {
	c.once.Do(func() {
		c.value = c.FetchValue()
	})
	return c.value
}

type SumNode struct {
	LHS  *ConstNode // must be pointers as we want to share nodes
	RHS  *ConstNode
	sum  int
	once sync.Once
}

func (s *SumNode) Value() int {
	s.once.Do(func() {
		var lhsVal, rhsVal int
		var wg sync.WaitGroup
		wg.Add(2)
		go func() {
			lhsVal = s.LHS.Value()
			wg.Done()
		}()
		go func() {
			rhsVal = s.RHS.Value()
			wg.Done()
		}()
		wg.Wait()
		s.sum = lhsVal + rhsVal
	})
	return s.sum
}

func TestShouldFetchLazilyOnce(t *testing.T) {
	oneFetchCount := 0
	one := ConstNode{
		FetchValue: func() int {
			oneFetchCount++
			return 1
		},
	}
	sum := SumNode{
		LHS: &one,
		RHS: &one,
	}
	if got := sum.Value(); got != 2 {
		t.Errorf("expected 1+1=2, got %d", got)
	}
	if oneFetchCount != 1 {
		t.Errorf("expected 1 fetch after getting sum initially, got %d", oneFetchCount)
	}
	if got := sum.Value(); got != 2 {
		t.Errorf("still expected 1+1=2, got %d", got)
	}
	if oneFetchCount != 1 {
		t.Errorf("still expected 1 fetch after getting sum again, got %d", oneFetchCount)
	}
}

func TestShouldFetchInParallel(t *testing.T) {
	// two leafs that block until the other one is being evaluated
	fetchStarted := [...]chan struct{}{
		make(chan struct{}, 1),
		make(chan struct{}, 1),
	}
	leafs := [2]ConstNode{}
	for i := range leafs {
		j := i
		leafs[i] = ConstNode{
			FetchValue: func() int {
				close(fetchStarted[j])
				// wait for other node to be fetched
				<-fetchStarted[1-j]
				return j
			},
		}
	}
	root := SumNode{
		LHS: &leafs[0],
		RHS: &leafs[1],
	}
	// this will block indefinitely if the values are fetched sequentially
	if got := root.Value(); got != 1 {
		t.Errorf("expected 0+1=1, got %d", got)
	}
}
<|endoftext|>


<commit_before>package bebber

import (
  _"fmt"
  "time"
  "net/http"
  "github.com/gin-gonic/gin"
  "gopkg.in/mgo.v2/bson"
)

const (
  SessionsCollection = "sessions"
  TokenHeaderField = "X-XSRF-TOKEN"
)

func Auth(c *gin.Context, g Globals) {

    token := c.Request.Header.Get(TokenHeaderField)
    if token == "" {
      cookie, _ := c.Request.Cookie(XSRFCookieName)
      token = cookie.Value
      if token == "" {
        c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Header not found"})
        c.Abort()
        return
      }
    }

    session := g.MongoDB.Session.Copy()
    defer session.Close()

    sessionsColl := session.DB(g.MongoDB.DBName).C(SessionsCollection)
    query := sessionsColl.Find(bson.M{"token": token})
    n, err := query.Count()
    if err != nil {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", err.Error()})
      c.Abort()
      return
    }
    if n != 1 {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Session not found"})
      c.Abort()
      return

    }

    userSession := UserSession{}
    err = query.One(&userSession)
    if err != nil {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", err.Error()})
      c.Abort()
      return
    }
    if userSession.Expires.Before(time.Now()) {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Session expired"})
      c.Abort()
      return
    } else {
      c.Set("session", userSession)
      c.Next()
    }

}
<commit_msg>fix error when no cookie exists<commit_after>package bebber

import (
  _"fmt"
  "time"
  "net/http"
  "github.com/gin-gonic/gin"
  "gopkg.in/mgo.v2/bson"
)

const (
  SessionsCollection = "sessions"
  TokenHeaderField = "X-XSRF-TOKEN"
)

func Auth(c *gin.Context, g Globals) {

    token := c.Request.Header.Get(TokenHeaderField)
    if token == "" {
      cookie, err := c.Request.Cookie(XSRFCookieName)
      if err != nil {
        c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Cookie not found"})
        c.Abort()
        return
      }
      token = cookie.Value
      if token == "" {
        c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Header not found"})
        c.Abort()
        return
      }
    }

    session := g.MongoDB.Session.Copy()
    defer session.Close()

    sessionsColl := session.DB(g.MongoDB.DBName).C(SessionsCollection)
    query := sessionsColl.Find(bson.M{"token": token})
    n, err := query.Count()
    if err != nil {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", err.Error()})
      c.Abort()
      return
    }
    if n != 1 {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Session not found"})
      c.Abort()
      return

    }

    userSession := UserSession{}
    err = query.One(&userSession)
    if err != nil {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", err.Error()})
      c.Abort()
      return
    }
    if userSession.Expires.Before(time.Now()) {
      c.JSON(http.StatusUnauthorized, ErrorResponse{"fail", "Session expired"})
      c.Abort()
      return
    } else {
      c.Set("session", userSession)
      c.Next()
    }

}
<|endoftext|>


<commit_before>package ginprometheus

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	log "github.com/sirupsen/logrus"
)

var defaultMetricPath = "/metrics"

// Prometheus contains the metrics gathered by the instance and its path
type Prometheus struct {
	reqCnt               *prometheus.CounterVec
	reqDur, reqSz, resSz prometheus.Summary
	router               *gin.Engine
	listenAddress        string

	Ppg PrometheusPushGateway

	MetricsPath string
}

// PrometheusPushGateway contains the configuration for pushing to a Prometheus pushgateway (optional)
type PrometheusPushGateway struct {

	// Push interval in seconds
	PushIntervalSeconds time.Duration

	// Push Gateway URL in format http://domain:port
	// where JOBNAME can be any string of your choice
	PushGatewayURL string

	// Local metrics URL where metrics are fetched from, this could be ommited in the future
	// if implemented using prometheus common/expfmt instead
	MetricsURL string

	// pushgateway job name, defaults to "gin"
	Job string
}

// NewPrometheus generates a new set of metrics with a certain subsystem name
func NewPrometheus(subsystem string) *Prometheus {

	p := &Prometheus{
		MetricsPath: defaultMetricPath,
	}
	p.registerMetrics(subsystem)

	return p
}

// SetPushGateway sends metrics to a remote pushgateway exposed on pushGatewayURL
// every pushIntervalSeconds. Metrics are fetched from metricsURL
func (p *Prometheus) SetPushGateway(pushGatewayURL, metricsURL string, pushIntervalSeconds time.Duration) {
	p.Ppg.PushGatewayURL = pushGatewayURL
	p.Ppg.MetricsURL = metricsURL
	p.Ppg.PushIntervalSeconds = pushIntervalSeconds
	p.startPushTicker()
}

// SetPushGatewayJob job name, defaults to "gin"
func (p *Prometheus) SetPushGatewayJob(j string) {
	p.Ppg.Job = j
}

// SetListenAddress for exposing metrics on address. If not set, it will be exposed at the
// same address of the gin engine that is being used
func (p *Prometheus) SetListenAddress(address string) {
	p.listenAddress = address
	if p.listenAddress != "" {
		p.router = gin.Default()
	}
}

func (p *Prometheus) setMetricsPath(e *gin.Engine) {

	if p.listenAddress != "" {
		p.router.GET(p.MetricsPath, prometheusHandler())
		p.runServer()
	} else {
		e.GET(p.MetricsPath, prometheusHandler())
	}
}

func (p *Prometheus) setMetricsPathWithAuth(e *gin.Engine, accounts gin.Accounts) {

	if p.listenAddress != "" {
		p.router.GET(p.MetricsPath, gin.BasicAuth(accounts), prometheusHandler())
		p.runServer()
	} else {
		e.GET(p.MetricsPath, gin.BasicAuth(accounts), prometheusHandler())
	}

}

func (p *Prometheus) runServer() {
	if p.listenAddress != "" {
		go p.router.Run(p.listenAddress)
	}
}

func (p *Prometheus) getMetrics() []byte {
	response, _ := http.Get(p.Ppg.MetricsURL)

	defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)

	return body
}

func (p *Prometheus) getPushGatewayURL() string {
	h, _ := os.Hostname()
	if p.Ppg.Job == "" {
		p.Ppg.Job = "gin"
	}
	return p.Ppg.PushGatewayURL + "/metrics/job/" + p.Ppg.Job + "/instance/" + h
}

func (p *Prometheus) sendMetricsToPushGateway(metrics []byte) {
	req, err := http.NewRequest("POST", p.getPushGatewayURL(), bytes.NewBuffer(metrics))
	client := &http.Client{}
	_, err = client.Do(req)
	if err != nil {
		log.Error("Error sending to push gatway: " + err.Error())
	}
}

func (p *Prometheus) startPushTicker() {
	ticker := time.NewTicker(time.Second * p.Ppg.PushIntervalSeconds)
	go func() {
		for range ticker.C {
			p.sendMetricsToPushGateway(p.getMetrics())
		}
	}()
}

func (p *Prometheus) registerMetrics(subsystem string) {

	p.reqCnt = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: subsystem,
			Name:      "requests_total",
			Help:      "How many HTTP requests processed, partitioned by status code and HTTP method.",
		},
		[]string{"code", "method", "handler", "host"},
	)

	if err := prometheus.Register(p.reqCnt); err != nil {
		log.Info("reqCnt could not be registered: ", err)
	} else {
		log.Info("reqCnt registered.")
	}

	p.reqDur = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "request_duration_seconds",
			Help:      "The HTTP request latencies in seconds.",
		},
	)

	if err := prometheus.Register(p.reqDur); err != nil {
		log.Info("reqDur could not be registered: ", err)
	} else {
		log.Info("reqDur registered.")
	}

	p.reqSz = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "request_size_bytes",
			Help:      "The HTTP request sizes in bytes.",
		},
	)

	if err := prometheus.Register(p.reqSz); err != nil {
		log.Info("reqSz could not be registered: ", err)
	} else {
		log.Info("reqSz registered.")
	}

	p.resSz = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "response_size_bytes",
			Help:      "The HTTP response sizes in bytes.",
		},
	)

	if err := prometheus.Register(p.resSz); err != nil {
		log.Info("resSz could not be registered: ", err)
	} else {
		log.Info("resSz registered.")
	}

}

// Use adds the middleware to a gin engine.
func (p *Prometheus) Use(e *gin.Engine) {
	e.Use(p.handlerFunc())
	p.setMetricsPath(e)
}

// UseWithAuth adds the middleware to a gin engine with BasicAuth.
func (p *Prometheus) UseWithAuth(e *gin.Engine, accounts gin.Accounts) {
	e.Use(p.handlerFunc())
	p.setMetricsPathWithAuth(e, accounts)
}

func (p *Prometheus) handlerFunc() gin.HandlerFunc {
	return func(c *gin.Context) {
		if c.Request.URL.String() == p.MetricsPath {
			c.Next()
			return
		}

		start := time.Now()
		reqSz := computeApproximateRequestSize(c.Request)

		c.Next()

		status := strconv.Itoa(c.Writer.Status())
		elapsed := float64(time.Since(start)) / float64(time.Second)
		resSz := float64(c.Writer.Size())

		p.reqDur.Observe(elapsed)
		p.reqCnt.WithLabelValues(status, c.Request.Method, c.HandlerName(), c.Request.Host).Inc()
		p.reqSz.Observe(float64(reqSz))
		p.resSz.Observe(resSz)
	}
}

func prometheusHandler() gin.HandlerFunc {
	h := promhttp.Handler()
	return func(c *gin.Context) {
		h.ServeHTTP(c.Writer, c.Request)
	}
}

// From https://github.com/DanielHeckrath/gin-prometheus/blob/master/gin_prometheus.go
func computeApproximateRequestSize(r *http.Request) int {
	s := 0
	if r.URL != nil {
		s = len(r.URL.String())
	}

	s += len(r.Method)
	s += len(r.Proto)
	for name, values := range r.Header {
		s += len(name)
		for _, value := range values {
			s += len(value)
		}
	}
	s += len(r.Host)

	// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.

	if r.ContentLength != -1 {
		s += int(r.ContentLength)
	}
	return s
}
<commit_msg>Add url label to request counter<commit_after>package ginprometheus

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	log "github.com/sirupsen/logrus"
)

var defaultMetricPath = "/metrics"

// Prometheus contains the metrics gathered by the instance and its path
type Prometheus struct {
	reqCnt               *prometheus.CounterVec
	reqDur, reqSz, resSz prometheus.Summary
	router               *gin.Engine
	listenAddress        string

	Ppg PrometheusPushGateway

	MetricsPath string
}

// PrometheusPushGateway contains the configuration for pushing to a Prometheus pushgateway (optional)
type PrometheusPushGateway struct {

	// Push interval in seconds
	PushIntervalSeconds time.Duration

	// Push Gateway URL in format http://domain:port
	// where JOBNAME can be any string of your choice
	PushGatewayURL string

	// Local metrics URL where metrics are fetched from, this could be ommited in the future
	// if implemented using prometheus common/expfmt instead
	MetricsURL string

	// pushgateway job name, defaults to "gin"
	Job string
}

// NewPrometheus generates a new set of metrics with a certain subsystem name
func NewPrometheus(subsystem string) *Prometheus {

	p := &Prometheus{
		MetricsPath: defaultMetricPath,
	}
	p.registerMetrics(subsystem)

	return p
}

// SetPushGateway sends metrics to a remote pushgateway exposed on pushGatewayURL
// every pushIntervalSeconds. Metrics are fetched from metricsURL
func (p *Prometheus) SetPushGateway(pushGatewayURL, metricsURL string, pushIntervalSeconds time.Duration) {
	p.Ppg.PushGatewayURL = pushGatewayURL
	p.Ppg.MetricsURL = metricsURL
	p.Ppg.PushIntervalSeconds = pushIntervalSeconds
	p.startPushTicker()
}

// SetPushGatewayJob job name, defaults to "gin"
func (p *Prometheus) SetPushGatewayJob(j string) {
	p.Ppg.Job = j
}

// SetListenAddress for exposing metrics on address. If not set, it will be exposed at the
// same address of the gin engine that is being used
func (p *Prometheus) SetListenAddress(address string) {
	p.listenAddress = address
	if p.listenAddress != "" {
		p.router = gin.Default()
	}
}

func (p *Prometheus) setMetricsPath(e *gin.Engine) {

	if p.listenAddress != "" {
		p.router.GET(p.MetricsPath, prometheusHandler())
		p.runServer()
	} else {
		e.GET(p.MetricsPath, prometheusHandler())
	}
}

func (p *Prometheus) setMetricsPathWithAuth(e *gin.Engine, accounts gin.Accounts) {

	if p.listenAddress != "" {
		p.router.GET(p.MetricsPath, gin.BasicAuth(accounts), prometheusHandler())
		p.runServer()
	} else {
		e.GET(p.MetricsPath, gin.BasicAuth(accounts), prometheusHandler())
	}

}

func (p *Prometheus) runServer() {
	if p.listenAddress != "" {
		go p.router.Run(p.listenAddress)
	}
}

func (p *Prometheus) getMetrics() []byte {
	response, _ := http.Get(p.Ppg.MetricsURL)

	defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)

	return body
}

func (p *Prometheus) getPushGatewayURL() string {
	h, _ := os.Hostname()
	if p.Ppg.Job == "" {
		p.Ppg.Job = "gin"
	}
	return p.Ppg.PushGatewayURL + "/metrics/job/" + p.Ppg.Job + "/instance/" + h
}

func (p *Prometheus) sendMetricsToPushGateway(metrics []byte) {
	req, err := http.NewRequest("POST", p.getPushGatewayURL(), bytes.NewBuffer(metrics))
	client := &http.Client{}
	_, err = client.Do(req)
	if err != nil {
		log.Error("Error sending to push gatway: " + err.Error())
	}
}

func (p *Prometheus) startPushTicker() {
	ticker := time.NewTicker(time.Second * p.Ppg.PushIntervalSeconds)
	go func() {
		for range ticker.C {
			p.sendMetricsToPushGateway(p.getMetrics())
		}
	}()
}

func (p *Prometheus) registerMetrics(subsystem string) {

	p.reqCnt = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Subsystem: subsystem,
			Name:      "requests_total",
			Help:      "How many HTTP requests processed, partitioned by status code and HTTP method.",
		},
		[]string{"code", "method", "handler", "host", "url"},
	)

	if err := prometheus.Register(p.reqCnt); err != nil {
		log.Info("reqCnt could not be registered: ", err)
	} else {
		log.Info("reqCnt registered.")
	}

	p.reqDur = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "request_duration_seconds",
			Help:      "The HTTP request latencies in seconds.",
		},
	)

	if err := prometheus.Register(p.reqDur); err != nil {
		log.Info("reqDur could not be registered: ", err)
	} else {
		log.Info("reqDur registered.")
	}

	p.reqSz = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "request_size_bytes",
			Help:      "The HTTP request sizes in bytes.",
		},
	)

	if err := prometheus.Register(p.reqSz); err != nil {
		log.Info("reqSz could not be registered: ", err)
	} else {
		log.Info("reqSz registered.")
	}

	p.resSz = prometheus.NewSummary(
		prometheus.SummaryOpts{
			Subsystem: subsystem,
			Name:      "response_size_bytes",
			Help:      "The HTTP response sizes in bytes.",
		},
	)

	if err := prometheus.Register(p.resSz); err != nil {
		log.Info("resSz could not be registered: ", err)
	} else {
		log.Info("resSz registered.")
	}

}

// Use adds the middleware to a gin engine.
func (p *Prometheus) Use(e *gin.Engine) {
	e.Use(p.handlerFunc())
	p.setMetricsPath(e)
}

// UseWithAuth adds the middleware to a gin engine with BasicAuth.
func (p *Prometheus) UseWithAuth(e *gin.Engine, accounts gin.Accounts) {
	e.Use(p.handlerFunc())
	p.setMetricsPathWithAuth(e, accounts)
}

func (p *Prometheus) handlerFunc() gin.HandlerFunc {
	return func(c *gin.Context) {
		if c.Request.URL.String() == p.MetricsPath {
			c.Next()
			return
		}

		start := time.Now()
		reqSz := computeApproximateRequestSize(c.Request)

		c.Next()

		status := strconv.Itoa(c.Writer.Status())
		elapsed := float64(time.Since(start)) / float64(time.Second)
		resSz := float64(c.Writer.Size())

		p.reqDur.Observe(elapsed)
		p.reqCnt.WithLabelValues(status, c.Request.Method, c.HandlerName(), c.Request.Host, c.Request.URL.String()).Inc()
		p.reqSz.Observe(float64(reqSz))
		p.resSz.Observe(resSz)
	}
}

func prometheusHandler() gin.HandlerFunc {
	h := promhttp.Handler()
	return func(c *gin.Context) {
		h.ServeHTTP(c.Writer, c.Request)
	}
}

// From https://github.com/DanielHeckrath/gin-prometheus/blob/master/gin_prometheus.go
func computeApproximateRequestSize(r *http.Request) int {
	s := 0
	if r.URL != nil {
		s = len(r.URL.String())
	}

	s += len(r.Method)
	s += len(r.Proto)
	for name, values := range r.Header {
		s += len(name)
		for _, value := range values {
			s += len(value)
		}
	}
	s += len(r.Host)

	// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.

	if r.ContentLength != -1 {
		s += int(r.ContentLength)
	}
	return s
}
<|endoftext|>


<commit_before>package notifications

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
)

const maxNotifications = 50

// All shows all notifications sent so far.
func All(ctx *aero.Context) string {
	user := utils.GetUser(ctx)

	if user == nil {
		return ctx.Error(http.StatusBadRequest, "Not logged in", nil)
	}

	notifications := user.Notifications().Notifications()

	// Sort by date
	sort.Slice(notifications, func(i, j int) bool {
		return notifications[i].Created > notifications[j].Created
	})

	// Limit results
	if len(notifications) > maxNotifications {
		notifications = notifications[:maxNotifications]
	}

	return ctx.HTML(components.Notifications(notifications, user))
}
<commit_msg>Reduced notification limit<commit_after>package notifications

import (
	"net/http"
	"sort"

	"github.com/aerogo/aero"
	"github.com/animenotifier/notify.moe/components"
	"github.com/animenotifier/notify.moe/utils"
)

const maxNotifications = 30

// All shows all notifications sent so far.
func All(ctx *aero.Context) string {
	user := utils.GetUser(ctx)

	if user == nil {
		return ctx.Error(http.StatusBadRequest, "Not logged in", nil)
	}

	notifications := user.Notifications().Notifications()

	// Sort by date
	sort.Slice(notifications, func(i, j int) bool {
		return notifications[i].Created > notifications[j].Created
	})

	// Limit results
	if len(notifications) > maxNotifications {
		notifications = notifications[:maxNotifications]
	}

	return ctx.HTML(components.Notifications(notifications, user))
}
<|endoftext|>


<commit_before>// +build integration

/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

func TestPreload(t *testing.T) {
	if NoneDriver() {
		t.Skipf("skipping %s - incompatible with none driver", t.Name())
	}

	profile := UniqueProfileName("test-preload")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(40))
	defer CleanupWithLogs(t, profile, cancel)

	startArgs := []string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=3", "--wait=true", "--preload=false"}
	startArgs = append(startArgs, StartArgs()...)
	k8sVersion := "v1.17.0"
	startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", k8sVersion))

	rr, err := Run(t, exec.CommandContext(ctx, Target(), startArgs...))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}

	// Now, pull the busybox image into the VMs docker daemon
	image := "busybox"
	rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "pull", image))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}

	// Restart minikube with v1.17.3, which has a preloaded tarball
	startArgs = []string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=3", "--wait=true"}
	startArgs = append(startArgs, StartArgs()...)
	k8sVersion = "v1.17.3"
	startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", k8sVersion))
	rr, err = Run(t, exec.CommandContext(ctx, Target(), startArgs...))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}
	rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images"))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}
	if !strings.Contains(rr.Output(), image) {
		t.Fatalf("Expected to find %s in output of `docker images`, instead got %s", image, rr.Output())
	}
}
<commit_msg>fix lint<commit_after>// +build integration

/*
Copyright 2020 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package integration

import (
	"context"
	"fmt"
	"os/exec"
	"strings"
	"testing"
)

func TestPreload(t *testing.T) {
	if NoneDriver() {
		t.Skipf("skipping %s - incompatible with none driver", t.Name())
	}

	profile := UniqueProfileName("test-preload")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(40))
	defer CleanupWithLogs(t, profile, cancel)

	startArgs := []string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=3", "--wait=true", "--preload=false"}
	startArgs = append(startArgs, StartArgs()...)
	k8sVersion := "v1.17.0"
	startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", k8sVersion))

	rr, err := Run(t, exec.CommandContext(ctx, Target(), startArgs...))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}

	// Now, pull the busybox image into the VMs docker daemon
	image := "busybox"
	rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "pull", image))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}

	// Restart minikube with v1.17.3, which has a preloaded tarball
	startArgs = []string{"start", "-p", profile, "--memory=2200", "--alsologtostderr", "-v=3", "--wait=true"}
	startArgs = append(startArgs, StartArgs()...)
	k8sVersion = "v1.17.3"
	startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", k8sVersion))
	rr, err = Run(t, exec.CommandContext(ctx, Target(), startArgs...))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}
	rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images"))
	if err != nil {
		t.Fatalf("%s failed: %v", rr.Command(), err)
	}
	if !strings.Contains(rr.Output(), image) {
		t.Fatalf("Expected to find %s in output of `docker images`, instead got %s", image, rr.Output())
	}
}
<|endoftext|>