<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

var (
	successEndpoints = []string{
		// Discovery
		"http://169.254.169.254",
		"http://metadata.google.internal",
		"http://169.254.169.254/",
		"http://metadata.google.internal/",
		"http://metadata.google.internal/computeMetadata",
		"http://metadata.google.internal/computeMetadata/v1",
		// Allowed API versions.
		"http://metadata.google.internal/computeMetadata/v1/",
		// Service account token endpoints.
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
		// Params that contain 'recursive' as substring.
		"http://metadata.google.internal/computeMetadata/v1/instance/?nonrecursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?something=other&nonrecursive=true",
	}
	legacySuccessEndpoints = []string{
		// Discovery
		"http://metadata.google.internal/0.1",
		"http://metadata.google.internal/0.1/",
		"http://metadata.google.internal/0.1/meta-data",
		"http://metadata.google.internal/computeMetadata/v1beta1",
		// Allowed API versions.
		"http://metadata.google.internal/0.1/meta-data/",
		"http://metadata.google.internal/computeMetadata/v1beta1/",
		// Service account token endpoints.
		"http://metadata.google.internal/0.1/meta-data/service-accounts/default/acquire",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token",
	}
	noKubeEnvEndpoints = []string{
		// Check that these don't get a recursive result.
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive%3Dtrue",   // urlencoded
		"http://metadata.google.internal/computeMetadata/v1/instance/?re%08ecursive=true", // backspaced
	}
	failureEndpoints = []string{
		// Other API versions.
		"http://metadata.google.internal/0.2/",
		"http://metadata.google.internal/computeMetadata/v2/",
		// kube-env.
		"http://metadata.google.internal/0.1/meta-data/attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env",
		// VM identity.
		"http://metadata.google.internal/0.1/meta-data/service-accounts/default/identity",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/identity",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity",
		// Recursive.
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?something=other&recursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true&something=other",
		// Other.
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes//kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes/../attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts//default/identity",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/../service-accounts/default/identity",
	}
)

func main() {
	success := 0
	h := map[string][]string{
		"Metadata-Flavor": {"Google"},
	}
	for _, e := range successEndpoints {
		if err := checkURL(e, h, 200, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}
	for _, e := range noKubeEnvEndpoints {
		if err := checkURL(e, h, 200, "", "kube-env"); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}
	for _, e := range failureEndpoints {
		if err := checkURL(e, h, 403, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}

	legacyEndpointExpectedStatus := 200
	if err := checkURL("http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints", h, 200, "true", ""); err == nil {
		// If `disable-legacy-endpoints` is set to true, queries to unconcealed legacy endpoints will return a 403.
		legacyEndpointExpectedStatus = 403
	}
	for _, e := range legacySuccessEndpoints {
		if err := checkURL(e, h, legacyEndpointExpectedStatus, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}

	xForwardedForHeader := map[string][]string{
		"X-Forwarded-For": {"Somebody-somewhere"},
	}
	// Check that success endpoints fail if X-Forwarded-For is present.
	for _, e := range successEndpoints {
		if err := checkURL(e, xForwardedForHeader, 403, "", ""); err != nil {
			log.Printf("Wrong response for %v with X-Forwarded-For: %v", e, err)
			success = 1
		}
	}
	os.Exit(success)
}

// Checks that a URL with the given headers returns the right code.
// If expectedToContain is non-empty, checks that the body contains expectedToContain.
// Similarly, if expectedToNotContain is non-empty, checks that the body doesn't contain expectedToNotContain.
func checkURL(url string, header http.Header, expectedStatus int, expectedToContain, expectedToNotContain string) error {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	req.Header = header
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != expectedStatus {
		return fmt.Errorf("unexpected response: got %d, want %d", resp.StatusCode, expectedStatus)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	if expectedToContain != "" {
		matched, err := regexp.Match(expectedToContain, body)
		if err != nil {
			return err
		}
		if !matched {
			return fmt.Errorf("body didn't contain %q: got %v", expectedToContain, string(body))
		}
	}
	if expectedToNotContain != "" {
		matched, err := regexp.Match(expectedToNotContain, body)
		if err != nil {
			return err
		}
		if matched {
			return fmt.Errorf("body incorrectly contained %q: got %v", expectedToNotContain, string(body))
		}
	}
	return nil
}
<commit_msg>always allow unimportant legacy root paths<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

var (
	successEndpoints = []string{
		// Discovery
		"http://169.254.169.254",
		"http://metadata.google.internal",
		"http://169.254.169.254/",
		"http://metadata.google.internal/",
		"http://metadata.google.internal/0.1",
		"http://metadata.google.internal/0.1/",
		"http://metadata.google.internal/computeMetadata",
		"http://metadata.google.internal/computeMetadata/v1",
		// Allowed API versions.
		"http://metadata.google.internal/computeMetadata/v1/",
		// Service account token endpoints.
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
		// Params that contain 'recursive' as substring.
		"http://metadata.google.internal/computeMetadata/v1/instance/?nonrecursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?something=other&nonrecursive=true",
	}
	legacySuccessEndpoints = []string{
		// Discovery
		"http://metadata.google.internal/0.1/meta-data",
		"http://metadata.google.internal/computeMetadata/v1beta1",
		// Allowed API versions.
		"http://metadata.google.internal/0.1/meta-data/",
		"http://metadata.google.internal/computeMetadata/v1beta1/",
		// Service account token endpoints.
		"http://metadata.google.internal/0.1/meta-data/service-accounts/default/acquire",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token",
	}
	noKubeEnvEndpoints = []string{
		// Check that these don't get a recursive result.
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive%3Dtrue",   // urlencoded
		"http://metadata.google.internal/computeMetadata/v1/instance/?re%08ecursive=true", // backspaced
	}
	failureEndpoints = []string{
		// Other API versions.
		"http://metadata.google.internal/0.2/",
		"http://metadata.google.internal/computeMetadata/v2/",
		// kube-env.
		"http://metadata.google.internal/0.1/meta-data/attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env",
		// VM identity.
		"http://metadata.google.internal/0.1/meta-data/service-accounts/default/identity",
		"http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/identity",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity",
		// Recursive.
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?something=other&recursive=true",
		"http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true&something=other",
		// Other.
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes//kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/attributes/../attributes/kube-env",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts//default/identity",
		"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/../service-accounts/default/identity",
	}
)

func main() {
	success := 0
	h := map[string][]string{
		"Metadata-Flavor": {"Google"},
	}
	for _, e := range successEndpoints {
		if err := checkURL(e, h, 200, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}
	for _, e := range noKubeEnvEndpoints {
		if err := checkURL(e, h, 200, "", "kube-env"); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}
	for _, e := range failureEndpoints {
		if err := checkURL(e, h, 403, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}

	legacyEndpointExpectedStatus := 200
	if err := checkURL("http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints", h, 200, "true", ""); err == nil {
		// If `disable-legacy-endpoints` is set to true, queries to unconcealed legacy endpoints will return a 403.
		legacyEndpointExpectedStatus = 403
	}
	for _, e := range legacySuccessEndpoints {
		if err := checkURL(e, h, legacyEndpointExpectedStatus, "", ""); err != nil {
			log.Printf("Wrong response for %v: %v", e, err)
			success = 1
		}
	}

	xForwardedForHeader := map[string][]string{
		"X-Forwarded-For": {"Somebody-somewhere"},
	}
	// Check that success endpoints fail if X-Forwarded-For is present.
	for _, e := range successEndpoints {
		if err := checkURL(e, xForwardedForHeader, 403, "", ""); err != nil {
			log.Printf("Wrong response for %v with X-Forwarded-For: %v", e, err)
			success = 1
		}
	}
	os.Exit(success)
}

// Checks that a URL with the given headers returns the right code.
// If expectedToContain is non-empty, checks that the body contains expectedToContain.
// Similarly, if expectedToNotContain is non-empty, checks that the body doesn't contain expectedToNotContain.
func checkURL(url string, header http.Header, expectedStatus int, expectedToContain, expectedToNotContain string) error {
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	req.Header = header
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != expectedStatus {
		return fmt.Errorf("unexpected response: got %d, want %d", resp.StatusCode, expectedStatus)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	if expectedToContain != "" {
		matched, err := regexp.Match(expectedToContain, body)
		if err != nil {
			return err
		}
		if !matched {
			return fmt.Errorf("body didn't contain %q: got %v", expectedToContain, string(body))
		}
	}
	if expectedToNotContain != "" {
		matched, err := regexp.Match(expectedToNotContain, body)
		if err != nil {
			return err
		}
		if matched {
			return fmt.Errorf("body incorrectly contained %q: got %v", expectedToNotContain, string(body))
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2011 Alexander Færøy <ahf@0x90.dk>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

type ClientRegistry struct {
    ircd *Ircd

    // Maps nicknames to a Client.
    clients map[string] *Client
}

func NewClientRegistry(ircd *Ircd) *ClientRegistry {
    return &ClientRegistry{ircd, make(map[string] *Client)}
}

func (this *ClientRegistry) Find(nick string) *Client {
    if client, ok := this.clients[nick]; ok {
        return client
    }

    return nil
}

func (this *ClientRegistry) Register(client *Client) bool {
    this.Printf("Registering %s", client.Nickname())

    if _, exists := this.clients[client.Nickname()]; exists {
        return false
    }

    this.clients[client.Nickname()] = client
    return true
}

func (this *ClientRegistry) Unregister(client *Client) {
    this.Printf("Unregistering %s", client)
    this.clients[client.Nickname()] = nil, false
}

func (this *ClientRegistry) Printf(format string, a...interface{}) {
    this.ircd.Printf(format, a...)
}
<commit_msg>Lower the nickname key in the client registry.<commit_after>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2011 Alexander Færøy <ahf@0x90.dk>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

type ClientRegistry struct {
    ircd *Ircd

    // Maps nicknames to a Client.
    clients map[string] *Client
}

func NewClientRegistry(ircd *Ircd) *ClientRegistry {
    return &ClientRegistry{ircd, make(map[string] *Client)}
}

func (this *ClientRegistry) Find(nick string) *Client {
    if client, ok := this.clients[ToLower(nick)]; ok {
        return client
    }

    return nil
}

func (this *ClientRegistry) Register(client *Client) bool {
    this.Printf("Registering %s", client.Nickname())

    n := ToLower(client.Nickname())

    if _, exists := this.clients[n]; exists {
        return false
    }

    this.clients[n] = client
    return true
}

func (this *ClientRegistry) Unregister(client *Client) {
    this.Printf("Unregistering %s", client)
    this.clients[ToLower(client.Nickname())] = nil, false
}

func (this *ClientRegistry) Printf(format string, a...interface{}) {
    this.ircd.Printf(format, a...)
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/plugins"
	"github.com/bitrise-io/bitrise/version"
	"github.com/codegangsta/cli"
)

func initLogFormatter() {
	log.SetFormatter(&log.TextFormatter{
		FullTimestamp:   true,
		ForceColors:     true,
		TimestampFormat: "15:04:05",
	})
}

func before(c *cli.Context) error {
	/*
		return err will print app's help also,
		use log.Fatal to avoid print help.
	*/

	initLogFormatter()
	initHelpAndVersionFlags()
	initAppHelpTemplate()

	// Debug mode?
	if c.Bool(DebugModeKey) {
		// set for other tools, as an ENV
		if err := os.Setenv(configs.DebugModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set DEBUG env, error: %s", err)
		}
		configs.IsDebugMode = true
		log.Warn("=> Started in DEBUG mode")
	}

	// Log level
	// If log level defined - use it
	logLevelStr := c.String(LogLevelKey)
	if logLevelStr == "" && configs.IsDebugMode {
		// if no Log Level defined and we're in Debug Mode - set loglevel to debug
		logLevelStr = "debug"
		log.Warn("=> LogLevel set to debug")
	}
	if logLevelStr == "" {
		// if still empty: set the default
		logLevelStr = "info"
	}

	level, err := log.ParseLevel(logLevelStr)
	if err != nil {
		log.Fatalf("Failed parse log level, error: %s", err)
	}

	if err := os.Setenv(configs.LogLevelEnvKey, level.String()); err != nil {
		log.Fatalf("Failed to set LOGLEVEL env, error: %s", err)
	}
	log.SetLevel(level)

	// CI Mode check
	if c.Bool(CIKey) {
		// if CI mode indicated make sure we set the related env
		//  so all other tools we use will also get it
		if err := os.Setenv(configs.CIModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set CI env, error: %s", err)
		}
		configs.IsCIMode = true
	}

	if err := configs.InitPaths(); err != nil {
		log.Fatalf("Failed to initialize required paths, error: %s", err)
	}

	if err := plugins.InitPaths(); err != nil {
		log.Fatalf("Failed to initialize required plugin paths, error: %s", err)
	}

	// Pull Request Mode check
	if c.Bool(PRKey) {
		// if PR mode indicated make sure we set the related env
		//  so all other tools we use will also get it
		if err := os.Setenv(configs.PRModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set PR env, error: %s", err)
		}
		configs.IsPullRequestMode = true
	}

	pullReqID := os.Getenv(configs.PullRequestIDEnvKey)
	if pullReqID != "" {
		configs.IsPullRequestMode = true
	}

	IsPR := os.Getenv(configs.PRModeEnvKey)
	if IsPR == "true" {
		configs.IsPullRequestMode = true
	}

	return nil
}

func printVersion(c *cli.Context) {
	fmt.Fprintf(c.App.Writer, "%v\n", c.App.Version)
}

// Run ...
func Run() {
	// Parse cl
	cli.VersionPrinter = printVersion

	app := cli.NewApp()
	app.Name = path.Base(os.Args[0])
	app.Usage = "Bitrise Automations Workflow Runner"
	app.Version = version.VERSION

	app.Author = ""
	app.Email = ""

	app.Before = before

	app.Flags = flags
	app.Commands = commands

	app.Action = func(c *cli.Context) {
		pluginName, pluginArgs, isPlugin := plugins.ParseArgs(c.Args())
		if isPlugin {
			log.Debugf("Try to run bitrise plugin: (%s) with args: (%v)", pluginName, pluginArgs)

			plugin, found, err := plugins.LoadPlugin(pluginName)
			if err != nil {
				log.Fatalf("Failed to get plugin (%s), error: %s", pluginName, err)
			}
			if !found {
				log.Fatalf("Plugin (%s) not installed", pluginName)
			}

			log.Debugf("Start plugin: (%s)", pluginName)
			if err := plugins.RunPluginByCommand(plugin, pluginArgs); err != nil {
				log.Fatalf("Failed to run plugin (%s), error: %s", pluginName, err)
			}
		} else {
			cli.ShowAppHelp(c)
		}
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatalf("Finished with error: %s", err)
	}
}
<commit_msg>errcheck fix<commit_after>package cli

import (
	"fmt"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/plugins"
	"github.com/bitrise-io/bitrise/version"
	"github.com/codegangsta/cli"
)

func initLogFormatter() {
	log.SetFormatter(&log.TextFormatter{
		FullTimestamp:   true,
		ForceColors:     true,
		TimestampFormat: "15:04:05",
	})
}

func before(c *cli.Context) error {
	/*
		return err will print app's help also,
		use log.Fatal to avoid print help.
	*/

	initLogFormatter()
	initHelpAndVersionFlags()
	initAppHelpTemplate()

	// Debug mode?
	if c.Bool(DebugModeKey) {
		// set for other tools, as an ENV
		if err := os.Setenv(configs.DebugModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set DEBUG env, error: %s", err)
		}
		configs.IsDebugMode = true
		log.Warn("=> Started in DEBUG mode")
	}

	// Log level
	// If log level defined - use it
	logLevelStr := c.String(LogLevelKey)
	if logLevelStr == "" && configs.IsDebugMode {
		// if no Log Level defined and we're in Debug Mode - set loglevel to debug
		logLevelStr = "debug"
		log.Warn("=> LogLevel set to debug")
	}
	if logLevelStr == "" {
		// if still empty: set the default
		logLevelStr = "info"
	}

	level, err := log.ParseLevel(logLevelStr)
	if err != nil {
		log.Fatalf("Failed parse log level, error: %s", err)
	}

	if err := os.Setenv(configs.LogLevelEnvKey, level.String()); err != nil {
		log.Fatalf("Failed to set LOGLEVEL env, error: %s", err)
	}
	log.SetLevel(level)

	// CI Mode check
	if c.Bool(CIKey) {
		// if CI mode indicated make sure we set the related env
		//  so all other tools we use will also get it
		if err := os.Setenv(configs.CIModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set CI env, error: %s", err)
		}
		configs.IsCIMode = true
	}

	if err := configs.InitPaths(); err != nil {
		log.Fatalf("Failed to initialize required paths, error: %s", err)
	}

	if err := plugins.InitPaths(); err != nil {
		log.Fatalf("Failed to initialize required plugin paths, error: %s", err)
	}

	// Pull Request Mode check
	if c.Bool(PRKey) {
		// if PR mode indicated make sure we set the related env
		//  so all other tools we use will also get it
		if err := os.Setenv(configs.PRModeEnvKey, "true"); err != nil {
			log.Fatalf("Failed to set PR env, error: %s", err)
		}
		configs.IsPullRequestMode = true
	}

	pullReqID := os.Getenv(configs.PullRequestIDEnvKey)
	if pullReqID != "" {
		configs.IsPullRequestMode = true
	}

	IsPR := os.Getenv(configs.PRModeEnvKey)
	if IsPR == "true" {
		configs.IsPullRequestMode = true
	}

	return nil
}

func printVersion(c *cli.Context) {
	fmt.Fprintf(c.App.Writer, "%v\n", c.App.Version)
}

// Run ...
func Run() {
	// Parse cl
	cli.VersionPrinter = printVersion

	app := cli.NewApp()
	app.Name = path.Base(os.Args[0])
	app.Usage = "Bitrise Automations Workflow Runner"
	app.Version = version.VERSION

	app.Author = ""
	app.Email = ""

	app.Before = before

	app.Flags = flags
	app.Commands = commands

	app.Action = func(c *cli.Context) {
		pluginName, pluginArgs, isPlugin := plugins.ParseArgs(c.Args())
		if isPlugin {
			log.Debugf("Try to run bitrise plugin: (%s) with args: (%v)", pluginName, pluginArgs)

			plugin, found, err := plugins.LoadPlugin(pluginName)
			if err != nil {
				log.Fatalf("Failed to get plugin (%s), error: %s", pluginName, err)
			}
			if !found {
				log.Fatalf("Plugin (%s) not installed", pluginName)
			}

			log.Debugf("Start plugin: (%s)", pluginName)
			if err := plugins.RunPluginByCommand(plugin, pluginArgs); err != nil {
				log.Fatalf("Failed to run plugin (%s), error: %s", pluginName, err)
			}
		} else {
			if err := cli.ShowAppHelp(c); err != nil {
				log.Fatalf("Failed to show help, error: %s", err)
			}
		}
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatalf("Finished with error: %s", err)
	}
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/Originate/git-town/src/util"
	"github.com/acarl005/stripansi"
)

// Command runs commands on the command line
type Command struct {
	name   string
	args   []string
	ran    bool
	err    error
	output string
}

// New creates a new Command instance
func New(command ...string) *Command {
	return &Command{name: command[0], args: command[1:]}
}

// Run runs this command.
// Doesn't run again if it ran already.
// Stores the outcome in fields of the instance.
func (r *Command) Run() {
	if r.ran {
		return
	}

	logRun(r)
	subProcess := exec.Command(r.name, r.args...) // #nosec
	output, err := subProcess.CombinedOutput()
	r.output = stripansi.Strip(strings.TrimSpace(string(output)))
	r.err = err
	r.ran = true
}

// Output returns the output of this command.
// Runs if it hasn't so far.
func (r *Command) Output() string {
	r.Run()
	return r.output
}

// OutputLines returns the output of this command, split into lines.
// Runs if it hasn't so far.
func (r *Command) OutputLines() []string {
	return strings.Split(r.Output(), "\n")
}

// Err returns the error that this command encountered.
// Runs the command if it hasn't so far.
func (r *Command) Err() error {
	r.Run()
	return r.err
}

// OutputContainsLine returns whether the output of this command
// contains the given line
func (r *Command) OutputContainsLine(line string) bool {
	return util.DoesStringArrayContain(r.OutputLines(), line)
}

// OutputContainsText returns whether the output of this command
// contains the given text
func (r *Command) OutputContainsText(text string) bool {
	r.Run()
	return strings.Contains(r.output, text)
}

func (r Command) String() string {
	return fmt.Sprintf("%s %s", r.name, strings.Join(r.args, " "))
}
<commit_msg>Fix instance name (#1227)<commit_after>package command

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/Originate/git-town/src/util"
	"github.com/acarl005/stripansi"
)

// Command runs commands on the command line
type Command struct {
	name   string
	args   []string
	ran    bool
	err    error
	output string
}

// New creates a new Command instance
func New(command ...string) *Command {
	return &Command{name: command[0], args: command[1:]}
}

// Run runs this command.
// Doesn't run again if it ran already.
// Stores the outcome in fields of the instance.
func (c *Command) Run() {
	if c.ran {
		return
	}

	logRun(c)
	subProcess := exec.Command(c.name, c.args...) // #nosec
	output, err := subProcess.CombinedOutput()
	c.output = stripansi.Strip(strings.TrimSpace(string(output)))
	c.err = err
	c.ran = true
}

// Output returns the output of this command.
// Runs if it hasn't so far.
func (c *Command) Output() string {
	c.Run()
	return c.output
}

// OutputLines returns the output of this command, split into lines.
// Runs if it hasn't so far.
func (c *Command) OutputLines() []string {
	return strings.Split(c.Output(), "\n")
}

// Err returns the error that this command encountered.
// Runs the command if it hasn't so far.
func (c *Command) Err() error {
	c.Run()
	return c.err
}

// OutputContainsLine returns whether the output of this command
// contains the given line
func (c *Command) OutputContainsLine(line string) bool {
	return util.DoesStringArrayContain(c.OutputLines(), line)
}

// OutputContainsText returns whether the output of this command
// contains the given text
func (c *Command) OutputContainsText(text string) bool {
	c.Run()
	return strings.Contains(c.output, text)
}

func (c Command) String() string {
	return fmt.Sprintf("%s %s", c.name, strings.Join(c.args, " "))
}
<|endoftext|>


<commit_before>package admin

import (
	"fmt"
	"path"
	"time"

	"github.com/qor/exchange"
	"github.com/qor/exchange/backends/csv"
	"github.com/qor/media/oss"
	"github.com/qor/qor"
	"github.com/qor/worker"

	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
)

func getWorker() *worker.Worker {
	Worker := worker.New()

	type sendNewsletterArgument struct {
		Subject      string
		Content      string `sql:"size:65532"`
		SendPassword string
		worker.Schedule
	}

	Worker.RegisterJob(&worker.Job{
		Name: "Send Newsletter",
		Handler: func(argument interface{}, qorJob worker.QorJobInterface) error {
			qorJob.AddLog("Started sending newsletters...")
			qorJob.AddLog(fmt.Sprintf("Argument: %+v", argument.(*sendNewsletterArgument)))
			for i := 1; i <= 100; i++ {
				time.Sleep(100 * time.Millisecond)
				qorJob.AddLog(fmt.Sprintf("Sending newsletter %v...", i))
				qorJob.SetProgress(uint(i))
			}
			qorJob.AddLog("Finished send newsletters")
			return nil
		},
		Resource: Admin.NewResource(&sendNewsletterArgument{}),
	})

	type importProductArgument struct {
		File oss.OSS
	}

	Worker.RegisterJob(&worker.Job{
		Name:  "Import Products",
		Group: "Products Management",
		Handler: func(arg interface{}, qorJob worker.QorJobInterface) error {
			argument := arg.(*importProductArgument)

			context := &qor.Context{DB: db.DB}

			var errorCount uint

			if err := ProductExchange.Import(
				csv.New(path.Join("public", argument.File.URL())),
				context,
				func(progress exchange.Progress) error {
					var cells = []worker.TableCell{
						{Value: fmt.Sprint(progress.Current)},
					}

					var hasError bool
					for _, cell := range progress.Cells {
						var tableCell = worker.TableCell{
							Value: fmt.Sprint(cell.Value),
						}

						if cell.Error != nil {
							hasError = true
							errorCount++
							tableCell.Error = cell.Error.Error()
						}

						cells = append(cells, tableCell)
					}

					if hasError {
						if errorCount == 1 {
							var headerCells = []worker.TableCell{
								{Value: "Line No."},
							}
							for _, cell := range progress.Cells {
								headerCells = append(headerCells, worker.TableCell{
									Value: cell.Header,
								})
							}
							qorJob.AddResultsRow(headerCells...)
						}

						qorJob.AddResultsRow(cells...)
					}

					qorJob.SetProgress(uint(float32(progress.Current) / float32(progress.Total) * 100))
					qorJob.AddLog(fmt.Sprintf("%d/%d Importing product %v", progress.Current, progress.Total, progress.Value.(*models.Product).Code))
					return nil
				},
			); err != nil {
				qorJob.AddLog(err.Error())
			}

			return nil
		},
		Resource: Admin.NewResource(&importProductArgument{}),
	})

	Worker.RegisterJob(&worker.Job{
		Name:  "Export Products",
		Group: "Products Management",
		Handler: func(arg interface{}, qorJob worker.QorJobInterface) error {
			qorJob.AddLog("Exporting products...")

			context := &qor.Context{DB: db.DB}
			fileName := fmt.Sprintf("/downloads/products.%v.csv", time.Now().UnixNano())
			if err := ProductExchange.Export(
				csv.New(path.Join("public", fileName)),
				context,
				func(progress exchange.Progress) error {
					qorJob.AddLog(fmt.Sprintf("%v/%v Exporting product %v", progress.Current, progress.Total, progress.Value.(*models.Product).Code))
					return nil
				},
			); err != nil {
				qorJob.AddLog(err.Error())
			}

			qorJob.SetProgressText(fmt.Sprintf("Download exported products", fileName))
			return nil
		},
	})
	return Worker
}
<commit_msg>Fix load templates in Windows<commit_after>package admin

import (
	"fmt"
	"path/filepath"
	"time"

	"github.com/qor/exchange"
	"github.com/qor/exchange/backends/csv"
	"github.com/qor/media/oss"
	"github.com/qor/qor"
	"github.com/qor/worker"

	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/db"
)

func getWorker() *worker.Worker {
	Worker := worker.New()

	type sendNewsletterArgument struct {
		Subject      string
		Content      string `sql:"size:65532"`
		SendPassword string
		worker.Schedule
	}

	Worker.RegisterJob(&worker.Job{
		Name: "Send Newsletter",
		Handler: func(argument interface{}, qorJob worker.QorJobInterface) error {
			qorJob.AddLog("Started sending newsletters...")
			qorJob.AddLog(fmt.Sprintf("Argument: %+v", argument.(*sendNewsletterArgument)))
			for i := 1; i <= 100; i++ {
				time.Sleep(100 * time.Millisecond)
				qorJob.AddLog(fmt.Sprintf("Sending newsletter %v...", i))
				qorJob.SetProgress(uint(i))
			}
			qorJob.AddLog("Finished send newsletters")
			return nil
		},
		Resource: Admin.NewResource(&sendNewsletterArgument{}),
	})

	type importProductArgument struct {
		File oss.OSS
	}

	Worker.RegisterJob(&worker.Job{
		Name:  "Import Products",
		Group: "Products Management",
		Handler: func(arg interface{}, qorJob worker.QorJobInterface) error {
			argument := arg.(*importProductArgument)

			context := &qor.Context{DB: db.DB}

			var errorCount uint

			if err := ProductExchange.Import(
				csv.New(filepath.Join("public", argument.File.URL())),
				context,
				func(progress exchange.Progress) error {
					var cells = []worker.TableCell{
						{Value: fmt.Sprint(progress.Current)},
					}

					var hasError bool
					for _, cell := range progress.Cells {
						var tableCell = worker.TableCell{
							Value: fmt.Sprint(cell.Value),
						}

						if cell.Error != nil {
							hasError = true
							errorCount++
							tableCell.Error = cell.Error.Error()
						}

						cells = append(cells, tableCell)
					}

					if hasError {
						if errorCount == 1 {
							var headerCells = []worker.TableCell{
								{Value: "Line No."},
							}
							for _, cell := range progress.Cells {
								headerCells = append(headerCells, worker.TableCell{
									Value: cell.Header,
								})
							}
							qorJob.AddResultsRow(headerCells...)
						}

						qorJob.AddResultsRow(cells...)
					}

					qorJob.SetProgress(uint(float32(progress.Current) / float32(progress.Total) * 100))
					qorJob.AddLog(fmt.Sprintf("%d/%d Importing product %v", progress.Current, progress.Total, progress.Value.(*models.Product).Code))
					return nil
				},
			); err != nil {
				qorJob.AddLog(err.Error())
			}

			return nil
		},
		Resource: Admin.NewResource(&importProductArgument{}),
	})

	Worker.RegisterJob(&worker.Job{
		Name:  "Export Products",
		Group: "Products Management",
		Handler: func(arg interface{}, qorJob worker.QorJobInterface) error {
			qorJob.AddLog("Exporting products...")

			context := &qor.Context{DB: db.DB}
			fileName := fmt.Sprintf("/downloads/products.%v.csv", time.Now().UnixNano())
			if err := ProductExchange.Export(
				csv.New(filepath.Join("public", fileName)),
				context,
				func(progress exchange.Progress) error {
					qorJob.AddLog(fmt.Sprintf("%v/%v Exporting product %v", progress.Current, progress.Total, progress.Value.(*models.Product).Code))
					return nil
				},
			); err != nil {
				qorJob.AddLog(err.Error())
			}

			qorJob.SetProgressText(fmt.Sprintf("Download exported products", fileName))
			return nil
		},
	})
	return Worker
}
<|endoftext|>


<commit_before>package overlay

import (
	"github.com/MJKWoolnough/gopherjs/style"
	"github.com/MJKWoolnough/gopherjs/xjs"
	"honnef.co/go/js/dom"
)

const css = `
window, body {
	width : 100%;
	margin : 0;
	overflow-x : hidden;
}

.mw-overlay {
	position : fixed;
	top : 0;
	left : 0;
	right : 0;
	bottom : 0;
	background : rgba(0, 0, 0, 0.25);
}

.mw-overlay > * {
	position : absolute;
	top : 10px;
	left : 10px;
	right : 10px;
	background : #fff;
}

.mw-overlay .closer {
	color : #fff;
	font-family : serif;
	right : 2px;
	position : absolute;
	text-shadow : #000 -1px -1px 0, #000 1px -1px 0, #000 1px 1px 0, #000 -1px 1px 0, #000 -1px 0 0, #000 1px 0 0;
	top : 0;
	transition : color 0.25s;
	transition-timing-function : ease;
	user-select : none;
	z-index : 1;
	-moz-user-select : none;
	-webkit-user-select : none;
}

.mw-overlay .closer:hover {
	color : #f00;
	cursor : pointer;
}`

func init() {
	style.Add(css)
}

func Overlay(e dom.Element) dom.Element {
	o := xjs.CreateElement("div")
	o.SetAttribute("class", "mw-overlay")
	c := xjs.CreateElement("div")
	xjs.SetInnerText(c, "X")
	c.SetAttribute("class", "closer")
	c.AddEventListener("click", false, func(dom.Event) {
		p := o.ParentNode()
		if p != nil {
			p.RemoveChild(o)
		}
	})
	e.InsertBefore(c, e.FirstChild())
	o.AppendChild(e)
	return o
}
<commit_msg>Closer is now part of outerlayer, not added as a child of inner layer - also added CSS to stop multiple layers affecting the grey layer<commit_after>package overlay

import (
	"github.com/MJKWoolnough/gopherjs/style"
	"github.com/MJKWoolnough/gopherjs/xjs"
	"honnef.co/go/js/dom"
)

const css = `
window, body {
	width : 100%;
	margin : 0;
	overflow-x : hidden;
}

.mw-overlay {
	position : fixed;
	top : 0;
	left : 0;
	right : 0;
	bottom : 0;
	background-color : rgba(0, 0, 0, 0.25);
}

.mw-overlay > *:not(.closer) {
	position : absolute;
	top : 10px;
	left : 10px;
	right : 10px;
	background-color : #fff;
}

.mw-overlay > .closer {
	color : #fff;
	font-family : serif;
	right : 12px;
	position : absolute;
	text-shadow : #000 -1px -1px 0, #000 1px -1px 0, #000 1px 1px 0, #000 -1px 1px 0, #000 -1px 0 0, #000 1px 0 0;
	top : 10px;
	transition : color 0.25s;
	transition-timing-function : ease;
	user-select : none;
	z-index : 1;
	-moz-user-select : none;
	-webkit-user-select : none;
}

.mw-overlay > .closer:hover {
	color : #f00;
	cursor : pointer;
}

* > .mw-overlay:not(:last-of-type) {
	background-color : transparent;
}
`

func init() {
	style.Add(css)
}

func Overlay(e dom.Element) dom.Element {
	o := xjs.CreateElement("div")
	o.SetAttribute("class", "mw-overlay")
	c := xjs.CreateElement("div")
	xjs.SetInnerText(c, "X")
	c.SetAttribute("class", "closer")
	c.AddEventListener("click", false, func(dom.Event) {
		p := o.ParentNode()
		if p != nil {
			p.RemoveChild(o)
		}
	})
	o.AppendChild(c)
	o.AppendChild(e)
	return o
}
<|endoftext|>


<commit_before>package bwmf

import (
	"fmt"
	// "math"
	"testing"

	pb "github.com/taskgraph/taskgraph/example/bwmf/proto"
	"github.com/taskgraph/taskgraph/op"
)

func TestEvaluation(t *testing.T) {

	h := op.NewVecParameter(4)
	g := h.CloneWithoutCopy()
	h.Set(0, 1.0)
	h.Set(1, 1.0)
	h.Set(2, 1.0)
	h.Set(3, 1.0)

	kld_loss := newKLDivLoss()

	loss_val := kld_loss.Evaluate(h, g)

	fmt.Println("loss val is ", loss_val)
	fmt.Println("gradient is ", g)

	/*
		if math.Abs(float64(loss_val)-4.6) > 5e-2 {
			t.Errorf("Loss value incorrect: actual %f, expected 6.06543", loss_val)
		}

		if math.Abs(float64(g.Get(0))+1.01) > 1e-2 || math.Abs(float64(g.Get(1))+1.01) > 1e-2 {
			t.Errorf("Gradient incorrect: actual {%f, %f}, expected { -1.01, -1.01 }", g.Get(0), g.Get(1))
		}
	*/

	h.Set(0, 0.0)
	h.Set(1, 1.0)
	h.Set(2, 1.0)
	h.Set(3, 0.0)

	loss_val = kld_loss.Evaluate(h, g)

	fmt.Println("loss val is ", loss_val)
	fmt.Println("gradient is ", g)

}

func newKLDivLoss() *KLDivLoss {
	m := uint32(3)
	n := uint32(2)
	k := uint32(2)

	// v is
	// -------------
	// | 0.0 | 1.0 |
	// |-----|-----|
	// | 1.0 | 0.0 |
	// |-----|-----|
	// | 0.5 | 0.5 |
	// |-----|-----|
	v := &pb.MatrixShard{
		IsSparse: true,
		M: 2,
		N: 3,
		Val: []float32 {1.0, 1.0, 0.5, 0.5},
		Ir: []uint32 {1, 0, 0, 1},
		Jc: []uint32 {0, 1, 2, 4},
	}

	// w is composed by two shards:
	//
	// shard 0:
	//  -------------
	//  | 1.0 | 0.0 |
	//  -------------
	//  | 0.0 | 1.0 |
	//  -------------
	// and shard 1:
	//  -------------
	//  | 0.5 | 0.5 |
	//  -------------
	//
	w := []*pb.MatrixShard{
		&pb.MatrixShard{
			M: 2,
			N: n,
			Val: []float32 {1.0, 0, 0.0, 1.0},
		},
		&pb.MatrixShard{
			M: 1,
			N: n,
			Val: []float32 {0.5, 0.5},
		},
	}

	return NewKLDivLoss(v, w, m, n, k, 1e-6)
}
<commit_msg>bwmf: check the result of kldiv in unit tests<commit_after>package bwmf

import (
	"fmt"
	"math"
	"testing"

	pb "github.com/taskgraph/taskgraph/example/bwmf/proto"
	"github.com/taskgraph/taskgraph/op"
)

func TestEvaluation(t *testing.T) {

	h := op.NewVecParameter(4)
	g := h.CloneWithoutCopy()
	h.Set(0, 1.0)
	h.Set(1, 1.0)
	h.Set(2, 1.0)
	h.Set(3, 1.0)

	kld_loss := newKLDivLoss()

	loss_val := kld_loss.Evaluate(h, g)

	fmt.Println("loss val is ", loss_val)
	fmt.Println("gradient is ", g)

	expectedLoss := 5.999997
	if math.Abs(float64(loss_val)-expectedLoss) > 1e-5 {
		t.Errorf("Loss value incorrect: actual %f, expected %f", loss_val, expectedLoss)
	}

	expectedGrad := []float32 { 1.2499998, 0.24999973, 0.24999973, 1.2499998 }
	if euclideanDist(g.Data(), expectedGrad) > 1e-5 {
		t.Errorf("Gradient incorrect: actual %v, expected %v", g.Data(), expectedGrad)
	}

	h.Set(0, 0.0)
	h.Set(1, 1.0)
	h.Set(2, 1.0)
	h.Set(3, 0.0)

	loss_val = kld_loss.Evaluate(h, g)

	fmt.Println("loss val is ", loss_val)
	fmt.Println("gradient is ", g)

	expectedLoss = 3.6931434
	if math.Abs(float64(loss_val)-expectedLoss) > 1e-5 {
		t.Errorf("Loss value incorrect: actual %f, expected %f", loss_val, expectedLoss)
	}

	expectedGrad = []float32 { 1, 0, 0, 1 }
	if euclideanDist(g.Data(), expectedGrad) > 1e-5 {
		t.Errorf("Gradient incorrect: actual %v, expected %v", g.Data(), expectedGrad)
	}
}

func newKLDivLoss() *KLDivLoss {
	m := uint32(3)
	n := uint32(2)
	k := uint32(2)

	// v is
	// -------------
	// | 0.0 | 1.0 |
	// |-----|-----|
	// | 1.0 | 0.0 |
	// |-----|-----|
	// | 0.5 | 0.5 |
	// |-----|-----|
	v := &pb.MatrixShard{
		IsSparse: true,
		M: 2,
		N: 3,
		Val: []float32 {1.0, 1.0, 0.5, 0.5},
		Ir: []uint32 {1, 0, 0, 1},
		Jc: []uint32 {0, 1, 2, 4},
	}

	// w is composed by two shards:
	//
	// shard 0:
	//  -------------
	//  | 1.0 | 0.0 |
	//  -------------
	//  | 0.0 | 1.0 |
	//  -------------
	// and shard 1:
	//  -------------
	//  | 0.5 | 0.5 |
	//  -------------
	//
	w := []*pb.MatrixShard{
		&pb.MatrixShard{
			M: 2,
			N: n,
			Val: []float32 {1.0, 0.0, 0.0, 1.0},
		},
		&pb.MatrixShard{
			M: 1,
			N: n,
			Val: []float32 {0.5, 0.5},
		},
	}

	return NewKLDivLoss(v, w, m, n, k, 1e-6)
}

func euclideanDist(x, y []float32) float64 {
	if len(x) != len(y) {
		return math.Inf(1)
	}

	val := 0.0

	for i, xi := range x {
		val += float64((xi-y[i])*(xi-y[i]))
	}
	return val
}
<|endoftext|>


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

package handler

import (
	"http"
	"server/tmpl"
)

// This is like FarmVille, but it actually works.
func LawnVille(w http.ResponseWriter, r *http.Request) {
	tmpl.TemplateSet.Execute(w, "Lawnville", nil)
}

//from google.appengine.ext import webapp
//
//from irrduinoserver.utils import web as webutils
//from irrduinoserver.utils import irrduino as irrduinoutils
//
//
//class LawnVilleHandler(webapp.RequestHandler):
//  def get(self):
//    template_params = {}
//    template_params["zones"] = sorted(irrduinoutils.ZONES.items())
//    webutils.render_to_response(self, "lawnville.html", template_params)
<commit_msg>Misspelled<commit_after>// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package handler

import (
	"http"
	"server/tmpl"
)

// This is like FarmVille, but it actually works.
func LawnVille(w http.ResponseWriter, r *http.Request) {
	tmpl.TemplateSet.Execute(w, "LawnVille", nil)
}

//from google.appengine.ext import webapp
//
//from irrduinoserver.utils import web as webutils
//from irrduinoserver.utils import irrduino as irrduinoutils
//
//
//class LawnVilleHandler(webapp.RequestHandler):
//  def get(self):
//    template_params = {}
//    template_params["zones"] = sorted(irrduinoutils.ZONES.items())
//    webutils.render_to_response(self, "lawnville.html", template_params)
<|endoftext|>


<commit_before>package heppdt_test

import (
	"testing"

	"github.com/go-hep/heppdt"
)

func TestPID(t *testing.T) {
	/*
	ids := []int{ 5, 25, 15, 213, -3214, 10213, 9050225, -200543, 129050225,
		2000025, 3101, 3301, -2212, 1000020040, -1000060120, 555,
		5000040, 5100005, 24, 5100024, 5100025, 9221132,
		4111370, -4120240, 4110050, 10013730,
		1000993, 1000612, 1000622, 1000632, 1006213, 1000652,
		1009113, 1009213, 1009323,
		1093114, 1009333, 1006313, 1092214, 1006223,
	}
	*/

	for _, table := range []struct{
		id int
		nx, nr, n1, nq1, nq2, nq3, nj int
		extra int
		jspin, lspin, spin int
		fid int
		charge float64
		valid bool

		ishadron, ismeson,isrhadron,isbaryon bool
		islepton, isdiquark, isnucleus bool

		issusy, isdyon, isqlb, isunknown bool

		hasup, hasdown, hasstrange, hascharm, hasbottom, hastop bool
	}{
		{
			id: 5,
			nx: 0, nr:0, n1:0, nq1:0, nq2:0, nq3:0, nj:5,
			extra: 0,
			jspin: 2, lspin:0, spin:0,
			fid: 0,
			charge: -1./3.,
			valid: true,
			isqlb: true,
		},
		{
			id: 25,
			nx: 0, nr:0, n1:0, nq1:0, nq2:0, nq3:2, nj:5,
			extra: 0,
			jspin: 0, lspin:0, spin:0,
			fid: 0,
			charge: 0,
			valid: true,
			isqlb: true,
		},
	} {
		id := table.id
		pid := heppdt.PID(id)
		nx := pid.Digit(heppdt.N)
		if nx != table.nx {
			t.Fatalf("pid=%d. expected nx=%d. got=%d", id, table.nx, nx)
		}

		nr := pid.Digit(heppdt.Nr)
		if nr != table.nr {
			t.Fatalf("pid=%d. expected nr=%d. got=%d", id, table.nr, nr)
		}

		nq1 := pid.Digit(heppdt.Nq1)
		if nq1 != table.nq1 {
			t.Fatalf("pid=%d. expected nq1=%d. got=%d", id, table.nq1, nq1)
		}

		nq2 := pid.Digit(heppdt.Nq2)
		if nq2 != table.nq2 {
			t.Fatalf("pid=%d. expected nq2=%d. got=%d", id, table.nq2, nq2)
		}

		nq3 := pid.Digit(heppdt.Nq3)
		if nq3 != table.nq3 {
			t.Fatalf("pid=%d. expected nq3=%d. got=%d", id, table.nq3, nq3)
		}

		extra := pid.ExtraBits()
		if extra != table.extra {
			t.Fatalf("pid=%d. expected extra=%d. got=%d", id, table.extra, extra)
		}

		jspin := pid.JSpin()
		if jspin != table.jspin {
			t.Fatalf("pid=%d. expected jspin=%d. got=%d", id, table.jspin, jspin)
		}

		lspin := pid.LSpin()
		if lspin != table.lspin {
			t.Fatalf("pid=%d. expected lspin=%d. got=%d", id, table.lspin, lspin)
		}

		spin := pid.SSpin()
		if spin != table.spin {
			t.Fatalf("pid=%d. expected sspin=%d. got=%d", id, table.spin, spin)
		}

		charge := pid.Charge()
		if charge != table.charge {
			t.Fatalf("pid=%d. expected charge=%v. got=%v", id, table.charge, charge)
		}

		if pid.IsValid() != table.valid {
			t.Fatalf("expected pid=%d valid=%v. got=%v", int(pid), table.valid, pid.IsValid())
		}

		if table.ishadron != pid.IsHadron() {
			t.Fatalf("expected pid=%d ishadron=%v. got=%v", int(pid), table.ishadron, pid.IsHadron())
		}

		if table.ismeson != pid.IsMeson() {
			t.Fatalf("expected pid=%d ismeson=%v. got=%v", int(pid), table.ismeson, pid.IsMeson())
		}

		if table.isrhadron != pid.IsRhadron() {
			t.Fatalf("expected pid=%d isrhadron=%v. got=%v", int(pid), table.isrhadron, pid.IsRhadron())
		}

		if table.isbaryon != pid.IsBaryon() {
			t.Fatalf("expected pid=%d isbaryon=%v. got=%v", int(pid), table.isbaryon, pid.IsBaryon())
		}

		if table.islepton != pid.IsLepton() {
			t.Fatalf("expected pid=%d islepton=%v. got=%v", int(pid), table.islepton, pid.IsLepton())
		}

		if table.isdiquark != pid.IsDiQuark() {
			t.Fatalf("expected pid=%d isdiquark=%v. got=%v", int(pid), table.isdiquark, pid.IsDiQuark())
		}

		if table.isnucleus != pid.IsNucleus() {
			t.Fatalf("expected pid=%d isnucleus=%v. got=%v", int(pid), table.isnucleus, pid.IsNucleus())
		}

		if table.issusy != pid.IsSUSY() {
			t.Fatalf("expected pid=%d issusy=%v. got=%v", int(pid), table.issusy, pid.IsSUSY())
		}

		if table.isdyon != pid.IsDyon() {
			t.Fatalf("expected pid=%d isdyon=%v. got=%v", int(pid), table.isdyon, pid.IsDyon())
		}

		if table.isqlb != (pid.AbsPID() < 100) {
			t.Fatalf("expected pid=%d is-quark/lepton/boson=%v. got=%v", int(pid), table.isqlb, pid.AbsPID() < 100)
		}

		if table.isunknown != (!pid.IsSUSY() && !pid.IsDyon() && !pid.IsHadron() &&
			!pid.IsLepton()	&& !pid.IsDiQuark() && !pid.IsNucleus() &&
			!(pid.AbsPID() < 100)) {
			t.Fatalf("expected pid=%d isunknown=%v. got=%v", int(pid), table.isunknown, !table.isunknown)
		}

		if table.hasup != pid.HasUp() {
			t.Fatalf("expected pid=%d has=%v. got=%v", int(pid), table.hasup, pid.HasUp())
		}

		if table.hasdown != pid.HasDown() {
			t.Fatalf("expected pid=%d hasdown=%v. got=%v", int(pid), table.hasdown, pid.HasDown())
		}

		if table.hasstrange != pid.HasStrange() {
			t.Fatalf("expected pid=%d hasstrange=%v. got=%v", int(pid), table.hasstrange, pid.HasStrange())
		}

		if table.hascharm != pid.HasCharm() {
			t.Fatalf("expected pid=%d hascharm=%v. got=%v", int(pid), table.hascharm, pid.HasCharm())
		}

		if table.hasbottom != pid.HasBottom() {
			t.Fatalf("expected pid=%d hasbottom=%v. got=%v", int(pid), table.hasbottom, pid.HasBottom())
		}

		if table.hastop != pid.HasTop() {
			t.Fatalf("expected pid=%d hastop=%v. got=%v", int(pid), table.hastop, pid.HasTop())
		}
	}
}
<commit_msg>test: pid-15<commit_after>package heppdt_test

import (
	"testing"

	"github.com/go-hep/heppdt"
)

func TestPID(t *testing.T) {
	/*
	ids := []int{ 5, 25, 15, 213, -3214, 10213, 9050225, -200543, 129050225,
		2000025, 3101, 3301, -2212, 1000020040, -1000060120, 555,
		5000040, 5100005, 24, 5100024, 5100025, 9221132,
		4111370, -4120240, 4110050, 10013730,
		1000993, 1000612, 1000622, 1000632, 1006213, 1000652,
		1009113, 1009213, 1009323,
		1093114, 1009333, 1006313, 1092214, 1006223,
	}
	*/

	for _, table := range []struct{
		id int
		nx, nr, n1, nq1, nq2, nq3, nj int
		extra int
		jspin, lspin, spin int
		fid int
		charge float64
		valid bool

		ishadron, ismeson,isrhadron,isbaryon bool
		islepton, isdiquark, isnucleus bool

		issusy, isdyon, isqlb, isunknown bool

		hasup, hasdown, hasstrange, hascharm, hasbottom, hastop bool
	}{
		{
			id: 5,
			nx: 0, nr:0, n1:0, nq1:0, nq2:0, nq3:0, nj:5,
			extra: 0,
			jspin: 2, lspin:0, spin:0,
			fid: 0,
			charge: -1./3.,
			valid: true,
			isqlb: true,
		},
		{
			id: 25,
			nx: 0, nr:0, n1:0, nq1:0, nq2:0, nq3:2, nj:5,
			extra: 0,
			jspin: 0, lspin:0, spin:0,
			fid: 0,
			charge: 0,
			valid: true,
			isqlb: true,
		},
		{
			id: 15,
			nx: 0, nr:0, n1:0, nq1:0, nq2:0, nq3:1, nj:5,
			extra: 0,
			jspin: 2, lspin:0, spin:0,
			fid: 0,
			charge: -1,
			valid: true,
			isqlb: true,
			islepton: true,
		},
	} {
		id := table.id
		pid := heppdt.PID(id)
		nx := pid.Digit(heppdt.N)
		if nx != table.nx {
			t.Fatalf("pid=%d. expected nx=%d. got=%d", id, table.nx, nx)
		}

		nr := pid.Digit(heppdt.Nr)
		if nr != table.nr {
			t.Fatalf("pid=%d. expected nr=%d. got=%d", id, table.nr, nr)
		}

		nq1 := pid.Digit(heppdt.Nq1)
		if nq1 != table.nq1 {
			t.Fatalf("pid=%d. expected nq1=%d. got=%d", id, table.nq1, nq1)
		}

		nq2 := pid.Digit(heppdt.Nq2)
		if nq2 != table.nq2 {
			t.Fatalf("pid=%d. expected nq2=%d. got=%d", id, table.nq2, nq2)
		}

		nq3 := pid.Digit(heppdt.Nq3)
		if nq3 != table.nq3 {
			t.Fatalf("pid=%d. expected nq3=%d. got=%d", id, table.nq3, nq3)
		}

		extra := pid.ExtraBits()
		if extra != table.extra {
			t.Fatalf("pid=%d. expected extra=%d. got=%d", id, table.extra, extra)
		}

		jspin := pid.JSpin()
		if jspin != table.jspin {
			t.Fatalf("pid=%d. expected jspin=%d. got=%d", id, table.jspin, jspin)
		}

		lspin := pid.LSpin()
		if lspin != table.lspin {
			t.Fatalf("pid=%d. expected lspin=%d. got=%d", id, table.lspin, lspin)
		}

		spin := pid.SSpin()
		if spin != table.spin {
			t.Fatalf("pid=%d. expected sspin=%d. got=%d", id, table.spin, spin)
		}

		charge := pid.Charge()
		if charge != table.charge {
			t.Fatalf("pid=%d. expected charge=%v. got=%v", id, table.charge, charge)
		}

		if pid.IsValid() != table.valid {
			t.Fatalf("expected pid=%d valid=%v. got=%v", int(pid), table.valid, pid.IsValid())
		}

		if table.ishadron != pid.IsHadron() {
			t.Fatalf("expected pid=%d ishadron=%v. got=%v", int(pid), table.ishadron, pid.IsHadron())
		}

		if table.ismeson != pid.IsMeson() {
			t.Fatalf("expected pid=%d ismeson=%v. got=%v", int(pid), table.ismeson, pid.IsMeson())
		}

		if table.isrhadron != pid.IsRhadron() {
			t.Fatalf("expected pid=%d isrhadron=%v. got=%v", int(pid), table.isrhadron, pid.IsRhadron())
		}

		if table.isbaryon != pid.IsBaryon() {
			t.Fatalf("expected pid=%d isbaryon=%v. got=%v", int(pid), table.isbaryon, pid.IsBaryon())
		}

		if table.islepton != pid.IsLepton() {
			t.Fatalf("expected pid=%d islepton=%v. got=%v", int(pid), table.islepton, pid.IsLepton())
		}

		if table.isdiquark != pid.IsDiQuark() {
			t.Fatalf("expected pid=%d isdiquark=%v. got=%v", int(pid), table.isdiquark, pid.IsDiQuark())
		}

		if table.isnucleus != pid.IsNucleus() {
			t.Fatalf("expected pid=%d isnucleus=%v. got=%v", int(pid), table.isnucleus, pid.IsNucleus())
		}

		if table.issusy != pid.IsSUSY() {
			t.Fatalf("expected pid=%d issusy=%v. got=%v", int(pid), table.issusy, pid.IsSUSY())
		}

		if table.isdyon != pid.IsDyon() {
			t.Fatalf("expected pid=%d isdyon=%v. got=%v", int(pid), table.isdyon, pid.IsDyon())
		}

		if table.isqlb != (pid.AbsPID() < 100) {
			t.Fatalf("expected pid=%d is-quark/lepton/boson=%v. got=%v", int(pid), table.isqlb, pid.AbsPID() < 100)
		}

		if table.isunknown != (!pid.IsSUSY() && !pid.IsDyon() && !pid.IsHadron() &&
			!pid.IsLepton()	&& !pid.IsDiQuark() && !pid.IsNucleus() &&
			!(pid.AbsPID() < 100)) {
			t.Fatalf("expected pid=%d isunknown=%v. got=%v", int(pid), table.isunknown, !table.isunknown)
		}

		if table.hasup != pid.HasUp() {
			t.Fatalf("expected pid=%d has=%v. got=%v", int(pid), table.hasup, pid.HasUp())
		}

		if table.hasdown != pid.HasDown() {
			t.Fatalf("expected pid=%d hasdown=%v. got=%v", int(pid), table.hasdown, pid.HasDown())
		}

		if table.hasstrange != pid.HasStrange() {
			t.Fatalf("expected pid=%d hasstrange=%v. got=%v", int(pid), table.hasstrange, pid.HasStrange())
		}

		if table.hascharm != pid.HasCharm() {
			t.Fatalf("expected pid=%d hascharm=%v. got=%v", int(pid), table.hascharm, pid.HasCharm())
		}

		if table.hasbottom != pid.HasBottom() {
			t.Fatalf("expected pid=%d hasbottom=%v. got=%v", int(pid), table.hasbottom, pid.HasBottom())
		}

		if table.hastop != pid.HasTop() {
			t.Fatalf("expected pid=%d hastop=%v. got=%v", int(pid), table.hastop, pid.HasTop())
		}
	}
}
<|endoftext|>


<commit_before>package core

import (
	"time"

	"github.com/go-ole/go-ole"
)

// NamingContext represents an active directory naming context.
type NamingContext struct {
	ID          *ole.GUID
	DN          string // Distinguished name
	Description string
	Path        string
}

// Domain contains the replication group information for an Active Directory
// domain.
type Domain struct {
	NamingContext
	Groups         []Group
	ConfigDuration time.Duration // Time elapsed while retrieving configuration
}

// Group represents a replication group.
type Group struct {
	Name           string
	ID             *ole.GUID
	Folders        []Folder
	Members        []Member
	ConfigDuration time.Duration // Time elapsed while retrieving configuration
}

// Folder represents a replication folder.
type Folder struct {
	Name string
	ID   *ole.GUID
}

// Member represents a replication member.
type Member struct {
	MemberInfo
	Connections []Connection
}

// MemberInfo represents identifying information about a replication member.
type MemberInfo struct {
	Name     string
	ID       *ole.GUID
	Computer Computer
	DN       string // Distinguished name of the member
}

// Computer represents information about a computer.
type Computer struct {
	DN   string // Distinguished name
	Host string
}

// Connection represents a one-way connection between replication members.
type Connection struct {
	Name     string
	ID       *ole.GUID
	MemberDN string
	Enabled  bool
	Computer Computer // Distinguished name of source member in topology, matches DN field of that Member
}

// Backlog represents the backlog from one DFSR member to another.
type Backlog struct {
	Group    *Group
	From     string
	To       string
	Backlog  []int
	Err      error
	Duration time.Duration // Wall time for backlog calculation
}
<commit_msg>Added timestamp to core.Backlog<commit_after>package core

import (
	"time"

	"github.com/go-ole/go-ole"
)

// NamingContext represents an active directory naming context.
type NamingContext struct {
	ID          *ole.GUID
	DN          string // Distinguished name
	Description string
	Path        string
}

// Domain contains the replication group information for an Active Directory
// domain.
type Domain struct {
	NamingContext
	Groups         []Group
	ConfigDuration time.Duration // Time elapsed while retrieving configuration
}

// Group represents a replication group.
type Group struct {
	Name           string
	ID             *ole.GUID
	Folders        []Folder
	Members        []Member
	ConfigDuration time.Duration // Time elapsed while retrieving configuration
}

// Folder represents a replication folder.
type Folder struct {
	Name string
	ID   *ole.GUID
}

// Member represents a replication member.
type Member struct {
	MemberInfo
	Connections []Connection
}

// MemberInfo represents identifying information about a replication member.
type MemberInfo struct {
	Name     string
	ID       *ole.GUID
	Computer Computer
	DN       string // Distinguished name of the member
}

// Computer represents information about a computer.
type Computer struct {
	DN   string // Distinguished name
	Host string
}

// Connection represents a one-way connection between replication members.
type Connection struct {
	Name     string
	ID       *ole.GUID
	MemberDN string
	Enabled  bool
	Computer Computer // Distinguished name of source member in topology, matches DN field of that Member
}

// Backlog represents the backlog from one DFSR member to another.
type Backlog struct {
	Group     *Group
	From      string
	To        string
	Backlog   []int
	Timestamp time.Time
	Duration  time.Duration // Wall time for backlog calculation
	Err       error
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"time"

	"gopkg.in/v2/yaml"
)

var (
	// 用于截取当前IP，放在全局变量是为了不用多次解析正则
	ipRegexp = regexp.MustCompile(`<code>([^\n]+)</code>`)
)

func main() {
	// 读配置文件
	buf, err := ioutil.ReadFile("config.yaml")
	if err != nil {
		printError("readConfig", err)
		os.Exit(1)
	}
	var config = new(configType)
	err = yaml.Unmarshal(buf, config)
	if err != nil {
		printError("unmarshalConfig", err)
		os.Exit(1)
	}

	var domainList = new(domainListType)
	err = postMsg("https://dnsapi.cn/Domain.List", url.Values{
		"login_email":    {config.Email},
		"login_password": {config.Password},
		"format":         {"json"},
		"lang":           {"cn"},
	}, domainList)
	if err != nil {
		printError("getDomainList", err)
		os.Exit(1)
	}

	// 检查错误
	if domainList.Status.Code == "1" {
		printInfo("Login", "登录成功")
	} else {
		printError("Login", domainList.Status.Message)
		os.Exit(1)
	}

	// 获取Domain ID
	var domainID string
	for _, v := range domainList.Domains {
		if v.Name == config.Domain {
			domainID = strconv.Itoa(v.ID)
			break
		}
	}
	if domainID == "" {
		printError("DomainID", "账户中不存在此域名")
		printInfo("Domain", "尝试添加此域名到账户，请注意设置域名NS以及验证是否添加成功")
		var info = new(infoType)
		err = postMsg("https://dnsapi.cn/Domain.Create", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain":         {config.Domain},
		}, info)
		if err != nil {
			printError("addDomain", err)
			os.Exit(1)
		}

		// 检查错误
		if info.Status.Code == "1" {
			printInfo("addDomain", "操作成功，请重启程序查看是否可用")
			// 操作成功，退出程序
			os.Exit(0)
		} else {
			printError("addDomain", info.Status.Message)
			os.Exit(1)
		}
	}
	printInfo("DomainID", domainID)

	var recordList = new(recordListType)
	err = postMsg("https://dnsapi.cn/Record.List", url.Values{
		"login_email":    {config.Email},
		"login_password": {config.Password},
		"format":         {"json"},
		"lang":           {"cn"},
		"domain_id":      {domainID},
	}, recordList)
	if err != nil {
		printError("getRecordList", err)
		os.Exit(1)
	}

	// 检查错误
	if recordList.Status.Code != "1" {
		printError("getRecordList", recordList.Status.Message)
		os.Exit(1)
	}

	// 获取Record ID
	var recordID string
	for _, v := range recordList.Records {
		// 获取相同子域名，类型为A记录，线路为默认的记录ID
		if v.Name == config.SubDomain && v.Type == "A" && v.Line == "默认" {
			recordID = v.ID
			break
		}
	}
	if recordID == "" {
		printError("RecordID", "域名中不存在此子域名或此子域名不存在默认线路的A记录")
		printInfo("SubDomain", "尝试添加此子域名A记录")
		// 获取当前IP
		ip, err := getIP()
		if err != nil {
			printError("getIP", err)
		}
		var info = new(infoType)
		err = postMsg("https://dnsapi.cn/Record.Create", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain_id":      {domainID},
			"sub_domain":     {config.SubDomain},
			"record_type":    {"A"},
			"record_line":    {"默认"},
			"value":          {ip},
		}, info)
		if err != nil {
			printError("addSubDomain", err)
			os.Exit(1)
		}

		// 检查错误
		if info.Status.Code == "1" {
			printInfo("addSubDomain", "操作成功，请重启程序查看是否可用")
			// 操作成功，退出程序
			os.Exit(0)
		} else {
			printError("addSubDomain", info.Status.Message)
			os.Exit(1)
		}
	}
	printInfo("RecordID", recordID)

	// 循环检测IP与设置DNS
	// 一旦出现error则直接结束本次循环
	// 进入sleep等待下一次循环
	for {
		// 获取记录的IP
		var recordInfo = new(recordInfoType)
		err = postMsg("https://dnsapi.cn/Record.Info", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain_id":      {domainID},
			"record_id":      {recordID},
		}, recordInfo)
		if err != nil {
			printError("getRecordInfo", err)
		} else {
			// 检查错误
			if recordInfo.Status.Code != "1" {
				printError("getRecordInfo", recordInfo.Status.Message)
			} else {
				// 获取当前IP
				ip, err := getIP()
				if err != nil {
					printError("getIP", err)
				} else {
					// 检查DNS记录的IP是否和当前IP相同
					if ip != recordInfo.Record.Value {
						printInfo("IP", recordInfo.Record.Value, "==>", ip, "IP变更，自动更新DNS")
						// 设置动态DNS
						var recordModify = new(recordModifyType)
						err = postMsg("https://dnsapi.cn/Record.Ddns", url.Values{
							"login_email":    {config.Email},
							"login_password": {config.Password},
							"format":         {"json"},
							"lang":           {"cn"},
							"domain_id":      {domainID},
							"record_id":      {recordID},
							"sub_domain":     {config.SubDomain},
							"record_line":    {"默认"},
						}, recordModify)
						if err != nil {
							printError("recordModify", err)
						} else {
							// 检查错误
							if recordModify.Status.Code == "1" {
								printInfo("IP", "DNS更新完成")
							} else {
								printError("recordModify", recordModify.Status.Message)
							}
						}
					} else {
						printInfo("IP", "没有检测到IP变更。下次检查时间：", config.CheckTime, "后")
					}
				}
			}
		}

		time.Sleep(time.Second * config.CheckTime)
	}
}

func postMsg(u string, msg url.Values, value interface{}) error {
	getDomainList, err := http.PostForm(u, msg)
	if err != nil {
		return err
	}
	defer getDomainList.Body.Close()

	buf, err := ioutil.ReadAll(getDomainList.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(buf, value)
	if err != nil {
		return err
	}

	return nil
}

func printInfo(s string, v ...interface{}) {
	log.Println(append([]interface{}{"[INFO]", s + ":"}, v...)...)
}

func printError(s string, v ...interface{}) {
	log.Println(append([]interface{}{"[ERROR]", s + ":"}, v...)...)
}

func getIP() (string, error) {
	resp, err := http.Get("http://ip.cn")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	// 提取IP地址
	buf := ipRegexp.FindSubmatch(body)
	// 页面内不存在IP地址
	if len(buf) == 0 {
		return "", errors.New("服务器错误，无法获取当前ip")
	}

	return string(buf[1]), nil
}

type configType struct {
	Email     string        `yaml:"Email"`
	Password  string        `yaml:"Password"`
	Domain    string        `yaml:"Domain"`
	SubDomain string        `yaml:"SubDomain"`
	CheckTime time.Duration `yaml:"CheckTime"`
}

type domainListType struct {
	Status  statusType   `json:"status"`
	Info    struct{}     `json:"info"`
	Domains []domainType `json:"domains"`
}

type recordListType struct {
	Status  statusType   `json:"status"`
	Info    struct{}     `json:"info"`
	Domain  domainType   `json:"domain"`
	Records []recordType `json:"records"`
}

type infoType struct {
	Status statusType `json:"status"`
	Record recordType `json:"record"`
}

type recordInfoType struct {
	Status statusType `json:"status"`
	Domain domainType `json:"domain"`
	Record recordType `json:"record"`
}

// 这里单独一个而不用上面那个infoType的原因是
// DNSPod的动态DNS API里返回的Record ID
// 竟然和别的API里的不一样
// 是int而不是string
type recordModifyType struct {
	Status statusType `json:"status"`
	Record struct {
		ID    int    `json:"id"`
		Name  string `json:"name"`
		Value string `json:"value"`
	} `json:"record"`
}

type statusType struct {
	Code      string `json:"code"`
	Message   string `json:"message"`
	CreatedAt string `json:"created_at"`
}

type domainType struct {
	ID               int    `json:"id"`
	Name             string `json:"name"`
	Grade            string `json:"grade"`
	GradeTitle       string `json:"grade_title"`
	ExtStatus        string `json:"ext_status"`
	Records          string `json:"records"`
	GroupID          string `json:"group_id"`
	IsMark           string `json:"is_mark"`
	Remark           string `json:"remark"`
	IsVIP            string `json:"is_vip"`
	SearchenginePush string `json:"searchengine_push"`
	Beian            string `json:"beian"`
	CreatedOn        string `json:"created_on"`
	UpdatedOn        string `json:"updated_on"`
	TTL              string `json:"ttl"`
	Owner            string `json:"owner"`
}

type recordType struct {
	ID            string `json:"id"`
	Name          string `json:"name"`
	Line          string `json:"line"`
	Type          string `json:"type"`
	TTL           string `json:"ttl"`
	Value         string `json:"value"`
	MX            string `json:"mx"`
	Enabled       string `json:"enabled"`
	Status        string `json:"status"`
	MonitorStatus string `json:"monitor_status"`
	Remark        string `json:"remark"`
	UpdatedOn     string `json:"updated_on"`
	Hold          string `json:"hold"`
}
<commit_msg>添加获取IP备用方式<commit_after>package main

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"time"

	"gopkg.in/v2/yaml"
)

var (
	// 用于截取当前IP，放在全局变量是为了不用多次解析正则
	ipRegexp = regexp.MustCompile(`<code>([^\n]+)</code>`)
)

func main() {
	// 读配置文件
	buf, err := ioutil.ReadFile("config.yaml")
	if err != nil {
		printError("readConfig", err)
		os.Exit(1)
	}
	var config = new(configType)
	err = yaml.Unmarshal(buf, config)
	if err != nil {
		printError("unmarshalConfig", err)
		os.Exit(1)
	}

	var domainList = new(domainListType)
	err = postMsg("https://dnsapi.cn/Domain.List", url.Values{
		"login_email":    {config.Email},
		"login_password": {config.Password},
		"format":         {"json"},
		"lang":           {"cn"},
	}, domainList)
	if err != nil {
		printError("getDomainList", err)
		os.Exit(1)
	}

	// 检查错误
	if domainList.Status.Code == "1" {
		printInfo("Login", "登录成功")
	} else {
		printError("Login", domainList.Status.Message)
		os.Exit(1)
	}

	// 获取Domain ID
	var domainID string
	for _, v := range domainList.Domains {
		if v.Name == config.Domain {
			domainID = strconv.Itoa(v.ID)
			break
		}
	}
	if domainID == "" {
		printError("DomainID", "账户中不存在此域名")
		printInfo("Domain", "尝试添加此域名到账户，请注意设置域名NS以及验证是否添加成功")
		var info = new(infoType)
		err = postMsg("https://dnsapi.cn/Domain.Create", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain":         {config.Domain},
		}, info)
		if err != nil {
			printError("addDomain", err)
			os.Exit(1)
		}

		// 检查错误
		if info.Status.Code == "1" {
			printInfo("addDomain", "操作成功，请重启程序查看是否可用")
			// 操作成功，退出程序
			os.Exit(0)
		} else {
			printError("addDomain", info.Status.Message)
			os.Exit(1)
		}
	}
	printInfo("DomainID", domainID)

	var recordList = new(recordListType)
	err = postMsg("https://dnsapi.cn/Record.List", url.Values{
		"login_email":    {config.Email},
		"login_password": {config.Password},
		"format":         {"json"},
		"lang":           {"cn"},
		"domain_id":      {domainID},
	}, recordList)
	if err != nil {
		printError("getRecordList", err)
		os.Exit(1)
	}

	// 检查错误
	if recordList.Status.Code != "1" {
		printError("getRecordList", recordList.Status.Message)
		os.Exit(1)
	}

	// 获取Record ID
	var recordID string
	for _, v := range recordList.Records {
		// 获取相同子域名，类型为A记录，线路为默认的记录ID
		if v.Name == config.SubDomain && v.Type == "A" && v.Line == "默认" {
			recordID = v.ID
			break
		}
	}
	if recordID == "" {
		printError("RecordID", "域名中不存在此子域名或此子域名不存在默认线路的A记录")
		printInfo("SubDomain", "尝试添加此子域名A记录")
		// 获取当前IP
		ip, err := getIP()
		if err != nil {
			printError("getIP", err)
		}
		var info = new(infoType)
		err = postMsg("https://dnsapi.cn/Record.Create", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain_id":      {domainID},
			"sub_domain":     {config.SubDomain},
			"record_type":    {"A"},
			"record_line":    {"默认"},
			"value":          {ip},
		}, info)
		if err != nil {
			printError("addSubDomain", err)
			os.Exit(1)
		}

		// 检查错误
		if info.Status.Code == "1" {
			printInfo("addSubDomain", "操作成功，请重启程序查看是否可用")
			// 操作成功，退出程序
			os.Exit(0)
		} else {
			printError("addSubDomain", info.Status.Message)
			os.Exit(1)
		}
	}
	printInfo("RecordID", recordID)

	// 循环检测IP与设置DNS
	// 一旦出现error则直接结束本次循环
	// 进入sleep等待下一次循环
	for {
		// 获取记录的IP
		var recordInfo = new(recordInfoType)
		err = postMsg("https://dnsapi.cn/Record.Info", url.Values{
			"login_email":    {config.Email},
			"login_password": {config.Password},
			"format":         {"json"},
			"lang":           {"cn"},
			"domain_id":      {domainID},
			"record_id":      {recordID},
		}, recordInfo)
		if err != nil {
			printError("getRecordInfo", err)
		} else {
			// 检查错误
			if recordInfo.Status.Code != "1" {
				printError("getRecordInfo", recordInfo.Status.Message)
			} else {
				// 获取当前IP
				ip, err := getIP()
				if err != nil {
					printError("getIP", err)
				} else {
					// 检查DNS记录的IP是否和当前IP相同
					if ip != recordInfo.Record.Value {
						printInfo("IP", recordInfo.Record.Value, "==>", ip, "IP变更，自动更新DNS")
						// 设置动态DNS
						var recordModify = new(recordModifyType)
						err = postMsg("https://dnsapi.cn/Record.Ddns", url.Values{
							"login_email":    {config.Email},
							"login_password": {config.Password},
							"format":         {"json"},
							"lang":           {"cn"},
							"domain_id":      {domainID},
							"record_id":      {recordID},
							"sub_domain":     {config.SubDomain},
							"record_line":    {"默认"},
						}, recordModify)
						if err != nil {
							printError("recordModify", err)
						} else {
							// 检查错误
							if recordModify.Status.Code == "1" {
								printInfo("IP", "DNS更新完成")
							} else {
								printError("recordModify", recordModify.Status.Message)
							}
						}
					} else {
						printInfo("IP", "没有检测到IP变更。下次检查时间：", config.CheckTime, "后")
					}
				}
			}
		}

		time.Sleep(time.Second * config.CheckTime)
	}
}

func postMsg(u string, msg url.Values, value interface{}) error {
	getDomainList, err := http.PostForm(u, msg)
	if err != nil {
		return err
	}
	defer getDomainList.Body.Close()

	buf, err := ioutil.ReadAll(getDomainList.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(buf, value)
	if err != nil {
		return err
	}

	return nil
}

func printInfo(s string, v ...interface{}) {
	log.Println(append([]interface{}{"[INFO]", s + ":"}, v...)...)
}

func printError(s string, v ...interface{}) {
	log.Println(append([]interface{}{"[ERROR]", s + ":"}, v...)...)
}

// 获取本机IP
func getIP() (string, error) {
	resp, err := http.Get("http://ns1.dnspod.net:6666")
	if err != nil {
		// 连接到服务器出错
		// 使用备用方式
		ip, err := reGetIP()
		if err != nil {
			return "", err
		}
		return ip, nil
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		// 服务器内部错误
		// 使用备用方式
		ip, err := reGetIP()
		if err != nil {
			return "", err
		}
		return ip, nil
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	return string(body), nil
}

// 备用获取IP方式
func reGetIP() (string, error) {
	// 从ip.cn获取本机IP
	resp, err := http.Get("http://ip.cn")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	// 提取IP地址
	buf := ipRegexp.FindSubmatch(body)
	// 页面内不存在IP地址
	if len(buf) == 0 {
		return "", errors.New("服务器错误，无法获取当前ip")
	}

	return string(buf[1]), nil
}

type configType struct {
	Email     string        `yaml:"Email"`
	Password  string        `yaml:"Password"`
	Domain    string        `yaml:"Domain"`
	SubDomain string        `yaml:"SubDomain"`
	CheckTime time.Duration `yaml:"CheckTime"`
}

type domainListType struct {
	Status  statusType   `json:"status"`
	Info    struct{}     `json:"info"`
	Domains []domainType `json:"domains"`
}

type recordListType struct {
	Status  statusType   `json:"status"`
	Info    struct{}     `json:"info"`
	Domain  domainType   `json:"domain"`
	Records []recordType `json:"records"`
}

type infoType struct {
	Status statusType `json:"status"`
	Record recordType `json:"record"`
}

type recordInfoType struct {
	Status statusType `json:"status"`
	Domain domainType `json:"domain"`
	Record recordType `json:"record"`
}

// 这里单独一个而不用上面那个infoType的原因是
// DNSPod的动态DNS API里返回的Record ID
// 竟然和别的API里的不一样
// 是int而不是string
type recordModifyType struct {
	Status statusType `json:"status"`
	Record struct {
		ID    int    `json:"id"`
		Name  string `json:"name"`
		Value string `json:"value"`
	} `json:"record"`
}

type statusType struct {
	Code      string `json:"code"`
	Message   string `json:"message"`
	CreatedAt string `json:"created_at"`
}

type domainType struct {
	ID               int    `json:"id"`
	Name             string `json:"name"`
	Grade            string `json:"grade"`
	GradeTitle       string `json:"grade_title"`
	ExtStatus        string `json:"ext_status"`
	Records          string `json:"records"`
	GroupID          string `json:"group_id"`
	IsMark           string `json:"is_mark"`
	Remark           string `json:"remark"`
	IsVIP            string `json:"is_vip"`
	SearchenginePush string `json:"searchengine_push"`
	Beian            string `json:"beian"`
	CreatedOn        string `json:"created_on"`
	UpdatedOn        string `json:"updated_on"`
	TTL              string `json:"ttl"`
	Owner            string `json:"owner"`
}

type recordType struct {
	ID            string `json:"id"`
	Name          string `json:"name"`
	Line          string `json:"line"`
	Type          string `json:"type"`
	TTL           string `json:"ttl"`
	Value         string `json:"value"`
	MX            string `json:"mx"`
	Enabled       string `json:"enabled"`
	Status        string `json:"status"`
	MonitorStatus string `json:"monitor_status"`
	Remark        string `json:"remark"`
	UpdatedOn     string `json:"updated_on"`
	Hold          string `json:"hold"`
}
<|endoftext|>


<commit_before>package AnimeModule

import (
	"fmt"
	"github.com/bwmarrin/discordgo"
	anilistgo "github.com/gendonl/anilist-go"
	"github.com/gendonl/genbot/Bot"
	"strings"
)

func initAniUserInfoCommand() (cc AnimeCommand) {
	cc = AnimeCommand{
		name:        "aniuser",
		description: "Returns AniList information on the provided user",
		usage:       "`%saniuser <name/id>`",
		aliases:	 []string{"m"},
		permission:  discordgo.PermissionSendMessages,
		execute:     (*AnimeModule).AniUserInfoCommand,
	}
	return
}

func (c *AnimeModule) AniUserInfoCommand(cmd AnimeCommand, s *discordgo.Session, m *discordgo.MessageCreate, data *Bot.ServerData) {
	input := strings.SplitN(m.Content, " ", 2)

	if len(input) < 2 {
		result := c.Bot.Usage(cmd, s, m, data)
		s.ChannelMessageSendEmbed(m.ChannelID, result.MessageEmbed)
		return
	}

	userName := input[1]

	query := "query ($search: String) { User (search: $search) " +
		"{ id name avatar {large}  statistics {anime {count episodesWatched} manga {count chaptersRead}} siteUrl } }"
	variables := struct {
		Search string `json:"search"`
	}{
		userName,
	}

	a, _ := anilistgo.New()
	res, err := a.User(query, variables)
	if err != nil {
		s.ChannelMessageSend(m.ChannelID, "Unable to find user with this name.")
		return
	}

	Description := fmt.Sprintf("**Anime Watched:** %d\n **Episodes Watched:** %d\n\n **Manga Read:** %d\n **Chapters Read:** %d\n",
		res.Statistics.Anime.Count, res.Statistics.Anime.EpisodesWatched,
		res.Statistics.Manga.Count, res.Statistics.Manga.ChaptersRead)

	e := Bot.NewEmbed().
		SetColorFromUser(s, m.ChannelID, m.Author).
		SetTitle(res.Name).
		SetDescription(res.About).
		SetThumbnail(res.Avatar.Large).
		SetURL(res.SiteUrl).
		SetDescription(Description)

	s.ChannelMessageSendEmbed(m.ChannelID, e.MessageEmbed)

}
<commit_msg>Add recently watched to aniuser<commit_after>package AnimeModule

import (
	"fmt"
	"github.com/bwmarrin/discordgo"
	anilistgo "github.com/gendonl/anilist-go"
	"github.com/gendonl/genbot/Bot"
	"strings"
)

func initAniUserInfoCommand() (cc AnimeCommand) {
	cc = AnimeCommand{
		name:        "aniuser",
		description: "Returns AniList information on the provided user",
		usage:       "`%saniuser <name/id>`",
		aliases:	 []string{"m"},
		permission:  discordgo.PermissionSendMessages,
		execute:     (*AnimeModule).AniUserInfoCommand,
	}
	return
}

func (c *AnimeModule) AniUserInfoCommand(cmd AnimeCommand, s *discordgo.Session, m *discordgo.MessageCreate, data *Bot.ServerData) {
	input := strings.SplitN(m.Content, " ", 2)

	if len(input) < 2 {
		result := c.Bot.Usage(cmd, s, m, data)
		s.ChannelMessageSendEmbed(m.ChannelID, result.MessageEmbed)
		return
	}

	userName := input[1]

	query := "query ($search: String) { User (search: $search) " +
		"{ id name avatar {large}  statistics {anime {count episodesWatched} manga {count chaptersRead}} siteUrl } }"
	variables := struct {
		Search string `json:"search"`
	}{
		userName,
	}

	a, _ := anilistgo.New()
	res, err := a.User(query, variables)
	if err != nil {
		s.ChannelMessageSend(m.ChannelID, "Unable to find user with this name.")
		return
	}

	query = "query ($userid: Int) { Activity(userId: $userid, sort: ID_DESC) " +
		"{ ... on ListActivity { createdAt status progress media { type title { romaji } }  }  } } "
	variables2 := struct {
		Id int `json:"userid"`
	}{
		res.Id,
	}

	activity, err := a.Activity(query, variables2)
	if err != nil {
		s.ChannelMessageSend(m.ChannelID, "Unable to find user with this name.")
		return
	}

	description := fmt.Sprintf("**Anime Watched:** %d\n **Episodes Watched:** %d\n\n **Manga Read:** %d\n **Chapters Read:** %d\n",
		res.Statistics.Anime.Count, res.Statistics.Anime.EpisodesWatched,
		res.Statistics.Manga.Count, res.Statistics.Manga.ChaptersRead)

	if activity.Status == "completed" {
		description = fmt.Sprintf("%s\n Recently completed the %s **%s**", description,
			strings.ToLower(activity.Media.Type), activity.Media.Title.Romaji)
	} else if activity.Status != "" {
		description = fmt.Sprintf("%s\n Recently %s %s of **%s**", description, activity.Status, activity.Progress,
			activity.Media.Title.Romaji)
	}

	e := Bot.NewEmbed().
		SetColorFromUser(s, m.ChannelID, m.Author).
		SetTitle(res.Name).
		SetDescription(res.About).
		SetThumbnail(res.Avatar.Large).
		SetURL(res.SiteUrl).
		SetDescription(description)

	s.ChannelMessageSendEmbed(m.ChannelID, e.MessageEmbed)

}
<|endoftext|>


<commit_before>package borg

// Think of borg events like inotify events.  We're interested in changes to
// them all.  All events are sent to your instance of borg.  The filtering
// is done once they've arrived.  Let's make keys look like directories to
// aid this comparison.
//
// Example spec:
//
//     /<slug_id>/proc/<type>/<upid>/...
//
// Example interactive session:
//
//     $ borgd -i -a :9999
//     >> ls /proc/123_a3c_a12b3c45/beanstalkd/12345/
//     exe
//     env
//     lock
//     >> cat /proc/123_a3c_a12b3c45/beanstalkd/12345/*
//     beanstalkd -l 0.0.0.0 -p 4563
//     PORT=4563
//     123.4.5.678:9999
//     >>
//
// Example code:
//
//     me, err := borg.ListenAndServe(listenAddr)
//     if err != nil {
//         log.Exitf("listen failed: %v", err)
//     }
//
//     // Handle a specific type of key notification.
//     // The : signals a named variable part.
//     me.HandleFunc(
//         "/proc/:slug/beanstalkd/:upid/lock",
//         func (msg *borg.Message) {
//             if msg.Value == myId {
//                 cmd := beanstalkd ....
//                 ... launch beanstalkd ...
//                 me.Echo(cmd, "/proc/<slug>/beanstalkd/<upid>/cmd")
//             }
//         },
//     )

import (
	"borg/paxos"
	"borg/store"
	"borg/util"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
)

const (
	mSeqn = iota
	mFrom
	mTo
	mCmd
	mBody
	mNumParts
)

// NOT IPv6-compatible.
func getPort(addr string) uint64 {
	parts := strings.Split(addr, ":", -1)
	port, err := strconv.Btoui64(parts[len(parts) - 1], 10)
	if err != nil {
		fmt.Printf("error getting port from %q\n", addr)
	}
	return port
}

func RecvUdp(conn net.PacketConn, ch chan paxos.Msg) {
	for {
		pkt := make([]byte, 3000) // make sure it's big enough
		n, addr, err := conn.ReadFrom(pkt)
		if err != nil {
			fmt.Println(err)
			continue
		}
		msg := parse(string(pkt[0:n]))
		msg.From = getPort(addr.String())
		ch <- msg
	}
}

func parse(s string) paxos.Msg {
	parts := strings.Split(s, ":", mNumParts)
	if len(parts) != mNumParts {
		panic(s)
	}

	seqn, err := strconv.Btoui64(parts[mSeqn], 10)
	if err != nil {
		panic(s)
	}

	from, err := strconv.Btoui64(parts[mFrom], 10)
	if err != nil {
		panic(s)
	}

	var to uint64
	if parts[mTo] == "*" {
		to = 0
	} else {
		to, err = strconv.Btoui64(parts[mTo], 10)
		if err != nil {
			panic(err)
		}
	}

	return paxos.Msg{seqn, from, to, parts[mCmd], parts[mBody]}
}

type FuncPutter func (paxos.Msg)

func (f FuncPutter) Put(m paxos.Msg) {
	f(m)
}

func printMsg(m paxos.Msg) {
	fmt.Printf("should send %v\n", m)
}

func NewUdpPutter(me uint64, addrs []net.Addr, conn net.PacketConn) paxos.Putter {
	put := func(m paxos.Msg) {
		pkt := fmt.Sprintf("%d:%d:%d:%s:%s", m.Seqn, me, m.To, m.Cmd, m.Body)
		fmt.Printf("send udp packet %q\n", pkt)
		b := []byte(pkt)
		var to []net.Addr
		if m.To == 0 {
			to = addrs
		} else {
			to = []net.Addr{&net.UDPAddr{net.ParseIP("127.0.0.1"), int(m.To)}}
		}

		for _, addr := range to {
			n, err := conn.WriteTo(b, addr)
			if err != nil {
				fmt.Println(err)
				continue
			}
			if n != len(b) {
				fmt.Printf("sent <%d> bytes, wanted to send <%d>\n", n, len(b))
				continue
			}
		}
	}
	return FuncPutter(put)
}

type Node struct {
	id string
	listenAddr string
	logger *log.Logger
	nodes []net.Addr
	store *store.Store
	manager *paxos.Manager
}

func New(id string, listenAddr string, logger *log.Logger) *Node {
	if id == "" {
		b := make([]byte, 8)
		util.RandBytes(b)
		id = fmt.Sprintf("%x", b)
	}
	return &Node{
		listenAddr:listenAddr,
		logger:logger,
		store:store.New(logger),
		id:id,
	}
}

func (n *Node) Init() {
	var basePort int
	var err os.Error
	basePort, err = strconv.Atoi((n.listenAddr)[1:])
	n.nodes = make([]net.Addr, 5)
	if err != nil {
		fmt.Println(err)
		return
	}
	n.nodes[0] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 0}
	n.nodes[1] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 1}
	n.nodes[2] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 2}
	n.nodes[3] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 3}
	n.nodes[4] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 4}

	nodeKey := "/node/" + n.id
	mut, err := store.EncodeSet(nodeKey, n.listenAddr)
	if err != nil {
		panic(err)
	}
	n.store.Apply(1, mut)
	n.logger.Logf("registered %s at %s\n", n.id, n.listenAddr)
	n.manager = paxos.NewManager(2, uint64(len(n.nodes)), n.logger)
}

// TODO this function should take only an address and get all necessary info
// from the other existing nodes.
func (n *Node) Join(master string) {
	parts := strings.Split(master, "=", 2)
	if len(parts) < 2 {
		panic(fmt.Sprintf("bad master address: %s", master))
	}
	mid, addr := parts[0], parts[1]

	var basePort int
	var err os.Error
	n.nodes = make([]net.Addr, 5)
	basePort, err = strconv.Atoi((addr)[1:])
	if err != nil {
		fmt.Println(err)
		return
	}
	n.nodes[0] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 0}
	n.nodes[1] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 1}
	n.nodes[2] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 2}
	n.nodes[3] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 3}
	n.nodes[4] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 4}
	n.logger.Logf("attempting to attach to %v\n", n.nodes)

	n.logger.Logf("TODO: get a snapshot")
	// TODO remove all this fake stuff and talk to the other nodes
	// BEGIN FAKE STUFF
	nodeKey := "/node/" + mid
	mut, err := store.EncodeSet(nodeKey, addr)
	if err != nil {
		panic(err)
	}
	n.store.Apply(1, mut)
	// END OF FAKE STUFF

	n.manager = paxos.NewManager(2, uint64(len(n.nodes)), n.logger)
}

func (n *Node) RunForever() {
	me, err := strconv.Btoui64((n.listenAddr)[1:], 10)
	if err != nil {
		fmt.Println(err)
		return
	}

	n.logger.Logf("attempting to listen on %s\n", n.listenAddr)

	//open tcp sock

	conn, err := net.ListenPacket("udp", n.listenAddr)
	if err != nil {
		fmt.Println(err)
		return
	}

	udpCh := make(chan paxos.Msg)
	go RecvUdp(conn, udpCh)
	udpPutter := NewUdpPutter(me, n.nodes, conn)

	//n.manager.Init(FuncPutter(printMsg))
	n.manager.Init(udpPutter)

	go func() {
		for pkt := range udpCh {
			fmt.Printf("got udp packet: %#v\n", pkt)
			n.manager.Put(pkt)
		}
	}()

	//go func() {
	//	for m from a client:
	//		switch m.type {
	//		case 'set':
	//			go func() {
	//				v := n.manager.propose(encode(m))
	//				if v == m {
	//					reply 'OK'
	//				} else {
	//					reply 'fail'
	//				}
	//			}()
	//		case 'get':
	//			read from store
	//			return value
	//		}
	//}()

	for {
		n.store.Apply(n.manager.Recv())
	}
}
<commit_msg>start tcp server<commit_after>package borg

// Think of borg events like inotify events.  We're interested in changes to
// them all.  All events are sent to your instance of borg.  The filtering
// is done once they've arrived.  Let's make keys look like directories to
// aid this comparison.
//
// Example spec:
//
//     /<slug_id>/proc/<type>/<upid>/...
//
// Example interactive session:
//
//     $ borgd -i -a :9999
//     >> ls /proc/123_a3c_a12b3c45/beanstalkd/12345/
//     exe
//     env
//     lock
//     >> cat /proc/123_a3c_a12b3c45/beanstalkd/12345/*
//     beanstalkd -l 0.0.0.0 -p 4563
//     PORT=4563
//     123.4.5.678:9999
//     >>
//
// Example code:
//
//     me, err := borg.ListenAndServe(listenAddr)
//     if err != nil {
//         log.Exitf("listen failed: %v", err)
//     }
//
//     // Handle a specific type of key notification.
//     // The : signals a named variable part.
//     me.HandleFunc(
//         "/proc/:slug/beanstalkd/:upid/lock",
//         func (msg *borg.Message) {
//             if msg.Value == myId {
//                 cmd := beanstalkd ....
//                 ... launch beanstalkd ...
//                 me.Echo(cmd, "/proc/<slug>/beanstalkd/<upid>/cmd")
//             }
//         },
//     )

import (
	"borg/paxos"
	"borg/proto"
	"borg/store"
	"borg/util"
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
)

const (
	mSeqn = iota
	mFrom
	mTo
	mCmd
	mBody
	mNumParts
)

// NOT IPv6-compatible.
func getPort(addr string) uint64 {
	parts := strings.Split(addr, ":", -1)
	port, err := strconv.Btoui64(parts[len(parts) - 1], 10)
	if err != nil {
		fmt.Printf("error getting port from %q\n", addr)
	}
	return port
}

func RecvUdp(conn net.PacketConn, ch chan paxos.Msg) {
	for {
		pkt := make([]byte, 3000) // make sure it's big enough
		n, addr, err := conn.ReadFrom(pkt)
		if err != nil {
			fmt.Println(err)
			continue
		}
		msg := parse(string(pkt[0:n]))
		msg.From = getPort(addr.String())
		ch <- msg
	}
}

func parse(s string) paxos.Msg {
	parts := strings.Split(s, ":", mNumParts)
	if len(parts) != mNumParts {
		panic(s)
	}

	seqn, err := strconv.Btoui64(parts[mSeqn], 10)
	if err != nil {
		panic(s)
	}

	from, err := strconv.Btoui64(parts[mFrom], 10)
	if err != nil {
		panic(s)
	}

	var to uint64
	if parts[mTo] == "*" {
		to = 0
	} else {
		to, err = strconv.Btoui64(parts[mTo], 10)
		if err != nil {
			panic(err)
		}
	}

	return paxos.Msg{seqn, from, to, parts[mCmd], parts[mBody]}
}

type FuncPutter func (paxos.Msg)

func (f FuncPutter) Put(m paxos.Msg) {
	f(m)
}

func printMsg(m paxos.Msg) {
	fmt.Printf("should send %v\n", m)
}

func NewUdpPutter(me uint64, addrs []net.Addr, conn net.PacketConn) paxos.Putter {
	put := func(m paxos.Msg) {
		pkt := fmt.Sprintf("%d:%d:%d:%s:%s", m.Seqn, me, m.To, m.Cmd, m.Body)
		fmt.Printf("send udp packet %q\n", pkt)
		b := []byte(pkt)
		var to []net.Addr
		if m.To == 0 {
			to = addrs
		} else {
			to = []net.Addr{&net.UDPAddr{net.ParseIP("127.0.0.1"), int(m.To)}}
		}

		for _, addr := range to {
			n, err := conn.WriteTo(b, addr)
			if err != nil {
				fmt.Println(err)
				continue
			}
			if n != len(b) {
				fmt.Printf("sent <%d> bytes, wanted to send <%d>\n", n, len(b))
				continue
			}
		}
	}
	return FuncPutter(put)
}

type Node struct {
	id string
	listenAddr string
	logger *log.Logger
	nodes []net.Addr
	store *store.Store
	manager *paxos.Manager
}

func New(id string, listenAddr string, logger *log.Logger) *Node {
	if id == "" {
		b := make([]byte, 8)
		util.RandBytes(b)
		id = fmt.Sprintf("%x", b)
	}
	return &Node{
		listenAddr:listenAddr,
		logger:logger,
		store:store.New(logger),
		id:id,
	}
}

func (n *Node) Init() {
	var basePort int
	var err os.Error
	basePort, err = strconv.Atoi((n.listenAddr)[1:])
	n.nodes = make([]net.Addr, 5)
	if err != nil {
		fmt.Println(err)
		return
	}
	n.nodes[0] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 0}
	n.nodes[1] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 1}
	n.nodes[2] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 2}
	n.nodes[3] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 3}
	n.nodes[4] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 4}

	nodeKey := "/node/" + n.id
	mut, err := store.EncodeSet(nodeKey, n.listenAddr)
	if err != nil {
		panic(err)
	}
	n.store.Apply(1, mut)
	n.logger.Logf("registered %s at %s\n", n.id, n.listenAddr)
	n.manager = paxos.NewManager(2, uint64(len(n.nodes)), n.logger)
}

// TODO this function should take only an address and get all necessary info
// from the other existing nodes.
func (n *Node) Join(master string) {
	parts := strings.Split(master, "=", 2)
	if len(parts) < 2 {
		panic(fmt.Sprintf("bad master address: %s", master))
	}
	mid, addr := parts[0], parts[1]

	var basePort int
	var err os.Error
	n.nodes = make([]net.Addr, 5)
	basePort, err = strconv.Atoi((addr)[1:])
	if err != nil {
		fmt.Println(err)
		return
	}
	n.nodes[0] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 0}
	n.nodes[1] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 1}
	n.nodes[2] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 2}
	n.nodes[3] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 3}
	n.nodes[4] = &net.UDPAddr{net.ParseIP("127.0.0.1"), basePort + 4}
	n.logger.Logf("attempting to attach to %v\n", n.nodes)

	n.logger.Logf("TODO: get a snapshot")
	// TODO remove all this fake stuff and talk to the other nodes
	// BEGIN FAKE STUFF
	nodeKey := "/node/" + mid
	mut, err := store.EncodeSet(nodeKey, addr)
	if err != nil {
		panic(err)
	}
	n.store.Apply(1, mut)
	// END OF FAKE STUFF

	n.manager = paxos.NewManager(2, uint64(len(n.nodes)), n.logger)
}

func (n *Node) server(conn net.Conn) {
	br := bufio.NewReader(conn)
	for {
		parts, err := proto.Decode(br)
		if err != nil {
			n.logger.Log(err)
			continue
		}

		n.logger.Log("got", parts)
		//switch m.type {
		//case 'set':
		//	go func() {
		//		v := n.manager.propose(encode(m))
		//		if v == m {
		//			reply 'OK'
		//		} else {
		//			reply 'fail'
		//		}
		//	}()
		//case 'get':
		//	read from store
		//	return value
		//}
	}
}

func (n *Node) accept(l net.Listener) {
	for {
		c, err := l.Accept()
		if err != nil {
			n.logger.Log(err)
			continue
		}
		go n.server(c)
	}
}

func (n *Node) RunForever() {
	me, err := strconv.Btoui64((n.listenAddr)[1:], 10)
	if err != nil {
		fmt.Println(err)
		return
	}

	n.logger.Logf("attempting to listen on %s\n", n.listenAddr)

	tcpListener, err := net.Listen("tcp", n.listenAddr)
	if err != nil {
		n.logger.Log(err)
		return
	}
	go n.accept(tcpListener)

	udpConn, err := net.ListenPacket("udp", n.listenAddr)
	if err != nil {
		fmt.Println(err)
		return
	}

	udpCh := make(chan paxos.Msg)
	go RecvUdp(udpConn, udpCh)
	udpPutter := NewUdpPutter(me, n.nodes, udpConn)

	//n.manager.Init(FuncPutter(printMsg))
	n.manager.Init(udpPutter)

	go func() {
		for pkt := range udpCh {
			fmt.Printf("got udp packet: %#v\n", pkt)
			n.manager.Put(pkt)
		}
	}()

	for {
		n.store.Apply(n.manager.Recv())
	}
}
<|endoftext|>