<commit_before>package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/fatih/color"
	"github.com/fd0/termstatus"
	"github.com/spf13/pflag"
)

var opts = struct {
	threads          int
	placeholder      string
	workerTimeout    time.Duration
	useNullSeparator bool
	hideJobID        bool
	hideTimestamp    bool
	hideName         bool
}{}

func init() {
	pflag.IntVarP(&opts.threads, "procs", "p", runtime.NumCPU(), "number of parallel porgrams")
	pflag.StringVar(&opts.placeholder, "replace", "{}", "replace this string in the command to run")
	pflag.DurationVar(&opts.workerTimeout, "timeout", 0*time.Second, "set maximum runtime per queued job (0s == no limit)")
	pflag.BoolVarP(&opts.useNullSeparator, "null", "0", false, "use null bytes as input separator")
	pflag.BoolVar(&opts.hideJobID, "no-id", false, "hide the job id in the log")
	pflag.BoolVar(&opts.hideTimestamp, "no-timestamp", false, "hide the time stamp in the log")
	pflag.BoolVar(&opts.hideName, "no-name", false, "hide the job name in the log")
	pflag.Parse()
}

// ScanNullSeparatedValues splits data by null bytes
func ScanNullSeparatedValues(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	for i, b := range data {
		if b == 0 {
			return i + 1, data[:i], nil
		}
	}

	if atEOF {
		return len(data), data, nil
	}

	return 0, nil, nil
}

func parseInput(ch chan<- *Command, cmd string, args []string) {
	defer close(ch)

	sc := bufio.NewScanner(os.Stdin)

	if opts.useNullSeparator {
		sc.Split(ScanNullSeparatedValues)
	}

	jobnum := 1
	for sc.Scan() {
		cmdName := cmd
		cmdArgs := make([]string, 0, len(args))

		line := strings.TrimSpace(sc.Text())

		if line == "" {
			fmt.Fprintf(os.Stderr, "ignoring empty item\n")
			continue
		}

		cmdName = strings.Replace(cmd, opts.placeholder, line, -1)

		for _, arg := range args {
			cmdArgs = append(cmdArgs, strings.Replace(arg, opts.placeholder, line, -1))
		}

		ch <- &Command{
			ID:   jobnum,
			Tag:  line,
			Cmd:  cmdName,
			Args: cmdArgs,
		}
		jobnum++
	}
}

func checkForPlaceholder(cmdname string, args []string) {
	if cmdname == opts.placeholder {
		return
	}

	for _, arg := range args {
		if strings.Contains(arg, opts.placeholder) {
			return
		}
	}

	fmt.Fprintf(os.Stderr, "no placeholder found\n")
	os.Exit(2)
}

// Status is one message printed by a command.
type Status struct {
	ID      int
	Tag     string
	Message string
	Error   bool

	Done  bool
	Start bool
}

func formatDuration(d time.Duration) string {
	sec := uint64(d / time.Second)

	hours := sec / 3600
	sec -= hours * 3600
	min := sec / 60
	sec -= min * 60
	if hours > 0 {
		return fmt.Sprintf("%d:%02d:%02d", hours, min, sec)
	}

	return fmt.Sprintf("%d:%02d", min, sec)
}

var (
	colorNumber    = color.New(color.Reset, color.FgGreen).SprintFunc()
	colorTimestamp = color.New(color.Reset, color.FgBlue).SprintFunc()
	colorTag       = color.New(color.Reset, color.FgYellow).SprintFunc()
	colorError     = color.New(color.Reset, color.FgRed, color.Bold).SprintFunc()

	colorStatusLine = color.New(color.Bold, color.ReverseVideo).SprintFunc()
)

var (
	lastLineCount          = 0
	lastLineCountReduction time.Time
	smoothLines            = 0
	lastUpdate             time.Time
)

func updateTerminal(t *termstatus.Terminal, start time.Time, processed, failed int, data map[string]string) {
	if time.Since(lastUpdate) < 50*time.Millisecond {
		return
	}
	lastUpdate = time.Now()

	keys := make([]string, 0, len(data))
	for k := range data {
		keys = append(keys, k)
	}
	sort.Sort(sort.StringSlice(keys))

	lines := make([]string, 0, len(data)+3)
	lines = append(lines, colorStatusLine(fmt.Sprintf("[%s] %d processed (%d failed), %d/%d workers:",
		formatDuration(time.Since(start)),
		processed,
		failed,
		len(data),
		opts.threads)))

	for _, key := range keys {
		lines = append(lines, data[key])
	}

	lineCount := len(lines)

	if lineCount > smoothLines {
		smoothLines = lineCount
	} else if lineCount < lastLineCount {
		lastLineCountReduction = time.Now()
	}

	if time.Since(lastLineCountReduction) > 500*time.Millisecond {
		smoothLines = lineCount
	}

	for i := 0; i < smoothLines-lineCount; i++ {
		lines = append(lines, "")
	}

	lastLineCount = lineCount

	t.SetStatus(lines)
}

const timeFormat = "2006-01-02 15:04:05"

func status(ctx context.Context, wg *sync.WaitGroup, t *termstatus.Terminal, outCh <-chan Status) {
	defer wg.Done()
	stat := make(map[string]string)

	start := time.Now()
	ticker := time.NewTicker(200 * time.Millisecond)
	defer ticker.Stop()

	var stats = struct {
		processed int
		failed    int
	}{}

	defer func() {
		t.Finish()
		fmt.Fprintf(color.Output, "\nprocessed %d items (%d failures) in %s\n",
			stats.processed,
			stats.failed,
			formatDuration(time.Since(start)))
	}()

	for {
		select {
		case <-ctx.Done():
			return
		case s, ok := <-outCh:
			if !ok {
				return
			}

			var msg string
			if s.Message != "" {
				msg = s.Message
				if s.Error {
					msg = fmt.Sprintf("%v %v", colorError("error"), colorError(s.Message))
				}
			}

			if msg != "" {
				m := ""
				if !opts.hideJobID {
					m += colorNumber(s.ID) + " "
				}

				if !opts.hideTimestamp {
					m += colorTimestamp(time.Now().Format(timeFormat)) + " "
				}

				if !opts.hideName {
					m += colorTag(s.Tag) + " "
				}

				t.Print(m + msg)
			}

			stat[s.Tag] = fmt.Sprintf("%v %v", colorTag(s.Tag), msg)

			if s.Done {
				stats.processed++

				if s.Error {
					stats.failed++
				}

				delete(stat, s.Tag)
			}

			updateTerminal(t, start, stats.processed, stats.failed, stat)
		case <-ticker.C:
			updateTerminal(t, start, stats.processed, stats.failed, stat)
		}
	}
}

type fakeTerminal struct {
	io.Writer
	fd uintptr
}

func (t fakeTerminal) Fd() uintptr { return t.fd }

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

	var t *termstatus.Terminal
	if runtime.GOOS == "windows" {
		t = termstatus.New(ctx, &fakeTerminal{color.Output, os.Stdout.Fd()})
	} else {
		t = termstatus.New(ctx, os.Stdout)
	}
	outCh := make(chan Status)

	var statusWg sync.WaitGroup
	statusWg.Add(1)
	go status(ctx, &statusWg, t, outCh)

	ch := make(chan *Command)

	var workersWg sync.WaitGroup
	for i := 0; i < opts.threads; i++ {
		workersWg.Add(1)
		go worker(&workersWg, ch, outCh)
	}

	args := pflag.Args()
	if len(args) == 0 {
		fmt.Fprintf(os.Stderr, "no command given\n")
		pflag.Usage()
		os.Exit(1)
	}

	cmdname := args[0]
	args = args[1:]

	checkForPlaceholder(cmdname, args)

	go parseInput(ch, cmdname, args)

	workersWg.Wait()
	close(outCh)

	statusWg.Wait()
}
<commit_msg>Update screen every time new data is available<commit_after>package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/fatih/color"
	"github.com/fd0/termstatus"
	"github.com/spf13/pflag"
)

var opts = struct {
	threads          int
	placeholder      string
	workerTimeout    time.Duration
	useNullSeparator bool
	hideJobID        bool
	hideTimestamp    bool
	hideName         bool
}{}

func init() {
	pflag.IntVarP(&opts.threads, "procs", "p", runtime.NumCPU(), "number of parallel porgrams")
	pflag.StringVar(&opts.placeholder, "replace", "{}", "replace this string in the command to run")
	pflag.DurationVar(&opts.workerTimeout, "timeout", 0*time.Second, "set maximum runtime per queued job (0s == no limit)")
	pflag.BoolVarP(&opts.useNullSeparator, "null", "0", false, "use null bytes as input separator")
	pflag.BoolVar(&opts.hideJobID, "no-id", false, "hide the job id in the log")
	pflag.BoolVar(&opts.hideTimestamp, "no-timestamp", false, "hide the time stamp in the log")
	pflag.BoolVar(&opts.hideName, "no-name", false, "hide the job name in the log")
	pflag.Parse()
}

// ScanNullSeparatedValues splits data by null bytes
func ScanNullSeparatedValues(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	for i, b := range data {
		if b == 0 {
			return i + 1, data[:i], nil
		}
	}

	if atEOF {
		return len(data), data, nil
	}

	return 0, nil, nil
}

func parseInput(ch chan<- *Command, cmd string, args []string) {
	defer close(ch)

	sc := bufio.NewScanner(os.Stdin)

	if opts.useNullSeparator {
		sc.Split(ScanNullSeparatedValues)
	}

	jobnum := 1
	for sc.Scan() {
		cmdName := cmd
		cmdArgs := make([]string, 0, len(args))

		line := strings.TrimSpace(sc.Text())

		if line == "" {
			fmt.Fprintf(os.Stderr, "ignoring empty item\n")
			continue
		}

		cmdName = strings.Replace(cmd, opts.placeholder, line, -1)

		for _, arg := range args {
			cmdArgs = append(cmdArgs, strings.Replace(arg, opts.placeholder, line, -1))
		}

		ch <- &Command{
			ID:   jobnum,
			Tag:  line,
			Cmd:  cmdName,
			Args: cmdArgs,
		}
		jobnum++
	}
}

func checkForPlaceholder(cmdname string, args []string) {
	if cmdname == opts.placeholder {
		return
	}

	for _, arg := range args {
		if strings.Contains(arg, opts.placeholder) {
			return
		}
	}

	fmt.Fprintf(os.Stderr, "no placeholder found\n")
	os.Exit(2)
}

// Status is one message printed by a command.
type Status struct {
	ID      int
	Tag     string
	Message string
	Error   bool

	Done  bool
	Start bool
}

func formatDuration(d time.Duration) string {
	sec := uint64(d / time.Second)

	hours := sec / 3600
	sec -= hours * 3600
	min := sec / 60
	sec -= min * 60
	if hours > 0 {
		return fmt.Sprintf("%d:%02d:%02d", hours, min, sec)
	}

	return fmt.Sprintf("%d:%02d", min, sec)
}

var (
	colorNumber    = color.New(color.Reset, color.FgGreen).SprintFunc()
	colorTimestamp = color.New(color.Reset, color.FgBlue).SprintFunc()
	colorTag       = color.New(color.Reset, color.FgYellow).SprintFunc()
	colorError     = color.New(color.Reset, color.FgRed, color.Bold).SprintFunc()

	colorStatusLine = color.New(color.Bold, color.ReverseVideo).SprintFunc()
)

var (
	lastLineCount          = 0
	lastLineCountReduction time.Time
	smoothLines            = 0
)

func updateTerminal(t *termstatus.Terminal, start time.Time, processed, failed int, data map[string]string) {
	keys := make([]string, 0, len(data))
	for k := range data {
		keys = append(keys, k)
	}
	sort.Sort(sort.StringSlice(keys))

	lines := make([]string, 0, len(data)+3)
	lines = append(lines, colorStatusLine(fmt.Sprintf("[%s] %d processed (%d failed), %d/%d workers:",
		formatDuration(time.Since(start)),
		processed,
		failed,
		len(data),
		opts.threads)))

	for _, key := range keys {
		lines = append(lines, data[key])
	}

	lineCount := len(lines)

	if lineCount > smoothLines {
		smoothLines = lineCount
	} else if lineCount < lastLineCount {
		lastLineCountReduction = time.Now()
	}

	if time.Since(lastLineCountReduction) > 500*time.Millisecond {
		smoothLines = lineCount
	}

	for i := 0; i < smoothLines-lineCount; i++ {
		lines = append(lines, "")
	}

	lastLineCount = lineCount

	t.SetStatus(lines)
}

const timeFormat = "2006-01-02 15:04:05"

func status(ctx context.Context, wg *sync.WaitGroup, t *termstatus.Terminal, outCh <-chan Status) {
	defer wg.Done()
	stat := make(map[string]string)

	start := time.Now()
	ticker := time.NewTicker(200 * time.Millisecond)
	defer ticker.Stop()

	var stats = struct {
		processed int
		failed    int
	}{}

	defer func() {
		t.Finish()
		fmt.Fprintf(color.Output, "\nprocessed %d items (%d failures) in %s\n",
			stats.processed,
			stats.failed,
			formatDuration(time.Since(start)))
	}()

	for {
		select {
		case <-ctx.Done():
			return
		case s, ok := <-outCh:
			if !ok {
				return
			}

			var msg string
			if s.Message != "" {
				msg = s.Message
				if s.Error {
					msg = fmt.Sprintf("%v %v", colorError("error"), colorError(s.Message))
				}
			}

			if msg != "" {
				m := ""
				if !opts.hideJobID {
					m += colorNumber(s.ID) + " "
				}

				if !opts.hideTimestamp {
					m += colorTimestamp(time.Now().Format(timeFormat)) + " "
				}

				if !opts.hideName {
					m += colorTag(s.Tag) + " "
				}

				t.Print(m + msg)
			}

			stat[s.Tag] = fmt.Sprintf("%v %v", colorTag(s.Tag), msg)

			if s.Done {
				stats.processed++

				if s.Error {
					stats.failed++
				}

				delete(stat, s.Tag)
			}

			updateTerminal(t, start, stats.processed, stats.failed, stat)
		case <-ticker.C:
			updateTerminal(t, start, stats.processed, stats.failed, stat)
		}
	}
}

type fakeTerminal struct {
	io.Writer
	fd uintptr
}

func (t fakeTerminal) Fd() uintptr { return t.fd }

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

	var t *termstatus.Terminal
	if runtime.GOOS == "windows" {
		t = termstatus.New(ctx, &fakeTerminal{color.Output, os.Stdout.Fd()})
	} else {
		t = termstatus.New(ctx, os.Stdout)
	}
	outCh := make(chan Status)

	var statusWg sync.WaitGroup
	statusWg.Add(1)
	go status(ctx, &statusWg, t, outCh)

	ch := make(chan *Command)

	var workersWg sync.WaitGroup
	for i := 0; i < opts.threads; i++ {
		workersWg.Add(1)
		go worker(&workersWg, ch, outCh)
	}

	args := pflag.Args()
	if len(args) == 0 {
		fmt.Fprintf(os.Stderr, "no command given\n")
		pflag.Usage()
		os.Exit(1)
	}

	cmdname := args[0]
	args = args[1:]

	checkForPlaceholder(cmdname, args)

	go parseInput(ch, cmdname, args)

	workersWg.Wait()
	close(outCh)

	statusWg.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	"log"
	"log/syslog"
	"net/http"
	"os"
	"vip/fetch"
	"vip/peer"
	"vip/store"
)

const (
	KeyFilePath  = "/etc/vip/application.key"
	CertFilePath = "/etc/vip/application.pem"
)

var (
	cache     *groupcache.Group
	peers     peer.CachePool
	storage   store.ImageStore
	authToken string

	verbose  *bool   = flag.Bool("verbose", false, "verbose logging")
	httpport *string = flag.String("httpport", "8080", "target port")
	secure   bool    = false
)

func listenHttp() {
	log.Printf("Listening on port :%s\n", *httpport)

	port := fmt.Sprintf(":%s", *httpport)

	if secure {
		log.Println("Serving via TSL")
		if err := http.ListenAndServeTLS(port, CertFilePath, KeyFilePath, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	} else {
		if err := http.ListenAndServe(port, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	}
}

func getRegion() aws.Region {
	region := os.Getenv("AWS_REGION")
	aws_region, ok := aws.Regions[region]
	if ok {
		return aws_region
	} else {
		log.Printf(
			"\"%s\" is not a valid AWS_REGION parameter provided, defaulting to us-east-1",
			region)
		return aws.USEast
	}
}

func init() {
	flag.Parse()
	var err error
	hasKey := true
	hasCert := true
	_, err = os.Stat(KeyFilePath)
	if err != nil {
		log.Printf("No key found at %s\n", KeyFilePath)
		hasKey = false
	}

	_, err = os.Stat(CertFilePath)
	if err != nil {
		log.Printf("No certificate found at %s\n", CertFilePath)
		hasCert = false
	}

	secure = hasCert && hasKey

	r := mux.NewRouter()

	authToken = os.Getenv("AUTH_TOKEN")
	if authToken == "" {
		log.Println("No AUTH_TOKEN parameter provided, uploads are insecure")
	}

	r.Handle("/upload/{bucket_id}", verifyAuth(handleUpload))
	r.HandleFunc("/{bucket_id}/{image_id}", handleImageRequest)
	r.HandleFunc("/ping", handlePing)
	http.Handle("/", r)
}

func main() {
	awsAuth, err := aws.EnvAuth()
	if err != nil {
		log.Fatalf(err.Error())
	}

	s3conn := s3.New(awsAuth, getRegion())
	storage = store.NewS3Store(s3conn)

	peers = peer.DebugPool()

	peers.SetContext(func(r *http.Request) groupcache.Context {
		return fetch.RequestContext(r)
	})

	cache = groupcache.NewGroup("ImageProxyCache", 64<<20, groupcache.GetterFunc(
		func(c groupcache.Context, key string, dest groupcache.Sink) error {
			log.Printf("Cache MISS for key -> %s", key)
			// Get image data from S3
			b, err := fetch.ImageData(storage, c)
			if err != nil {
				return err
			}

			return dest.SetBytes(b)
		}))

	if !*verbose {
		logwriter, err := syslog.Dial("udp", "app_syslog:514", syslog.LOG_NOTICE, "vip")
		if err != nil {
			log.Println(err.Error())
			log.Println("using default logger")
		} else {
			log.SetOutput(logwriter)
		}
	}

	go peers.Listen()
	go listenHttp()

	log.Println("Cache listening on port :" + peers.Port())
	s := &http.Server{
		Addr:    ":" + peers.Port(),
		Handler: peers,
	}
	s.ListenAndServe()
}
<commit_msg>Set GOMAXPROCS for imaging speedup<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
	"log"
	"log/syslog"
	"net/http"
	"os"
	"runtime"
	"vip/fetch"
	"vip/peer"
	"vip/store"
)

const (
	KeyFilePath  = "/etc/vip/application.key"
	CertFilePath = "/etc/vip/application.pem"
)

var (
	cache     *groupcache.Group
	peers     peer.CachePool
	storage   store.ImageStore
	authToken string

	verbose  *bool   = flag.Bool("verbose", false, "verbose logging")
	httpport *string = flag.String("httpport", "8080", "target port")
	secure   bool    = false
)

func listenHttp() {
	log.Printf("Listening on port :%s\n", *httpport)

	port := fmt.Sprintf(":%s", *httpport)

	if secure {
		log.Println("Serving via TSL")
		if err := http.ListenAndServeTLS(port, CertFilePath, KeyFilePath, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	} else {
		if err := http.ListenAndServe(port, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	}
}

func getRegion() aws.Region {
	region := os.Getenv("AWS_REGION")
	aws_region, ok := aws.Regions[region]
	if ok {
		return aws_region
	} else {
		log.Printf(
			"\"%s\" is not a valid AWS_REGION parameter provided, defaulting to us-east-1",
			region)
		return aws.USEast
	}
}

func init() {
	flag.Parse()
	var err error
	hasKey := true
	hasCert := true
	_, err = os.Stat(KeyFilePath)
	if err != nil {
		log.Printf("No key found at %s\n", KeyFilePath)
		hasKey = false
	}

	_, err = os.Stat(CertFilePath)
	if err != nil {
		log.Printf("No certificate found at %s\n", CertFilePath)
		hasCert = false
	}

	secure = hasCert && hasKey

	r := mux.NewRouter()

	authToken = os.Getenv("AUTH_TOKEN")
	if authToken == "" {
		log.Println("No AUTH_TOKEN parameter provided, uploads are insecure")
	}

	r.Handle("/upload/{bucket_id}", verifyAuth(handleUpload))
	r.HandleFunc("/{bucket_id}/{image_id}", handleImageRequest)
	r.HandleFunc("/ping", handlePing)
	http.Handle("/", r)
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	awsAuth, err := aws.EnvAuth()
	if err != nil {
		log.Fatalf(err.Error())
	}

	s3conn := s3.New(awsAuth, getRegion())
	storage = store.NewS3Store(s3conn)

	peers = peer.DebugPool()

	peers.SetContext(func(r *http.Request) groupcache.Context {
		return fetch.RequestContext(r)
	})

	cache = groupcache.NewGroup("ImageProxyCache", 64<<20, groupcache.GetterFunc(
		func(c groupcache.Context, key string, dest groupcache.Sink) error {
			log.Printf("Cache MISS for key -> %s", key)
			// Get image data from S3
			b, err := fetch.ImageData(storage, c)
			if err != nil {
				return err
			}

			return dest.SetBytes(b)
		}))

	if !*verbose {
		logwriter, err := syslog.Dial("udp", "app_syslog:514", syslog.LOG_NOTICE, "vip")
		if err != nil {
			log.Println(err.Error())
			log.Println("using default logger")
		} else {
			log.SetOutput(logwriter)
		}
	}

	go peers.Listen()
	go listenHttp()

	log.Println("Cache listening on port :" + peers.Port())
	s := &http.Server{
		Addr:    ":" + peers.Port(),
		Handler: peers,
	}
	s.ListenAndServe()
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/kkdai/line-bot-sdk-go/linebot"
)

var ImgSrv string = "https://img-cache-server.herokuapp.com/"
var bot *linebot.Client

//PetDB :
var PetDB *Pets

func main() {
	var err error
	PetDB = NewPets()
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func getSecureImageAddress(oriAdd string) string {
	eURL := url.QueryEscape(oriAdd)
	imgGetUrl := fmt.Sprintf("%surl?%s", ImgSrv, eURL)
	log.Println("eURL:", eURL, " url:", imgGetUrl, " ImgApi:", ImgSrv)

	response, err := http.Get(imgGetUrl)
	if err != nil {
		log.Println("Error while downloading:", err)
		return ""
	}
	defer response.Body.Close()

	if response.StatusCode != 200 {
		return ""
	}

	totalBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println("Error while parsing:", err)
		return ""
	}
	log.Println("Got data:", string(totalBody))
	return fmt.Sprintf("%simgs?%s.jpg", ImgSrv, string(totalBody))

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, event := range events {
		switch event.Type {
		case linebot.EventTypeMessage:
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				var pet *Pet
				var sendr *linebot.Sender
				log.Println(message.Text)
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText, "狗") || strings.Contains(inText, "dog") {
					pet = PetDB.GetNextDog()
					sendr = linebot.NewSender("Brown", "https://stickershop.line-scdn.net/stickershop/v1/sticker/52002749/iPhone/sticker_key@2x.png")

				} else if strings.Contains(inText, "貓") || strings.Contains(inText, "cat") {
					pet = PetDB.GetNextCat()
					sendr = linebot.NewSender("Sally", "https://stickershop.line-scdn.net/stickershop/v1/sticker/52002736/iPhone/sticker_key@2x.png")
				}

				if pet == nil {
					pet = PetDB.GetNextPet()
				}

				out := pet.DisplayPet()
				if len(pet.ImageName) > 0 {
					if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out).WithSender(sendr), linebot.NewImageMessage(pet.ImageName, pet.ImageName)).Do(); err != nil {
						log.Print(err)
					}
				} else if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<commit_msg>add lost case<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/kkdai/line-bot-sdk-go/linebot"
)

var ImgSrv string = "https://img-cache-server.herokuapp.com/"
var bot *linebot.Client

//PetDB :
var PetDB *Pets

func main() {
	var err error
	PetDB = NewPets()
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func getSecureImageAddress(oriAdd string) string {
	eURL := url.QueryEscape(oriAdd)
	imgGetUrl := fmt.Sprintf("%surl?%s", ImgSrv, eURL)
	log.Println("eURL:", eURL, " url:", imgGetUrl, " ImgApi:", ImgSrv)

	response, err := http.Get(imgGetUrl)
	if err != nil {
		log.Println("Error while downloading:", err)
		return ""
	}
	defer response.Body.Close()

	if response.StatusCode != 200 {
		return ""
	}

	totalBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println("Error while parsing:", err)
		return ""
	}
	log.Println("Got data:", string(totalBody))
	return fmt.Sprintf("%simgs?%s.jpg", ImgSrv, string(totalBody))

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, event := range events {
		switch event.Type {
		case linebot.EventTypeMessage:
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				var pet *Pet
				var sendr *linebot.Sender
				log.Println(message.Text)
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText, "狗") || strings.Contains(inText, "dog") {
					pet = PetDB.GetNextDog()
					sendr = linebot.NewSender("Brown", "https://stickershop.line-scdn.net/stickershop/v1/sticker/52002749/iPhone/sticker_key@2x.png")

				} else if strings.Contains(inText, "貓") || strings.Contains(inText, "cat") {
					pet = PetDB.GetNextCat()
					sendr = linebot.NewSender("Sally", "https://stickershop.line-scdn.net/stickershop/v1/sticker/52002736/iPhone/sticker_key@2x.png")
				}

				if pet == nil {
					pet = PetDB.GetNextPet()
				}

				out := pet.DisplayPet()
				if len(pet.ImageName) > 0 {
					if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out).WithSender(sendr), linebot.NewImageMessage(pet.ImageName, pet.ImageName).WithSender(sendr)).Do(); err != nil {
						log.Print(err)
					}
				} else if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out).WithSender(sendr)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"flag"
	"github.com/ajstarks/svgo"
	"io"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
)

// Chart is the simplest element only make up by label and value.
type Chart struct {
	Label string
	Value int
}

// Charts is slice of Chart
type Charts []Chart

// Sum of Charts,
func (c Charts) Sum() (s int) {
	for _, col := range c {
		s += col.Value
	}
	return
}

// Percentage of Charts,
func (c Charts) Percentage(label string) float64 {
	var numerator int
	for _, col := range c {
		if strings.Compare(col.Label, label) == 0 {
			numerator = col.Value
			break
		}
	}
	return float64(numerator) / float64(c.Sum())
}

// readCSV read from filename input by cmd flag, convert CSV into Charts struct and error if any file operand error happen.
func readCSV(filename string) (c Charts, err error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	r := csv.NewReader(file)
	records, err := r.ReadAll()
	if err != nil {
		return nil, err
	}
	for _, item := range records {
		if v, err := strconv.Atoi(item[1]); err == nil {
			col := Chart{item[0], v}
			c = append(c, col)
		}
	}
	return
}

func Draw(c Charts, width, height int, w io.Writer) (err error) {
	var angle float64
	canvas := svg.New(w)
	r := width * 3 / 15
	canvas.Start(width, height)
	canvas.Circle(width/2, height/2, r, "fill:none;stroke:red")
	for _, col := range c {
		half := float64(360)*c.Percentage(col.Label)/2 + angle
		angle += float64(360) * c.Percentage(col.Label)
		radius := angleToRadius(angle)
		canvas.Line(width/2, height/2, (width/2)+(int(math.Sin(radius)*float64(r))), (height/2)-(int(math.Cos(radius)*float64(r))), "stroke:red")
		canvas.Text((width/2)+(int(math.Sin(angleToRadius(half))*float64(r+50))), (height/2)-(int(math.Cos(angleToRadius(half))*float64(r+50))), col.Label)
	}
	canvas.End()
	return
}

func angleToRadius(angle float64) (radius float64) {
	radius = math.Pi * angle / 180
	return
}

func main() {
	var csvFile string
	var chartFile string
	var width, height int
	flag.StringVar(&csvFile, "csv", "input.csv", "CSV filename")
	flag.StringVar(&chartFile, "output", "output.svg", "OUTPUT filename")
	flag.IntVar(&width, "width", 1000, "OUTPUT file width")
	flag.IntVar(&height, "height", 800, "OUTPUT file height")
	flag.Parse()
	c, err := readCSV(csvFile)
	if err != nil {
		log.Fatal("Read csv file with some problem!")
	}
	out, err := os.Create(chartFile)
	if err != nil {
		log.Fatal("Create file with some problem!")
	}
	if err = Draw(c, width, height, out); err != nil {
		log.Fatal("Write canvas file with some problem!")
	}
}
<commit_msg>Update: replace draw method from line to SVG Path<commit_after>package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"github.com/ajstarks/svgo"
	"io"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
)

// Chart is the simplest element only make up by label and value.
type Chart struct {
	Label string
	Value int
}

// Charts is slice of Chart
type Charts []Chart

// Sum of Charts,
func (c Charts) Sum() (s int) {
	for _, col := range c {
		s += col.Value
	}
	return
}

// Percentage of Charts,
func (c Charts) Percentage(label string) float64 {
	var numerator int
	for _, col := range c {
		if strings.Compare(col.Label, label) == 0 {
			numerator = col.Value
			break
		}
	}
	return float64(numerator) / float64(c.Sum())
}

// readCSV read from filename input by cmd flag, convert CSV into Charts struct and error if any file operand error happen.
func readCSV(filename string) (c Charts, err error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	r := csv.NewReader(file)
	records, err := r.ReadAll()
	if err != nil {
		return nil, err
	}
	for _, item := range records {
		if v, err := strconv.Atoi(item[1]); err == nil {
			col := Chart{item[0], v}
			c = append(c, col)
		}
	}
	return
}

func Draw(c Charts, width, height int, w io.Writer) (err error) {
	var angle float64
	canvas := svg.New(w)
	color := []string{"red", "blue", "black", "green"}
	r := width * 3 / 15
	canvas.Start(width, height)
	canvas.Circle(width/2, height/2, r, "fill:none;stroke:red")
	for i, col := range c {
		half := float64(360)*c.Percentage(col.Label)/2 + angle
		start := angleToRadius(angle)
		angle += float64(360) * c.Percentage(col.Label)
		end := angleToRadius(angle)
		canvas.Path(fmt.Sprintf("M%d,%d L%d,%d A%d,%d 0 0,1 %d,%d L%d,%d", (width/2), (height/2), (width/2)+(int(math.Sin(start)*float64(r))), (height/2)-(int(math.Cos(start)*float64(r))), r, r, (width/2)+(int(math.Sin(end)*float64(r))), (height/2)-(int(math.Cos(end)*float64(r))), (width/2), (height/2)),
			fmt.Sprintf("fill:%s;stroke:%s", color[i%4], color[i%4]))
		/*
			canvas.Arc((width/2)+(int(math.Sin(start)*float64(r))), (height/2)-(int(math.Cos(start)*float64(r))), r, r, 0, (end-start) >= 180, true, (width/2)+(int(math.Sin(end)*float64(r))), (height/2)-(int(math.Cos(end)*float64(r))), fmt.Sprintf("fill:%s", color[i%4]))
			canvas.Line(width/2, height/2, (width/2)+(int(math.Sin(end)*float64(r))), (height/2)-(int(math.Cos(end)*float64(r))), "stroke:red")
		*/
		/*
			canvas.Def()
			canvas.Line(width/2, height/2, (width/2)+(int(math.Sin(start)*float64(r))), (height/2)-(int(math.Cos(start)*float64(r))), "stroke:red")
			canvas.Line(width/2, height/2, (width/2)+(int(math.Sin(end)*float64(r))), (height/2)-(int(math.Cos(end)*float64(r))), "stroke:red")
			canvas.Arc((width/2)+(int(math.Sin(start)*float64(r))), (height/2)-(int(math.Cos(start)*float64(r))), width/2, height/2, r, false, false, (width/2)+(int(math.Sin(end)*float64(r))), (height/2)-(int(math.Cos(end)*float64(r))), fmt.Sprintf("fill:%s", color[i]))
			canvas.DefEnd()
		*/
		fmt.Println("Printing line", i, start, end)
		canvas.Text((width/2)+(int(math.Sin(angleToRadius(half))*float64(r+50))), (height/2)-(int(math.Cos(angleToRadius(half))*float64(r+50))), col.Label)
	}
	fmt.Println(color)
	canvas.End()
	return
}

func angleToRadius(angle float64) (radius float64) {
	radius = math.Pi * angle / 180
	return
}

func main() {
	var csvFile string
	var chartFile string
	var width, height int
	flag.StringVar(&csvFile, "csv", "input.csv", "CSV filename")
	flag.StringVar(&chartFile, "output", "output.svg", "OUTPUT filename")
	flag.IntVar(&width, "width", 1000, "OUTPUT file width")
	flag.IntVar(&height, "height", 800, "OUTPUT file height")
	flag.Parse()
	c, err := readCSV(csvFile)
	if err != nil {
		log.Fatal("Read csv file with some problem!")
	}
	out, err := os.Create(chartFile)
	if err != nil {
		log.Fatal("Create file with some problem!")
	}
	if err = Draw(c, width, height, out); err != nil {
		log.Fatal("Write canvas file with some problem!")
	}
}
<|endoftext|>


<commit_before>package mark

import "strings"

// Just for test right now
func Render(text string) string {
	// Preproessing
	// 1. Replace all tabs with 4-spaces
	text = strings.Replace(text, "\t", "    ", -1)
	// TODO: Use/ot remove name option
	t := &Tree{lex: lex(text, text)}
	t.parse()
	// PostProcessing
	// 1. HTML escaping(<, >, ...)
	t.render()
	return t.output
}
<commit_msg>fix(mark): t.links<commit_after>package mark

import "strings"

// Just for test right now
func Render(text string) string {
	// Preproessing
	// 1. Replace all tabs with 4-spaces
	text = strings.Replace(text, "\t", "    ", -1)
	// TODO: Use/ot remove name option
	t := &Tree{lex: lex(text, text), links: map[string]*DefLinkNode{}}
	t.parse()
	// PostProcessing
	// 1. HTML escaping(<, >, ...)
	t.render()
	return t.output
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, web")
}

func main() {
	http.HandleFunc("/hello", helloHandler)
	err := http.ListenAndServe("127.0.0.1:8080", nil)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>update listen check.<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, web")
}

func main() {
	http.HandleFunc("/hello", helloHandler)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package parser

import "testing"

var demuxer DASHDemuxer

func TestOpen(t *testing.T) {
  demuxer := new(DASHDemuxer)
  demuxer.Open("path/to/base/manifest.mpd")

  urlCases := []struct {
    got, want string
  }{
    {demuxer.manifestURL, "http://path/to/base/manifest.mpd"},
    {demuxer.baseURL,     "http://path/to/base"},
  }

  for _, c :=  range urlCases {
    if c.want != c.got {
      t.Errorf("bad manfest url. want %q, got %q", c.want, c.got)
    }
  }
}
<commit_msg>added some tests for segment base and segment template<commit_after>package parser

import "testing"

const segmentBaseManifest string = "dash-vod-aka-test.canal-bis.com/test/1fps/index.mpd"
const segmentTemplateManifest string = "www.digitalprimates.net/dash/streams/mp4-live-template/mp4-live-mpd-AV-BS.mpd"

var demuxer DASHDemuxer

func TestOpen(t *testing.T) {
  demuxer := new(DASHDemuxer)
  demuxer.Open("path/to/base/manifest.mpd")

  urlCases := []struct {
    got, want string
  }{
    {demuxer.manifestURL, "http://path/to/base/manifest.mpd"},
    {demuxer.baseURL,     "http://path/to/base"},
  }

  for _, c :=  range urlCases {
    if c.want != c.got {
      t.Errorf("bad manfest url. want %q, got %q", c.want, c.got)
    }
  }
}

func TestSegemenBaseGetTracks(t *testing.T) {
  demuxer := new(DASHDemuxer)
  demuxer.Open(segmentBaseManifest)
  var tracks []*Track

  err := demuxer.GetTracks(&tracks)

  if err != nil {
    t.Errorf("got error in GetTracks %q", err)
  }

}

func TestSegemenTemplateGetTracks(t *testing.T) {
  demuxer := new(DASHDemuxer)
  demuxer.Open(segmentTemplateManifest)
  var tracks []*Track

  err := demuxer.GetTracks(&tracks)

  if err != nil {
    t.Errorf("got error in GetTracks %q", err)
  }
}<|endoftext|>


<commit_before>// testrestcliant
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/jmcvetta/napping"
)

type Configuration struct {
	Interval    int
	LogStashUrl string
	LgLogin     string // logstash login
	LgPassword  string // logstash password
	NatsUrls    []string
}
type NatsNodeTopInfo struct {
	Varz  Varz
	Connz Connz
}
type Cluster struct {
	Addr         string
	Cluster_port int
}
type Varz struct {
	Server_id         string
	Host              string
	Addr              string
	Http_host         string
	Cluster           Cluster
	Start             string
	Now               time.Time
	Uptime            string
	Mem               float32
	Cpu               float32
	Connections       int
	Total_connections int
	Routes            int
	Remotes           int
	In_msgs           int
	Out_msgs          int
	In_bytes          int
	Out_bytes         int
	In_msgs_sec       int
	Out_msgs_sec      int
	In_bytes_sec      int
	Out_bytes_sec     int
	Slow_consumers    int
	Subscriptions     int
}
type Connection struct {
	Сid           int
	Ip            string
	Port          int
	Start         string
	Last_activity string
	Uptime        string
	Pending_bytes int
	In_msgs       int
	Out_msgs      int
	In_bytes      int
	Out_bytes     int
}
type Connz struct {
	Now             string
	Num_connections int
	Total           int
	Offset          int
	Limit           int
	Connections     []Connection
}
type PrevInOutValues struct {
	In_msgs   int
	Out_msgs  int
	In_bytes  int
	Out_bytes int

	Now time.Time
}
type InOutPerSec struct {
	In_msgs_sec   int
	Out_msgs_sec  int
	In_bytes_sec  int
	Out_bytes_sec int
}

var prev_vals map[string]*PrevInOutValues = make(map[string]*PrevInOutValues)

func main() {

	config := Configuration{}

	var configPath string

	flag.StringVar(&configPath, "c", "path to config file", "")
	flag.StringVar(&configPath, "string", "path to config file", "")

	setFlag(flag.CommandLine)
	flag.Parse()

	config = readConfig(configPath)

	httpClient := http.Client{}
	httpClient.Timeout = time.Duration(300) * time.Millisecond
	sessionToNats := napping.Session{Client: &httpClient}
	sessionToLogstash := napping.Session{Userinfo: url.UserPassword(config.LgLogin, config.LgPassword)}

	e := HttpError{}

	for true {
		for _, url := range config.NatsUrls {

			varz := Varz{}
			connzs := Connz{}
			natsNodeTopInfo := NatsNodeTopInfo{}

			varzUrl := url + "/varz"
			connzUrl := url + "/connz"

			varzResponse, err := sessionToNats.Get(varzUrl, nil, &varz, &e)

			if err != nil {
				fmt.Println(err)
				continue
			}

			connzResponse, err := sessionToNats.Get(connzUrl, nil, &connzs, &e)

			if err != nil {
				fmt.Println(err)
				continue
			}

			if varzResponse.Status() == 200 && connzResponse.Status() == 200 {

				perSecValues := getPerSecValues(url, varz)

				varz.In_bytes_sec = perSecValues.In_bytes_sec
				varz.Out_bytes_sec = perSecValues.Out_bytes_sec
				varz.In_msgs_sec = perSecValues.In_msgs_sec
				varz.Out_msgs_sec = perSecValues.Out_msgs_sec

				varz.Mem = varz.Mem / 1024 / 1024 // to MB
				natsNodeTopInfo.Varz = varz
				natsNodeTopInfo.Connz = connzs

				fmt.Println(natsNodeTopInfo)
				fmt.Printf("Sending to logstash -> ")
				logstashResponse, err := sessionToLogstash.Post(config.LogStashUrl, natsNodeTopInfo, nil, &e)

				if err != nil {
					fmt.Println(err)
				}
				if logstashResponse.Status() == 200 {
					fmt.Println("Success\n")
				}
			}
		}
		time.Sleep(time.Duration(config.Interval) * time.Millisecond)
	}
}
func getPerSecValues(url string, varz Varz) InOutPerSec {
	inOutPerSec := InOutPerSec{}

	if prev_vals[url] == nil {

		prev_vals[url] = &PrevInOutValues{}

		prev_vals[url].In_bytes = varz.In_bytes
		prev_vals[url].Out_bytes = varz.Out_bytes
		prev_vals[url].In_msgs = varz.In_msgs
		prev_vals[url].Out_msgs = varz.Out_msgs
		prev_vals[url].Now = varz.Now

		return InOutPerSec{}
	}

	// calculate
	in_bytes_delta := varz.In_bytes - prev_vals[url].In_bytes
	out_bytes_delta := varz.Out_bytes - prev_vals[url].Out_bytes

	in_msgs_delta := varz.In_msgs - prev_vals[url].In_msgs
	out_msgs_delta := varz.Out_msgs - prev_vals[url].Out_msgs

	sec := varz.Now.Second() - prev_vals[url].Now.Second()

	inOutPerSec.In_bytes_sec = in_bytes_delta / sec
	inOutPerSec.Out_bytes_sec = out_bytes_delta / sec
	inOutPerSec.In_msgs_sec = in_msgs_delta / sec
	inOutPerSec.Out_msgs_sec = out_msgs_delta / sec

	// save prev.values
	prev_vals[url].In_bytes = varz.In_bytes
	prev_vals[url].Out_bytes = varz.Out_bytes
	prev_vals[url].In_msgs = varz.In_msgs
	prev_vals[url].Out_msgs = varz.Out_msgs
	prev_vals[url].Now = varz.Now

	// return result
	return inOutPerSec
}
func readConfig(filepath string) Configuration {

	file, _ := os.Open(filepath)
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err := decoder.Decode(&configuration)

	if err != nil {
		fmt.Println("error:", err)
	}

	return configuration
}

type HttpError struct {
	Message string
	Errors  []struct {
		Resource string
		Field    string
		Code     string
	}
}

func setFlag(flag *flag.FlagSet) {
	flag.Usage = func() {
		showHelp()
	}
}

func showHelp() {
	fmt.Println(`
Usage: CLI Template [OPTIONS]
Options:
    -c, --string     Path to config file.
    -h, --help       prints this help info.
    `)
}
<commit_msg><commit_after>// testrestcliant
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
	"log"

	"github.com/jmcvetta/napping"
	"bytes"
)

type Configuration struct {
	LogFilePath string
	Interval    int
	DebugMode   bool
	TraceMode   bool
	LogStashUrl string
	LgLogin     string // logstash login
	LgPassword  string // logstash password
	NatsUrls    []string
}
type NatsNodeTopInfo struct {
	Varz  Varz
	Connz Connz
}
type Cluster struct {
	Addr         string
	Cluster_port int
}
type Varz struct {
	Server_id         string
	Host              string
	Addr              string
	Http_host         string
	Cluster           Cluster
	Start             string
	Now               time.Time
	Uptime            string
	Mem               float32
	Cpu               float32
	Connections       int
	Total_connections int
	Routes            int
	Remotes           int
	In_msgs           int
	Out_msgs          int
	In_bytes          int
	Out_bytes         int
	In_msgs_sec       int
	Out_msgs_sec      int
	In_bytes_sec      int
	Out_bytes_sec     int
	Slow_consumers    int
	Subscriptions     int
}
type Connection struct {
	Сid           int
	Ip            string
	Port          int
	Start         string
	Last_activity string
	Uptime        string
	Pending_bytes int
	In_msgs       int
	Out_msgs      int
	In_bytes      int
	Out_bytes     int
}
type Connz struct {
	Now             string
	Num_connections int
	Total           int
	Offset          int
	Limit           int
	Connections     []Connection
}
type PrevInOutValues struct {
	In_msgs   int
	Out_msgs  int
	In_bytes  int
	Out_bytes int

	Now       time.Time
}
type InOutPerSec struct {
	In_msgs_sec   int
	Out_msgs_sec  int
	In_bytes_sec  int
	Out_bytes_sec int
}

var prev_vals map[string]*PrevInOutValues = make(map[string]*PrevInOutValues)

func main() {

	config := Configuration{}

	configPathCL := flag.String("c", "", "path to config file")
	logFilePathCL := flag.String("l", "", "path to log file")
	isDebugCL := flag.Bool("d", false, "DEBUG mode")
	isTraceCL := flag.Bool("t", false, "TRACE mode")

	setFlag(flag.CommandLine)
	flag.Parse()

	config = readConfig(*configPathCL)

	isDebug := config.DebugMode
	isTrace := config.DebugMode

	if *isDebugCL {
		isDebug = *isDebugCL
	}

	if *isTraceCL {
		isTrace = *isTraceCL
	}

	setLogOutput(config, *logFilePathCL)

	httpClient := http.Client{}
	httpClient.Timeout = time.Duration(300) * time.Millisecond
	sessionToNats := napping.Session{Client: &httpClient}
	sessionToLogstash := napping.Session{Userinfo: url.UserPassword(config.LgLogin, config.LgPassword)}

	e := HttpError{}

	log.Printf("NATS-ELK forwarder started\n")
	log.Printf("Interval of requests: %d ms\n", config.Interval)

	for true {
		for _, url := range config.NatsUrls {

			varz := Varz{}
			connzs := Connz{}
			natsNodeTopInfo := NatsNodeTopInfo{}

			varzUrl := url + "/varz"
			connzUrl := url + "/connz"

			varzResponse, err := sessionToNats.Get(varzUrl, nil, &varz, &e)

			if err != nil && isDebug {
				log.Printf("%v\n", err)
				continue
			}

			connzResponse, err := sessionToNats.Get(connzUrl, nil, &connzs, &e)

			if err != nil && isDebug {
				log.Printf("%v\n", err)
				continue
			}

			if varzResponse.Status() == 200 && connzResponse.Status() == 200 {

				if isDebug {
					log.Printf("Get data from nats node (%v) - Success\n", url)
				}

				perSecValues := getPerSecValues(url, varz)

				varz.In_bytes_sec = perSecValues.In_bytes_sec
				varz.Out_bytes_sec = perSecValues.Out_bytes_sec
				varz.In_msgs_sec = perSecValues.In_msgs_sec
				varz.Out_msgs_sec = perSecValues.Out_msgs_sec

				varz.Mem = varz.Mem / 1024 / 1024 // to MB
				natsNodeTopInfo.Varz = varz
				natsNodeTopInfo.Connz = connzs

				if isTrace {
					printPrettyJson(natsNodeTopInfo)
				}

				logstashResponse, err := sessionToLogstash.Post(config.LogStashUrl, natsNodeTopInfo, nil, &e)

				if err != nil && isDebug {
					log.Printf("Sending to logstash -> Error: ")
					log.Printf("%v\n", err)
				}
				if logstashResponse.Status() == 200 && isDebug {
					log.Printf("Sending to logstash (%v): Success\n", config.LogStashUrl)
				}
			}
		}
		time.Sleep(time.Duration(config.Interval) * time.Millisecond)
	}
}
func getPerSecValues(url string, varz Varz) InOutPerSec {
	inOutPerSec := InOutPerSec{}

	if prev_vals[url] == nil {

		prev_vals[url] = &PrevInOutValues{}

		prev_vals[url].In_bytes = varz.In_bytes
		prev_vals[url].Out_bytes = varz.Out_bytes
		prev_vals[url].In_msgs = varz.In_msgs
		prev_vals[url].Out_msgs = varz.Out_msgs
		prev_vals[url].Now = varz.Now

		return InOutPerSec{}
	}

	// calculate
	in_bytes_delta := varz.In_bytes - prev_vals[url].In_bytes
	out_bytes_delta := varz.Out_bytes - prev_vals[url].Out_bytes

	in_msgs_delta := varz.In_msgs - prev_vals[url].In_msgs
	out_msgs_delta := varz.Out_msgs - prev_vals[url].Out_msgs

	sec := varz.Now.Second() - prev_vals[url].Now.Second()

	inOutPerSec.In_bytes_sec = in_bytes_delta / sec
	inOutPerSec.Out_bytes_sec = out_bytes_delta / sec
	inOutPerSec.In_msgs_sec = in_msgs_delta / sec
	inOutPerSec.Out_msgs_sec = out_msgs_delta / sec

	// save prev.values
	prev_vals[url].In_bytes = varz.In_bytes
	prev_vals[url].Out_bytes = varz.Out_bytes
	prev_vals[url].In_msgs = varz.In_msgs
	prev_vals[url].Out_msgs = varz.Out_msgs
	prev_vals[url].Now = varz.Now

	// return result
	return inOutPerSec
}
func readConfig(filepath string) Configuration {

	file, _ := os.Open(filepath)
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err := decoder.Decode(&configuration)

	if err != nil {
		log.Println("error:", err)
	}

	return configuration
}

type HttpError struct {
	Message string
	Errors  []struct {
		Resource string
		Field    string
		Code     string
	}
}

func setFlag(flag *flag.FlagSet) {
	flag.Usage = func() {
		showHelp()
	}
}
func showHelp() {
	fmt.Println(`
Usage: CLI Template [OPTIONS]
Options:
    -c, --config     Path to config file.
    -l, --log        Path to log file.
    -d, --debug      DEBUG mode.
    -t, --trace      TRACE mode.
    -h, --help       prints this help info.
    `)
}
func setLogOutput(config Configuration, logFilePathCL string) {

	if len(config.LogFilePath) > 0 || len(logFilePathCL) > 0 {

		logFilePath := ""

		if len(config.LogFilePath) > 0 {
			logFilePath = config.LogFilePath
		}
		if len(logFilePathCL) > 0 {
			logFilePath = logFilePathCL
		}

		file, err := os.OpenFile(logFilePath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)

		if err != nil {
			log.Fatalf("error opening file: %v", err)
		}

		log.SetOutput(file)
	}
}
func printPrettyJson(info NatsNodeTopInfo){
	var prettyJSON bytes.Buffer

	body, err := json.Marshal(info)

	if err != nil {
		log.Println(err)
		return
	}

	error := json.Indent(&prettyJSON, body, "", "\t")
	if error != nil {
		log.Println("JSON parse error: ", error)
		return
	}

	log.Println(string(prettyJSON.Bytes()))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	jsonpb "github.com/gogo/protobuf/jsonpb"
	ggproto "github.com/gogo/protobuf/proto"
	b58 "github.com/jbenet/go-base58"
	p2p_crypto "github.com/libp2p/go-libp2p-crypto"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	gopass "github.com/mediachain/gopass"
	homedir "github.com/mitchellh/go-homedir"
	sbox "golang.org/x/crypto/nacl/secretbox"
	scrypt "golang.org/x/crypto/scrypt"
	kp "gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"
)

func main() {
	log.SetFlags(0) // naked logs, it's interactive output

	var (
		home = kp.Flag("home", "mcid home directory").Short('d').Default("~/.mediachain/mcid").String()

		_ = kp.Command("id", "show your public identity; generates a new key pair if it doesn't already exist.") // idCmd declared but not used

		signCmd      = kp.Command("sign", "sign a manifest")
		signEntity   = signCmd.Arg("entity", "entity id").Required().String()
		signManifest = signCmd.Arg("manifest", "manifest json file").Required().File()

		verifyCmd      = kp.Command("verify", "verify a manifest")
		verifyManifest = verifyCmd.Arg("manifest", "manifest json file").Required().ExistingFile()
	)

	switch kp.Parse() {
	case "id":
		doId(*home)

	case "sign":
		doSign(*home, *signEntity, *signManifest)

	case "verify":
		doVerify(*home, *verifyManifest)
	}
}

type Identity struct {
	Public  PublicId  `json:"public"`
	Private PrivateId `json:"private"`
}

type PublicId struct {
	KeyId string `json:"keyId"` // public key multihash
	Key   []byte `json:"key"`   // marshalled public key
}

type PrivateId struct {
	Params ScryptParams `json:"params"` // key derivation parameters
	Salt   []byte       `json:"salt"`   // key derivation salt
	Nonce  []byte       `json:"nonce"`  // encryption nonce
	Data   []byte       `json:"data"`   // encrypted marshalled private key
}

type ScryptParams struct {
	N, R, P int
}

// default scrypt parameters (2009): N=16384, r=8, p=1
// still current; see https://github.com/Tarsnap/scrypt/issues/19
const (
	ScryptN = 16384
	ScryptR = 8
	ScryptP = 1
)

var (
	DecryptionError = errors.New("Private key decryption failed")
)

// ops
func doId(home string) {
	id, err := getIdentity(home, true) // generate id if it doesn't already exist
	if err != nil {
		log.Fatalf("Error retrieving identity: %s", err.Error())
	}

	json.NewEncoder(os.Stdout).Encode(id.Public)
}

func doSign(home string, entity string, mf *os.File) {
	var manifest pb.Manifest
	var manifestBody pb.ManifestBody

	err := jsonpb.Unmarshal(mf, &manifestBody)
	if err != nil {
		log.Fatalf("Error decoding manifest body: %s", err.Error())
	}

	id, err := getIdentity(home, false) // error if id doesn't exist
	if err != nil {
		log.Fatalf("Error retrieving identity: %s", err.Error())
	}

	privk, err := getPrivateKey(id.Private)
	if err != nil {
		log.Fatalf("Error decrypting private key: %s", err.Error())
	}

	manifest.Entity = entity
	manifest.KeyId = id.Public.KeyId
	manifest.Body = &manifestBody
	manifest.Timestamp = time.Now().Unix()

	bytes, err := ggproto.Marshal(&manifest)
	if err != nil {
		log.Fatalf("Error marshalling manifest: %s", err.Error())
	}

	sig, err := privk.Sign(bytes)
	if err != nil {
		log.Fatalf("Error signing manifest: %s", err.Error())
	}

	manifest.Signature = sig

	marshaler := jsonpb.Marshaler{}
	err = marshaler.Marshal(os.Stdout, &manifest)
	if err != nil {
		log.Fatalf("Error encoding manifest: %s", err.Error())
	}
	fmt.Println()
}

func doVerify(home string, manifest string) {
	log.Fatalf("IMPLEMENT ME: doVerify %s %s\n", home, manifest)
}

// identity
func getIdentity(home string, genid bool) (id Identity, err error) {
	home, err = homedir.Expand(home)
	if err != nil {
		return
	}

	idpath := path.Join(home, "identity.json")
	_, err = os.Stat(idpath)
	switch {
	case os.IsNotExist(err):
		if genid {
			return generateIdentity(home, idpath)
		}
		fallthrough
	case err != nil:
		return

	default:
		return loadIdentity(idpath)
	}
}

func generateIdentity(home, idpath string) (id Identity, err error) {
	err = os.MkdirAll(home, 0755)
	if err != nil {
		return
	}

	log.Printf("Generating identity key pair")
	privk, pubk, err := mc.GenerateECCKeyPair()
	if err != nil {
		return
	}

	pubbytes, err := pubk.Bytes()
	if err != nil {
		return
	}
	kid := b58.Encode(mc.Hash(pubbytes))

	id.Public.KeyId = kid
	id.Public.Key = pubbytes

	privbytes, err := privk.Bytes()
	if err != nil {
		return
	}

	err = encryptPrivateId(&id.Private, privbytes)
	if err != nil {
		return
	}

	bytes, err := json.Marshal(&id)
	if err != nil {
		return
	}

	err = ioutil.WriteFile(idpath, bytes, 0600)
	return
}

func loadIdentity(idpath string) (id Identity, err error) {
	bytes, err := ioutil.ReadFile(idpath)
	if err != nil {
		return
	}

	err = json.Unmarshal(bytes, &id)
	return
}

func getPrivateKey(priv PrivateId) (p2p_crypto.PrivKey, error) {
	bytes, err := decryptPrivateId(priv)
	if err != nil {
		return nil, err
	}

	return p2p_crypto.UnmarshalPrivateKey(bytes)
}

// private key encryption/decryption:
//  key derivation with scrypt
//  encryption with nacl secretbox
func encryptPrivateId(priv *PrivateId, data []byte) error {
	var (
		salt  [16]byte
		nonce [24]byte
		key   [32]byte
	)

	_, err := rand.Read(salt[:])
	if err != nil {
		return err
	}

	_, err = rand.Read(nonce[:])
	if err != nil {
		return err
	}

	pass, err := getEncryptionPass()
	if err != nil {
		return err
	}

	xkey, err := scrypt.Key(pass, salt[:], ScryptN, ScryptR, ScryptP, 32)
	if err != nil {
		return err
	}

	copy(key[:], xkey)

	ctext := sbox.Seal(nil, data, &nonce, &key)

	priv.Salt = salt[:]
	priv.Nonce = nonce[:]
	priv.Data = ctext[:]
	priv.Params.N = ScryptN
	priv.Params.R = ScryptR
	priv.Params.P = ScryptP

	return nil
}

func decryptPrivateId(priv PrivateId) ([]byte, error) {
	var (
		nonce [24]byte
		key   [32]byte
	)

	pass, err := getDecryptionPass()
	if err != nil {
		return nil, err
	}

	xkey, err := scrypt.Key(pass, priv.Salt, priv.Params.N, priv.Params.R, priv.Params.P, 32)
	if err != nil {
		return nil, err
	}

	copy(nonce[:], priv.Nonce)
	copy(key[:], xkey)

	bytes, ok := sbox.Open(nil, priv.Data, &nonce, &key)
	if !ok {
		return nil, DecryptionError
	}

	return bytes, nil
}

func getEncryptionPass() ([]byte, error) {
	for {
		fmt.Fprintf(os.Stderr, "Enter passphrase: ")
		pass1, err := gopass.GetPasswdX(false, os.Stderr)
		if err != nil {
			return nil, err
		}

		fmt.Fprintf(os.Stderr, "Re-enter passphrase: ")
		pass2, err := gopass.GetPasswdX(false, os.Stderr)
		if err != nil {
			return nil, err
		}

		if bytes.Equal(pass1, pass2) {
			return pass1, nil
		}

		fmt.Fprintln(os.Stderr, "Passphrases don't match")
	}
}

func getDecryptionPass() ([]byte, error) {
	fmt.Fprintf(os.Stderr, "Enter passphrase: ")
	return gopass.GetPasswdX(false, os.Stderr)
}
<commit_msg>mcid: ctext is already a slice<commit_after>package main

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	jsonpb "github.com/gogo/protobuf/jsonpb"
	ggproto "github.com/gogo/protobuf/proto"
	b58 "github.com/jbenet/go-base58"
	p2p_crypto "github.com/libp2p/go-libp2p-crypto"
	mc "github.com/mediachain/concat/mc"
	pb "github.com/mediachain/concat/proto"
	gopass "github.com/mediachain/gopass"
	homedir "github.com/mitchellh/go-homedir"
	sbox "golang.org/x/crypto/nacl/secretbox"
	scrypt "golang.org/x/crypto/scrypt"
	kp "gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"log"
	"os"
	"path"
	"time"
)

func main() {
	log.SetFlags(0) // naked logs, it's interactive output

	var (
		home = kp.Flag("home", "mcid home directory").Short('d').Default("~/.mediachain/mcid").String()

		_ = kp.Command("id", "show your public identity; generates a new key pair if it doesn't already exist.") // idCmd declared but not used

		signCmd      = kp.Command("sign", "sign a manifest")
		signEntity   = signCmd.Arg("entity", "entity id").Required().String()
		signManifest = signCmd.Arg("manifest", "manifest json file").Required().File()

		verifyCmd      = kp.Command("verify", "verify a manifest")
		verifyManifest = verifyCmd.Arg("manifest", "manifest json file").Required().ExistingFile()
	)

	switch kp.Parse() {
	case "id":
		doId(*home)

	case "sign":
		doSign(*home, *signEntity, *signManifest)

	case "verify":
		doVerify(*home, *verifyManifest)
	}
}

type Identity struct {
	Public  PublicId  `json:"public"`
	Private PrivateId `json:"private"`
}

type PublicId struct {
	KeyId string `json:"keyId"` // public key multihash
	Key   []byte `json:"key"`   // marshalled public key
}

type PrivateId struct {
	Params ScryptParams `json:"params"` // key derivation parameters
	Salt   []byte       `json:"salt"`   // key derivation salt
	Nonce  []byte       `json:"nonce"`  // encryption nonce
	Data   []byte       `json:"data"`   // encrypted marshalled private key
}

type ScryptParams struct {
	N, R, P int
}

// default scrypt parameters (2009): N=16384, r=8, p=1
// still current; see https://github.com/Tarsnap/scrypt/issues/19
const (
	ScryptN = 16384
	ScryptR = 8
	ScryptP = 1
)

var (
	DecryptionError = errors.New("Private key decryption failed")
)

// ops
func doId(home string) {
	id, err := getIdentity(home, true) // generate id if it doesn't already exist
	if err != nil {
		log.Fatalf("Error retrieving identity: %s", err.Error())
	}

	json.NewEncoder(os.Stdout).Encode(id.Public)
}

func doSign(home string, entity string, mf *os.File) {
	var manifest pb.Manifest
	var manifestBody pb.ManifestBody

	err := jsonpb.Unmarshal(mf, &manifestBody)
	if err != nil {
		log.Fatalf("Error decoding manifest body: %s", err.Error())
	}

	id, err := getIdentity(home, false) // error if id doesn't exist
	if err != nil {
		log.Fatalf("Error retrieving identity: %s", err.Error())
	}

	privk, err := getPrivateKey(id.Private)
	if err != nil {
		log.Fatalf("Error decrypting private key: %s", err.Error())
	}

	manifest.Entity = entity
	manifest.KeyId = id.Public.KeyId
	manifest.Body = &manifestBody
	manifest.Timestamp = time.Now().Unix()

	bytes, err := ggproto.Marshal(&manifest)
	if err != nil {
		log.Fatalf("Error marshalling manifest: %s", err.Error())
	}

	sig, err := privk.Sign(bytes)
	if err != nil {
		log.Fatalf("Error signing manifest: %s", err.Error())
	}

	manifest.Signature = sig

	marshaler := jsonpb.Marshaler{}
	err = marshaler.Marshal(os.Stdout, &manifest)
	if err != nil {
		log.Fatalf("Error encoding manifest: %s", err.Error())
	}
	fmt.Println()
}

func doVerify(home string, manifest string) {
	log.Fatalf("IMPLEMENT ME: doVerify %s %s\n", home, manifest)
}

// identity
func getIdentity(home string, genid bool) (id Identity, err error) {
	home, err = homedir.Expand(home)
	if err != nil {
		return
	}

	idpath := path.Join(home, "identity.json")
	_, err = os.Stat(idpath)
	switch {
	case os.IsNotExist(err):
		if genid {
			return generateIdentity(home, idpath)
		}
		fallthrough
	case err != nil:
		return

	default:
		return loadIdentity(idpath)
	}
}

func generateIdentity(home, idpath string) (id Identity, err error) {
	err = os.MkdirAll(home, 0755)
	if err != nil {
		return
	}

	log.Printf("Generating identity key pair")
	privk, pubk, err := mc.GenerateECCKeyPair()
	if err != nil {
		return
	}

	pubbytes, err := pubk.Bytes()
	if err != nil {
		return
	}
	kid := b58.Encode(mc.Hash(pubbytes))

	id.Public.KeyId = kid
	id.Public.Key = pubbytes

	privbytes, err := privk.Bytes()
	if err != nil {
		return
	}

	err = encryptPrivateId(&id.Private, privbytes)
	if err != nil {
		return
	}

	bytes, err := json.Marshal(&id)
	if err != nil {
		return
	}

	err = ioutil.WriteFile(idpath, bytes, 0600)
	return
}

func loadIdentity(idpath string) (id Identity, err error) {
	bytes, err := ioutil.ReadFile(idpath)
	if err != nil {
		return
	}

	err = json.Unmarshal(bytes, &id)
	return
}

func getPrivateKey(priv PrivateId) (p2p_crypto.PrivKey, error) {
	bytes, err := decryptPrivateId(priv)
	if err != nil {
		return nil, err
	}

	return p2p_crypto.UnmarshalPrivateKey(bytes)
}

// private key encryption/decryption:
//  key derivation with scrypt
//  encryption with nacl secretbox
func encryptPrivateId(priv *PrivateId, data []byte) error {
	var (
		salt  [16]byte
		nonce [24]byte
		key   [32]byte
	)

	_, err := rand.Read(salt[:])
	if err != nil {
		return err
	}

	_, err = rand.Read(nonce[:])
	if err != nil {
		return err
	}

	pass, err := getEncryptionPass()
	if err != nil {
		return err
	}

	xkey, err := scrypt.Key(pass, salt[:], ScryptN, ScryptR, ScryptP, 32)
	if err != nil {
		return err
	}

	copy(key[:], xkey)

	ctext := sbox.Seal(nil, data, &nonce, &key)

	priv.Salt = salt[:]
	priv.Nonce = nonce[:]
	priv.Data = ctext
	priv.Params.N = ScryptN
	priv.Params.R = ScryptR
	priv.Params.P = ScryptP

	return nil
}

func decryptPrivateId(priv PrivateId) ([]byte, error) {
	var (
		nonce [24]byte
		key   [32]byte
	)

	pass, err := getDecryptionPass()
	if err != nil {
		return nil, err
	}

	xkey, err := scrypt.Key(pass, priv.Salt, priv.Params.N, priv.Params.R, priv.Params.P, 32)
	if err != nil {
		return nil, err
	}

	copy(nonce[:], priv.Nonce)
	copy(key[:], xkey)

	bytes, ok := sbox.Open(nil, priv.Data, &nonce, &key)
	if !ok {
		return nil, DecryptionError
	}

	return bytes, nil
}

func getEncryptionPass() ([]byte, error) {
	for {
		fmt.Fprintf(os.Stderr, "Enter passphrase: ")
		pass1, err := gopass.GetPasswdX(false, os.Stderr)
		if err != nil {
			return nil, err
		}

		fmt.Fprintf(os.Stderr, "Re-enter passphrase: ")
		pass2, err := gopass.GetPasswdX(false, os.Stderr)
		if err != nil {
			return nil, err
		}

		if bytes.Equal(pass1, pass2) {
			return pass1, nil
		}

		fmt.Fprintln(os.Stderr, "Passphrases don't match")
	}
}

func getDecryptionPass() ([]byte, error) {
	fmt.Fprintf(os.Stderr, "Enter passphrase: ")
	return gopass.GetPasswdX(false, os.Stderr)
}
<|endoftext|>


<commit_before>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"log"
	"sync"
)

// App is a Neptulon application.
type App struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
	connMutex  sync.Mutex
}

// NewApp creates a Neptulon app. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewApp(cert, privKey, clientCACert []byte, laddr string, debug bool) (*App, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &App{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (a *App) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	a.middleware = append(a.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (a *App) Run() error {
	err := a.listener.Accept(handleConn(a), handleMsg(a), handleDisconn(a))
	if err != nil && a.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	a.errMutex.Lock()
	a.err = err
	a.errMutex.Unlock()

	return err
}

// Send sends a message throught the connection denoted by the connection ID.
func (a *App) Send(connID string, msg []byte) error {
	_, err := a.conns[connID].Write(msg)
	return err
}

// Stop stops a server instance.
func (a *App) Stop() error {
	err := a.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	a.connMutex.Lock()
	for _, conn := range a.conns {
		conn.Close()
	}
	a.connMutex.Unlock()

	a.errMutex.RLock()
	if a.err != nil {
		return a.err
	}
	a.errMutex.RUnlock()
	return err
}

func handleConn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		a.conns[conn.ID] = conn
		a.connMutex.Unlock()
	}
}

func handleMsg(a *App) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range a.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			_, err := conn.Write(res)
			if err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		delete(a.conns, conn.ID)
		a.connMutex.Unlock()
	}
}
<commit_msg>differentiate past internal errors on App.Close<commit_after>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"fmt"
	"log"
	"sync"
)

// App is a Neptulon application.
type App struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
	connMutex  sync.Mutex
}

// NewApp creates a Neptulon app. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewApp(cert, privKey, clientCACert []byte, laddr string, debug bool) (*App, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &App{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (a *App) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	a.middleware = append(a.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (a *App) Run() error {
	err := a.listener.Accept(handleConn(a), handleMsg(a), handleDisconn(a))
	if err != nil && a.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	a.errMutex.Lock()
	a.err = err
	a.errMutex.Unlock()

	return err
}

// Send sends a message throught the connection denoted by the connection ID.
func (a *App) Send(connID string, msg []byte) error {
	_, err := a.conns[connID].Write(msg)
	return err
}

// Stop stops a server instance.
func (a *App) Stop() error {
	err := a.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	a.connMutex.Lock()
	for _, conn := range a.conns {
		conn.Close()
	}
	a.connMutex.Unlock()

	a.errMutex.RLock()
	if a.err != nil {
		return fmt.Errorf("Past internal error: %v", a.err)
	}
	a.errMutex.RUnlock()
	return err
}

func handleConn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		a.conns[conn.ID] = conn
		a.connMutex.Unlock()
	}
}

func handleMsg(a *App) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range a.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			_, err := conn.Write(res)
			if err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		delete(a.conns, conn.ID)
		a.connMutex.Unlock()
	}
}
<|endoftext|>


<commit_before>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"log"
	"sync"
)

// App is a Neptulon application.
type App struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
	connMutex  sync.Mutex
}

// NewApp creates a Neptulon app. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewApp(cert, privKey, clientCACert []byte, laddr string, debug bool) (*App, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &App{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (a *App) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	a.middleware = append(a.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (a *App) Run() error {
	err := a.listener.Accept(handleConn(a), handleMsg(a), handleDisconn(a))
	if err != nil && a.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	a.errMutex.Lock()
	a.err = err
	a.errMutex.Unlock()

	return err
}

// Send sends a message throught the connection denoted by the connection ID.
func (a *App) Send(connID string, msg []byte) error {
	_, err := a.conns[connID].Write(msg)
	return err
}

// Stop stops a server instance.
func (a *App) Stop() error {
	err := a.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	a.connMutex.Lock()
	for _, conn := range a.conns {
		err := conn.Close()
		if err != nil {
			return err
		}
	}
	a.connMutex.Unlock()

	a.errMutex.RLock()
	if a.err != nil {
		return a.err
	}
	a.errMutex.RUnlock()
	return err
}

func handleConn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		a.conns[conn.ID] = conn
		a.connMutex.Unlock()
	}
}

func handleMsg(a *App) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range a.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			_, err := conn.Write(res)
			if err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		delete(a.conns, conn.ID)
		a.connMutex.Unlock()
	}
}
<commit_msg>don't handle conn close errors<commit_after>// Package neptulon is a socket framework with middleware support.
package neptulon

import (
	"log"
	"sync"
)

// App is a Neptulon application.
type App struct {
	debug      bool
	err        error
	errMutex   sync.RWMutex
	listener   *Listener
	middleware []func(conn *Conn, msg []byte) []byte
	conns      map[string]*Conn
	connMutex  sync.Mutex
}

// NewApp creates a Neptulon app. This is the default TLS constructor.
// Debug mode dumps raw TCP data to stderr (log.Println() default).
func NewApp(cert, privKey, clientCACert []byte, laddr string, debug bool) (*App, error) {
	l, err := Listen(cert, privKey, clientCACert, laddr, debug)
	if err != nil {
		return nil, err
	}

	return &App{
		debug:    debug,
		listener: l,
		conns:    make(map[string]*Conn),
	}, nil
}

// Middleware registers a new middleware to handle incoming messages.
func (a *App) Middleware(middleware func(conn *Conn, msg []byte) []byte) {
	a.middleware = append(a.middleware, middleware)
}

// Run starts accepting connections on the internal listener and handles connections with registered middleware.
// This function blocks and never returns, unless there was an error while accepting a new connection or the listner was closed.
func (a *App) Run() error {
	err := a.listener.Accept(handleConn(a), handleMsg(a), handleDisconn(a))
	if err != nil && a.debug {
		log.Fatalln("Listener returned an error while closing:", err)
	}

	a.errMutex.Lock()
	a.err = err
	a.errMutex.Unlock()

	return err
}

// Send sends a message throught the connection denoted by the connection ID.
func (a *App) Send(connID string, msg []byte) error {
	_, err := a.conns[connID].Write(msg)
	return err
}

// Stop stops a server instance.
func (a *App) Stop() error {
	err := a.listener.Close()

	// close all active connections discarding any read/writes that is going on currently
	// this is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server
	a.connMutex.Lock()
	for _, conn := range a.conns {
		conn.Close()
	}
	a.connMutex.Unlock()

	a.errMutex.RLock()
	if a.err != nil {
		return a.err
	}
	a.errMutex.RUnlock()
	return err
}

func handleConn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		a.conns[conn.ID] = conn
		a.connMutex.Unlock()
	}
}

func handleMsg(a *App) func(conn *Conn, msg []byte) {
	return func(conn *Conn, msg []byte) {
		for _, m := range a.middleware {
			res := m(conn, msg)
			if res == nil {
				continue
			}

			_, err := conn.Write(res)
			if err != nil {
				log.Fatalln("Errored while writing response to connection:", err)
			}

			break
		}
	}
}

func handleDisconn(a *App) func(conn *Conn) {
	return func(conn *Conn) {
		a.connMutex.Lock()
		delete(a.conns, conn.ID)
		a.connMutex.Unlock()
	}
}
<|endoftext|>


<commit_before>package memo

import (
	"sync"
)

type (
	Memo struct {
		f     Func
		mu    sync.Mutex //guards cache
		cache *entry
	}

	Func func() (interface{}, error)
)

type (
	entry struct {
		res   result
		ready chan struct{} // close when res is read
	}

	result struct {
		value interface{}
		err   error
	}
)

func New(f Func) *Memo {
	return &Memo{
		f: f,
	}
}

func (memo *Memo) Invalidate() {
	memo.mu.Lock()
	memo.cache = nil
	memo.mu.Unlock()
}

func (memo *Memo) Get() (value interface{}, err error) {
	memo.mu.Lock()
	if memo.cache == nil {
		memo.cache = &entry{ready: make(chan struct{})}
		memo.mu.Unlock()

		memo.cache.res.value, memo.cache.res.err = memo.f()

		close(memo.cache.ready)
	} else {
		memo.mu.Unlock()

		<-memo.cache.ready
	}
	return memo.cache.res.value, memo.cache.res.err
}
<commit_msg>Invalidate cache based on Memo's cache duration<commit_after>package memo

import (
	"sync"
	"time"
)

type (
	Memo struct {
		f     Func
		mu    sync.Mutex //guards cache
		cache *entry

		cacheDur  time.Duration
		lastCache time.Time
	}

	Func func() (interface{}, error)
)

type (
	entry struct {
		res   result
		ready chan struct{} // close when res is read
	}

	result struct {
		value interface{}
		err   error
	}
)

func New(f Func, cd time.Duration) *Memo {
	return &Memo{
		f:        f,
		cacheDur: cd,
	}
}

// Invalidate resets the cache to nil if the memo's given cache duration has
// elapsed, and returns true if the cache was actually invalidated.
func (memo *Memo) Invalidate() bool {
	defer memo.mu.Unlock()
	memo.mu.Lock()

	if memo.cache != nil && time.Now().Sub(memo.lastCache) > memo.cacheDur {
		memo.cache = nil
		memo.lastCache = time.Now()
		return true
	}
	return false
}

func (memo *Memo) Get() (value interface{}, err error) {
	memo.mu.Lock()
	if memo.cache == nil {
		memo.cache = &entry{ready: make(chan struct{})}
		memo.mu.Unlock()

		memo.cache.res.value, memo.cache.res.err = memo.f()

		close(memo.cache.ready)
	} else {
		memo.mu.Unlock()

		<-memo.cache.ready
	}
	return memo.cache.res.value, memo.cache.res.err
}
<|endoftext|>


<commit_before>// Package for dealing with SU2 meshes
// For mesh definition, see: http://adl-public.stanford.edu/docs/display/SUSQUARED/Mesh+files
// For similar Python code, see https://github.com/su2code/SU2/blob/master/SU2_PY/SU2/mesh/tools.py

package mesh

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
)

type PointID int
type ElementID int
type VTKType int

const (
	Quadrilateral VTKType = 9
)

type SU2 struct {
	Elements []*Element
	Points   []*Point
	Markers  []*Marker
	Dim      int
}

type Marker struct {
	Tag string
	//TypeID   VTKType
	Elements []Element
}

type Element struct {
	Id        ElementID
	Type      VTKType
	VertexIds []PointID
}

type Point struct {
	Id        PointID
	Location  []float64
	Neighbors map[PointID]*Point
}

// ReadFrom reads the SU2 mesh from an io.Reader creating the mesh
func (s *SU2) ReadFrom(r io.Reader) (n int64, err error) {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		str := scanner.Text()
		str = strings.TrimSpace(str)
		if len(str) == 0 {
			continue
		}
		switch {
		case strings.HasPrefix(str, "%"):
			// ignore because comment
		case strings.HasPrefix(str, "NDIME="):
			// Parse the number of dimensions
			strs := strings.Split(str, "=")
			if len(strs) != 2 {
				return n, errors.New("more than one equals sign in NDIME line")
			}
			str = strings.TrimSpace(strs[1])
			s.Dim, err = strconv.Atoi(str)
			if err != nil {
				return n, errors.New("error parsing NDIME: " + err.Error())
			}
		case strings.HasPrefix(str, "NELEM="):
			read, err := s.parseElements(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		case strings.HasPrefix(str, "NPOIN="):
			read, err := s.parsePoints(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		case strings.HasPrefix(str, "NMARK="):
			read, err := s.parseMarkers(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		}
	}
	err = s.initialize()
	if err != nil {
		return n, err
	}
	return n, nil
}

func (s *SU2) parseElements(scanner *bufio.Scanner, str string) (n int64, err error) {
	// first, get the number of elements
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NELEM line")
	}
	str = strings.TrimSpace(strs[1])
	nelem, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NELEM: " + err.Error())
	}
	elements := make([]*Element, nelem)
	for i := 0; i < nelem; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning element %d: " + scanner.Err().Error())
		}
		elem := &Element{}
		str := scanner.Text()
		str = strings.TrimSpace(str)
		strs := strings.Fields(str)
		if len(strs) == 0 {
			return n, fmt.Errorf("error scanning element %d: unexpected blank line", i)
		}
		if len(strs) < 2 {
			return n, fmt.Errorf("error scanning element %d: should be at least two numbers (typeID elemID)", i)
		}
		t, err := strconv.Atoi(strs[0])
		elem.Type = VTKType(t)
		if err != nil {
			return n, fmt.Errorf("error scanning element %d: cannot parse typeID: %v", i, err)
		}
		elem.Id = ElementID(i)

		// BUG: SU2 accepts meshes that don't follow the format. See issue #52.
		t, err = strconv.Atoi(strs[len(strs)-1])
		if err != nil {
			return n, fmt.Errorf("error scanning element %d: cannot parse nodeID: %v", i, err)
		}
		if elem.Id != ElementID(i) {
			return n, fmt.Errorf("error scanning element %d: bad nodeID: %v", i, err)
		}
		strs = strs[1 : len(strs)-1]
		elem.VertexIds = make([]PointID, len(strs))
		for j, str := range strs {
			t, err := strconv.Atoi(str)
			elem.VertexIds[j] = PointID(t)
			if err != nil {
				return n, fmt.Errorf("error scanning element %d: cannot parse node number: %v", i, err)
			}
		}
		elements[i] = elem
	}
	s.Elements = elements
	return n, nil
}

func (s *SU2) parsePoints(scanner *bufio.Scanner, str string) (n int64, err error) {
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NPOIN line")
	}
	str = strings.TrimSpace(strs[1])
	npoints, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NPOIN: " + err.Error())
	}
	points := make([]*Point, npoints)
	for i := 0; i < npoints; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning point %d: " + scanner.Err().Error())
		}
		str := scanner.Text()
		str = strings.TrimSpace(str)
		strs := strings.Fields(str)
		if len(strs) != s.Dim+1 {
			return n, fmt.Errorf("point %d has wrong number of entries (should have nDim + 1)", i)
		}
		point := &Point{}
		point.Location = make([]float64, s.Dim)
		for j := 0; j < s.Dim; j++ {
			point.Location[j], err = strconv.ParseFloat(strs[j], 64)
			if err != nil {
				return n, fmt.Errorf("error parsing location of point %d: %v", i, err)
			}
		}
		t, err := strconv.Atoi(strs[len(strs)-1])
		point.Id = PointID(t)
		if err != nil {
			return n, fmt.Errorf("error parsing index of point %d: %v", i, err)
		}
		if point.Id != PointID(i) {
			return n, fmt.Errorf("bad point id %d: %v", i, err)
		}
		points[i] = point
	}
	s.Points = points
	return n, nil
}

func (s *SU2) parseMarkers(scanner *bufio.Scanner, str string) (n int64, err error) {
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NMARK line")
	}
	str = strings.TrimSpace(strs[1])
	nMarkers, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NMARK: " + err.Error())
	}
	markers := make([]*Marker, nMarkers)
	for i := 0; i < nMarkers; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning marker %d: " + scanner.Err().Error())
		}
		str := scanner.Text()
		if !strings.HasPrefix(str, "MARKER_TAG") {
			return n, fmt.Errorf("no MARKER_TAG for marker %d", i)
		}
		strs := strings.Split(str, "=")
		if len(strs) != 2 {
			return n, fmt.Errorf("marker %d: MARKER_TAG doesn't have exactly one equals sign ", i)
		}
		marker := &Marker{}
		marker.Tag = strs[1]
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning MARKER_ELEMS %d: " + scanner.Err().Error())
		}
		str = scanner.Text()
		if !strings.HasPrefix(str, "MARKER_ELEMS") {
			return n, fmt.Errorf("MARKER_ELEMS prefix not found for marker %d", i)
		}
		strs = strings.Split(str, "=")
		if len(strs) != 2 {
			return n, fmt.Errorf("marker %d: MARKER_ELEMS doesn't have exactly one equals sign", i)
		}

		str = strings.TrimSpace(strs[1])
		nMarkerElems, err := strconv.Atoi(str)
		if err != nil {
			return n, fmt.Errorf("marker %d:  MARKER_ELEMS parsing error: ", err.Error())
		}
		marker.Elements = make([]Element, nMarkerElems)
		for j := 0; j < nMarkerElems; j++ {
			scanner.Scan()
			str := scanner.Text()
			strs := strings.Fields(str)
			// Parse the type ID
			t, err := strconv.Atoi(strs[0])
			marker.Elements[j].Type = VTKType(t)
			if err != nil {
				return n, fmt.Errorf("marker %d, element %d: bad type id: %v", i, j, err)
			}
			marker.Elements[j].VertexIds = make([]PointID, len(strs)-1)
			for k := 0; k < len(strs)-1; k++ {
				str = strs[k+1]
				str = strings.TrimSpace(str)
				t, err := strconv.Atoi(str)
				marker.Elements[j].VertexIds[k] = PointID(t)
				if err != nil {
					return n, fmt.Errorf("marked %d, element %d, point %d: bad point %v", i, j, k, err)
				}
			}
			marker.Elements[j].Id = -1 // marker elements don't have an ID
		}
		markers[i] = marker
	}
	s.Markers = markers
	return n, nil
}

func (s *SU2) initialize() error {
	// Create all of the neighbor maps
	for _, point := range s.Points {
		point.Neighbors = make(map[PointID]*Point)
	}
	// Add all of the neighboring points
	for _, elem := range s.Elements {
		switch elem.Type {
		case Quadrilateral:
			l := len(elem.VertexIds)
			// The neighbors are the adjacent nodes in the list
			for j, id := range elem.VertexIds {
				neighbor := elem.VertexIds[(j+1)%l]
				s.Points[id].Neighbors[neighbor] = s.Points[neighbor]
				neighbor = elem.VertexIds[(j+l-1)%l]
				s.Points[id].Neighbors[neighbor] = s.Points[neighbor]
			}
		default:
			return fmt.Errorf("element type %d not implemented", elem.Type)
		}
	}
	return nil
}
<commit_msg>Fixes to mesh parsing script<commit_after>// Package for dealing with SU2 meshes
// For mesh definition, see: http://adl-public.stanford.edu/docs/display/SUSQUARED/Mesh+files
// For similar Python code, see https://github.com/su2code/SU2/blob/master/SU2_PY/SU2/mesh/tools.py

package mesh

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"sort"
	"strconv"
	"strings"
)

type PointID int
type ElementID int
type VTKType int

const (
	Quadrilateral VTKType = 9
)

type SU2 struct {
	Elements []*Element
	Points   []*Point
	Markers  []*Marker
	Dim      int
}

type Marker struct {
	Tag string
	//TypeID   VTKType
	Elements []Element
}

type Element struct {
	Id        ElementID
	Type      VTKType
	VertexIds []PointID
}

type Point struct {
	Id               PointID
	Location         []float64
	Neighbors        map[PointID]*Point
	OrderedNeighbors []*Point // The neighbors stored in order of PointID
}

// ReadFrom reads the SU2 mesh from an io.Reader creating the mesh
func (s *SU2) ReadFrom(r io.Reader) (n int64, err error) {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		str := scanner.Text()
		str = strings.TrimSpace(str)
		if len(str) == 0 {
			continue
		}
		switch {
		case strings.HasPrefix(str, "%"):
			// ignore because comment
		case strings.HasPrefix(str, "NDIME="):
			// Parse the number of dimensions
			strs := strings.Split(str, "=")
			if len(strs) != 2 {
				return n, errors.New("more than one equals sign in NDIME line")
			}
			str = strings.TrimSpace(strs[1])
			s.Dim, err = strconv.Atoi(str)
			if err != nil {
				return n, errors.New("error parsing NDIME: " + err.Error())
			}
		case strings.HasPrefix(str, "NELEM="):
			read, err := s.parseElements(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		case strings.HasPrefix(str, "NPOIN="):
			read, err := s.parsePoints(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		case strings.HasPrefix(str, "NMARK="):
			read, err := s.parseMarkers(scanner, str)
			n += read
			if err != nil {
				return n, err
			}
		}
	}
	err = s.initialize()
	if err != nil {
		return n, err
	}
	return n, nil
}

func (s *SU2) parseElements(scanner *bufio.Scanner, str string) (n int64, err error) {
	// first, get the number of elements
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NELEM line")
	}
	str = strings.TrimSpace(strs[1])
	nelem, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NELEM: " + err.Error())
	}
	elements := make([]*Element, nelem)
	for i := 0; i < nelem; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning element %d: " + scanner.Err().Error())
		}
		elem := &Element{}
		str := scanner.Text()
		str = strings.TrimSpace(str)
		strs := strings.Fields(str)
		if len(strs) == 0 {
			return n, fmt.Errorf("error scanning element %d: unexpected blank line", i)
		}
		if len(strs) < 2 {
			return n, fmt.Errorf("error scanning element %d: should be at least two numbers (typeID elemID)", i)
		}
		t, err := strconv.Atoi(strs[0])
		elem.Type = VTKType(t)
		if err != nil {
			return n, fmt.Errorf("error scanning element %d: cannot parse typeID: %v", i, err)
		}
		elem.Id = ElementID(i)

		// BUG: SU2 accepts meshes that don't follow the format. See issue #52.
		t, err = strconv.Atoi(strs[len(strs)-1])
		if err != nil {
			return n, fmt.Errorf("error scanning element %d: cannot parse nodeID: %v", i, err)
		}
		if elem.Id != ElementID(i) {
			return n, fmt.Errorf("error scanning element %d: bad nodeID: %v", i, err)
		}
		strs = strs[1 : len(strs)-1]
		elem.VertexIds = make([]PointID, len(strs))
		for j, str := range strs {
			t, err := strconv.Atoi(str)
			elem.VertexIds[j] = PointID(t)
			if err != nil {
				return n, fmt.Errorf("error scanning element %d: cannot parse node number: %v", i, err)
			}
		}
		elements[i] = elem
	}
	s.Elements = elements
	return n, nil
}

func (s *SU2) parsePoints(scanner *bufio.Scanner, str string) (n int64, err error) {
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NPOIN line")
	}
	str = strings.TrimSpace(strs[1])
	npoints, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NPOIN: " + err.Error())
	}
	points := make([]*Point, npoints)
	for i := 0; i < npoints; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning point %d: " + scanner.Err().Error())
		}
		str := scanner.Text()
		str = strings.TrimSpace(str)
		strs := strings.Fields(str)
		if len(strs) != s.Dim+1 {
			return n, fmt.Errorf("point %d has wrong number of entries (should have nDim + 1)", i)
		}
		point := &Point{}
		point.Location = make([]float64, s.Dim)
		for j := 0; j < s.Dim; j++ {
			point.Location[j], err = strconv.ParseFloat(strs[j], 64)
			if err != nil {
				return n, fmt.Errorf("error parsing location of point %d: %v", i, err)
			}
		}
		t, err := strconv.Atoi(strs[len(strs)-1])
		point.Id = PointID(t)
		if err != nil {
			return n, fmt.Errorf("error parsing index of point %d: %v", i, err)
		}
		if point.Id != PointID(i) {
			return n, fmt.Errorf("bad point id %d: %v", i, err)
		}
		points[i] = point
	}
	s.Points = points
	return n, nil
}

func (s *SU2) parseMarkers(scanner *bufio.Scanner, str string) (n int64, err error) {
	strs := strings.Split(str, "=")
	if len(strs) != 2 {
		return n, errors.New("more than one equals sign in NMARK line")
	}
	str = strings.TrimSpace(strs[1])
	nMarkers, err := strconv.Atoi(str)
	if err != nil {
		return n, errors.New("error parsing NMARK: " + err.Error())
	}
	markers := make([]*Marker, nMarkers)
	for i := 0; i < nMarkers; i++ {
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning marker %d: " + scanner.Err().Error())
		}
		str := scanner.Text()
		if !strings.HasPrefix(str, "MARKER_TAG") {
			return n, fmt.Errorf("no MARKER_TAG for marker %d", i)
		}
		strs := strings.Split(str, "=")
		if len(strs) != 2 {
			return n, fmt.Errorf("marker %d: MARKER_TAG doesn't have exactly one equals sign ", i)
		}
		marker := &Marker{}
		marker.Tag = strs[1]
		scanner.Scan()
		if scanner.Err() != nil {
			return n, fmt.Errorf("error scanning MARKER_ELEMS %d: " + scanner.Err().Error())
		}
		str = scanner.Text()
		if !strings.HasPrefix(str, "MARKER_ELEMS") {
			return n, fmt.Errorf("MARKER_ELEMS prefix not found for marker %d", i)
		}
		strs = strings.Split(str, "=")
		if len(strs) != 2 {
			return n, fmt.Errorf("marker %d: MARKER_ELEMS doesn't have exactly one equals sign", i)
		}

		str = strings.TrimSpace(strs[1])
		nMarkerElems, err := strconv.Atoi(str)
		if err != nil {
			return n, fmt.Errorf("marker %d:  MARKER_ELEMS parsing error: ", err.Error())
		}
		marker.Elements = make([]Element, nMarkerElems)
		for j := 0; j < nMarkerElems; j++ {
			scanner.Scan()
			str := scanner.Text()
			strs := strings.Fields(str)
			// Parse the type ID
			t, err := strconv.Atoi(strs[0])
			marker.Elements[j].Type = VTKType(t)
			if err != nil {
				return n, fmt.Errorf("marker %d, element %d: bad type id: %v", i, j, err)
			}
			marker.Elements[j].VertexIds = make([]PointID, len(strs)-1)
			for k := 0; k < len(strs)-1; k++ {
				str = strs[k+1]
				str = strings.TrimSpace(str)
				t, err := strconv.Atoi(str)
				marker.Elements[j].VertexIds[k] = PointID(t)
				if err != nil {
					return n, fmt.Errorf("marked %d, element %d, point %d: bad point %v", i, j, k, err)
				}
			}
			marker.Elements[j].Id = -1 // marker elements don't have an ID
		}
		markers[i] = marker
	}
	s.Markers = markers
	return n, nil
}

func (s *SU2) initialize() error {
	// Create all of the neighbor maps
	for _, point := range s.Points {
		point.Neighbors = make(map[PointID]*Point)
	}
	// Add all of the neighboring points
	for _, elem := range s.Elements {
		switch elem.Type {
		case Quadrilateral:
			l := len(elem.VertexIds)
			if l != 4 {
				return fmt.Errorf("Incorrect number of nodes in element %v", elem.Id)
			}
			// The neighbors are the adjacent nodes in the list
			for j, id := range elem.VertexIds {
				neighbor := elem.VertexIds[(j+1)%l]
				s.Points[id].Neighbors[neighbor] = s.Points[neighbor]
				neighbor = elem.VertexIds[(j+l-1)%l]
				s.Points[id].Neighbors[neighbor] = s.Points[neighbor]
			}
		default:
			return fmt.Errorf("element type %d not implemented", elem.Type)
		}
	}
	for _, point := range s.Points {
		nNeighbors := len(point.Neighbors)
		neighborIds := make([]int, nNeighbors)
		var count int
		for id := range point.Neighbors {
			neighborIds[count] = int(id)
			count++
		}
		sort.Ints(neighborIds)
		point.OrderedNeighbors = make([]*Point, nNeighbors)
		for i, id := range neighborIds {
			var ok bool
			point.OrderedNeighbors[i], ok = point.Neighbors[PointID(id)]
			if !ok {
				panic("bad neighbor")
			}
		}
	}
	return nil
}
<|endoftext|>