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

//go:build go1.15
// +build go1.15

/*
Command godocfx generates DocFX YAML for Go code.

Usage:

	godocfx [flags] path

	# New modules with the given prefix. Delete any previous output.
	godocfx -rm -project my-project -new-modules cloud.google.com/go
	# Process a single module @latest.
	godocfx cloud.google.com/go
	# Process and print, instead of save.
	godocfx -print cloud.google.com/go/storage@latest
	# Change output directory.
	godocfx -out custom/output/dir cloud.google.com/go

See:
* https://dotnet.github.io/docfx/spec/metadata_format_spec.html
* https://github.com/googleapis/doc-templates
* https://github.com/googleapis/doc-pipeline
*/
package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/tools/go/packages"
	"gopkg.in/yaml.v2"
)

func main() {
	print := flag.Bool("print", false, "Print instead of save (default false)")
	rm := flag.Bool("rm", false, "Delete out directory before generating")
	outDir := flag.String("out", "obj/api", "Output directory (default obj/api)")
	projectID := flag.String("project", "", "Project ID to use. Required when using -new-modules.")
	newMods := flag.Bool("new-modules", false, "Process all new modules with the given prefix. Uses timestamp in Datastore. Stores results in $out/$mod.")
	// TODO: flag to set output URL path

	log.SetPrefix("[godocfx] ")

	flag.Parse()
	if flag.NArg() == 0 {
		log.Fatalf("%s missing required argument: module path/prefix", os.Args[0])
	}

	modNames := flag.Args()
	var mods []indexEntry
	if *newMods {
		if *projectID == "" {
			log.Fatal("Must set -project when using -new-modules")
		}
		var err error
		mods, err = newModules(context.Background(), indexClient{}, &dsTimeSaver{projectID: *projectID}, modNames)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		for _, mod := range modNames {
			modPath := mod
			version := "latest"
			if strings.Contains(mod, "@") {
				parts := strings.Split(mod, "@")
				if len(parts) != 2 {
					log.Fatal("module arg expected only one '@'")
				}
				modPath = parts[0]
				version = parts[1]
			}
			modPath = strings.TrimSuffix(modPath, "/...") // No /... needed.
			mods = append(mods, indexEntry{
				Path:    modPath,
				Version: version,
			})
		}
	}

	if *rm {
		os.RemoveAll(*outDir)
	}
	if len(mods) == 0 {
		log.Println("No new modules to process")
		return
	}
	// Create a temp module so we can get the exact version asked for.
	workingDir, err := ioutil.TempDir("", "godocfx-*")
	if err != nil {
		log.Fatalf("ioutil.TempDir: %v", err)
	}
	// Use a fake module that doesn't start with cloud.google.com/go.
	runCmd(workingDir, "go", "mod", "init", "cloud.google.com/lets-build-some-docs")

	failed := false
	for _, m := range mods {
		log.Printf("Processing %s@%s", m.Path, m.Version)

		// Always output to specific directory.
		path := filepath.Join(*outDir, fmt.Sprintf("%s@%s", m.Path, m.Version))
		if err := process(m, workingDir, path, *print); err != nil {
			log.Printf("Failed to process %v: %v", m, err)
			failed = true
		}
		log.Printf("Done with %s@%s", m.Path, m.Version)
	}
	if failed {
		os.Exit(1)
	}
}

func runCmd(dir, name string, args ...string) error {
	log.Printf("> [%s] %s %s", dir, name, strings.Join(args, " "))
	cmd := exec.Command(name, args...)
	cmd.Dir = dir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Start: %v", err)
	}
	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("Wait: %s", err)
	}
	return nil
}

func process(mod indexEntry, workingDir, outDir string, print bool) error {
	filter := []string{
		"cloud.google.com/go/analytics",
		"cloud.google.com/go/area120",
		"cloud.google.com/go/gsuiteaddons",

		"google.golang.org/appengine/v2/cmd",
	}
	if hasPrefix(mod.Path, filter) {
		log.Printf("%q filtered out, nothing to do: here is the filter: %q", mod.Path, filter)
		return nil
	}

	// Be sure to get the module and run the module loader in the tempDir.
	if err := runCmd(workingDir, "go", "mod", "tidy"); err != nil {
		return fmt.Errorf("go mod tidy error: %v", err)
	}
	// Don't do /... because it fails on submodules.
	if err := runCmd(workingDir, "go", "get", "-d", "-t", mod.Path+"@"+mod.Version); err != nil {
		return fmt.Errorf("go get %s@%s: %v", mod.Path, mod.Version, err)
	}

	log.Println("Starting to parse")
	optionalExtraFiles := []string{}
	namer := &friendlyAPINamer{
		metaURL: "https://raw.githubusercontent.com/googleapis/google-cloud-go/main/internal/.repo-metadata-full.json",
	}
	r, err := parse(mod.Path+"/...", workingDir, optionalExtraFiles, filter, namer)
	if err != nil {
		return fmt.Errorf("parse: %v", err)
	}

	if print {
		if err := yaml.NewEncoder(os.Stdout).Encode(r.pages); err != nil {
			return fmt.Errorf("Encode: %v", err)
		}
		fmt.Println("----- toc.yaml")
		if err := yaml.NewEncoder(os.Stdout).Encode(r.toc); err != nil {
			return fmt.Errorf("Encode: %v", err)
		}
		return nil
	}

	if err := write(outDir, r); err != nil {
		log.Fatalf("write: %v", err)
	}
	return nil
}

func write(outDir string, r *result) error {
	if err := os.MkdirAll(outDir, os.ModePerm); err != nil {
		return fmt.Errorf("os.MkdirAll: %v", err)
	}
	for path, p := range r.pages {
		// Make the module root page the index.
		if path == r.module.Path {
			path = "index"
		}
		// Trim the module path from all other paths.
		path = strings.TrimPrefix(path, r.module.Path+"/")
		path = filepath.Join(outDir, path+".yml")
		if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
			return fmt.Errorf("os.MkdirAll: %v", err)
		}
		f, err := os.Create(path)
		if err != nil {
			return err
		}
		defer f.Close()
		fmt.Fprintln(f, "### YamlMime:UniversalReference")
		if err := yaml.NewEncoder(f).Encode(p); err != nil {
			return err
		}

		path = filepath.Join(outDir, "toc.yml")
		f, err = os.Create(path)
		if err != nil {
			return err
		}
		defer f.Close()
		fmt.Fprintln(f, "### YamlMime:TableOfContent")
		if err := yaml.NewEncoder(f).Encode(r.toc); err != nil {
			return err
		}
	}

	for _, ef := range r.extraFiles {
		src, err := os.Open(filepath.Join(r.module.Dir, ef.srcRelativePath))
		if err != nil {
			return err
		}
		dst, err := os.Create(filepath.Join(outDir, ef.dstRelativePath))
		if err != nil {
			return err
		}
		if _, err := io.Copy(dst, src); err != nil {
			return nil
		}
	}

	// Write the docuploader docs.metadata file. Not for DocFX.
	// See https://github.com/googleapis/docuploader/issues/11.
	// Example:
	/*
		update_time {
		  seconds: 1600048103
		  nanos: 183052000
		}
		name: "cloud.google.com/go"
		version: "v0.65.0"
		language: "go"
	*/
	path := filepath.Join(outDir, "docs.metadata")
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	now := time.Now().UTC()
	writeMetadata(f, now, r.module)
	return nil
}

func writeMetadata(w io.Writer, now time.Time, module *packages.Module) {
	fmt.Fprintf(w, `update_time {
	seconds: %d
	nanos: %d
}
name: %q
version: %q
language: "go"
`, now.Unix(), now.Nanosecond(), module.Path, module.Version)

	// Some modules specify a different path to serve from.
	// The URL will be /[stem]/[version]/[pkg path relative to module].
	// Alternatively, we could plumb this through command line flags.
	switch module.Path {
	case "google.golang.org/appengine":
		fmt.Fprintf(w, "stem: \"/appengine/docs/standard/go111/reference\"\n")
	case "google.golang.org/appengine/v2":
		fmt.Fprintf(w, "stem: \"/appengine/docs/standard/go/reference/services/bundled\"\n")
	}
}
<commit_msg>chore(internal/godocfx): update legacy appengine package stem (#6565)<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      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.

//go:build go1.15
// +build go1.15

/*
Command godocfx generates DocFX YAML for Go code.

Usage:

	godocfx [flags] path

	# New modules with the given prefix. Delete any previous output.
	godocfx -rm -project my-project -new-modules cloud.google.com/go
	# Process a single module @latest.
	godocfx cloud.google.com/go
	# Process and print, instead of save.
	godocfx -print cloud.google.com/go/storage@latest
	# Change output directory.
	godocfx -out custom/output/dir cloud.google.com/go

See:
* https://dotnet.github.io/docfx/spec/metadata_format_spec.html
* https://github.com/googleapis/doc-templates
* https://github.com/googleapis/doc-pipeline
*/
package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/tools/go/packages"
	"gopkg.in/yaml.v2"
)

func main() {
	print := flag.Bool("print", false, "Print instead of save (default false)")
	rm := flag.Bool("rm", false, "Delete out directory before generating")
	outDir := flag.String("out", "obj/api", "Output directory (default obj/api)")
	projectID := flag.String("project", "", "Project ID to use. Required when using -new-modules.")
	newMods := flag.Bool("new-modules", false, "Process all new modules with the given prefix. Uses timestamp in Datastore. Stores results in $out/$mod.")
	// TODO: flag to set output URL path

	log.SetPrefix("[godocfx] ")

	flag.Parse()
	if flag.NArg() == 0 {
		log.Fatalf("%s missing required argument: module path/prefix", os.Args[0])
	}

	modNames := flag.Args()
	var mods []indexEntry
	if *newMods {
		if *projectID == "" {
			log.Fatal("Must set -project when using -new-modules")
		}
		var err error
		mods, err = newModules(context.Background(), indexClient{}, &dsTimeSaver{projectID: *projectID}, modNames)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		for _, mod := range modNames {
			modPath := mod
			version := "latest"
			if strings.Contains(mod, "@") {
				parts := strings.Split(mod, "@")
				if len(parts) != 2 {
					log.Fatal("module arg expected only one '@'")
				}
				modPath = parts[0]
				version = parts[1]
			}
			modPath = strings.TrimSuffix(modPath, "/...") // No /... needed.
			mods = append(mods, indexEntry{
				Path:    modPath,
				Version: version,
			})
		}
	}

	if *rm {
		os.RemoveAll(*outDir)
	}
	if len(mods) == 0 {
		log.Println("No new modules to process")
		return
	}
	// Create a temp module so we can get the exact version asked for.
	workingDir, err := ioutil.TempDir("", "godocfx-*")
	if err != nil {
		log.Fatalf("ioutil.TempDir: %v", err)
	}
	// Use a fake module that doesn't start with cloud.google.com/go.
	runCmd(workingDir, "go", "mod", "init", "cloud.google.com/lets-build-some-docs")

	failed := false
	for _, m := range mods {
		log.Printf("Processing %s@%s", m.Path, m.Version)

		// Always output to specific directory.
		path := filepath.Join(*outDir, fmt.Sprintf("%s@%s", m.Path, m.Version))
		if err := process(m, workingDir, path, *print); err != nil {
			log.Printf("Failed to process %v: %v", m, err)
			failed = true
		}
		log.Printf("Done with %s@%s", m.Path, m.Version)
	}
	if failed {
		os.Exit(1)
	}
}

func runCmd(dir, name string, args ...string) error {
	log.Printf("> [%s] %s %s", dir, name, strings.Join(args, " "))
	cmd := exec.Command(name, args...)
	cmd.Dir = dir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Start: %v", err)
	}
	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("Wait: %s", err)
	}
	return nil
}

func process(mod indexEntry, workingDir, outDir string, print bool) error {
	filter := []string{
		"cloud.google.com/go/analytics",
		"cloud.google.com/go/area120",
		"cloud.google.com/go/gsuiteaddons",

		"google.golang.org/appengine/v2/cmd",
	}
	if hasPrefix(mod.Path, filter) {
		log.Printf("%q filtered out, nothing to do: here is the filter: %q", mod.Path, filter)
		return nil
	}

	// Be sure to get the module and run the module loader in the tempDir.
	if err := runCmd(workingDir, "go", "mod", "tidy"); err != nil {
		return fmt.Errorf("go mod tidy error: %v", err)
	}
	// Don't do /... because it fails on submodules.
	if err := runCmd(workingDir, "go", "get", "-d", "-t", mod.Path+"@"+mod.Version); err != nil {
		return fmt.Errorf("go get %s@%s: %v", mod.Path, mod.Version, err)
	}

	log.Println("Starting to parse")
	optionalExtraFiles := []string{}
	namer := &friendlyAPINamer{
		metaURL: "https://raw.githubusercontent.com/googleapis/google-cloud-go/main/internal/.repo-metadata-full.json",
	}
	r, err := parse(mod.Path+"/...", workingDir, optionalExtraFiles, filter, namer)
	if err != nil {
		return fmt.Errorf("parse: %v", err)
	}

	if print {
		if err := yaml.NewEncoder(os.Stdout).Encode(r.pages); err != nil {
			return fmt.Errorf("Encode: %v", err)
		}
		fmt.Println("----- toc.yaml")
		if err := yaml.NewEncoder(os.Stdout).Encode(r.toc); err != nil {
			return fmt.Errorf("Encode: %v", err)
		}
		return nil
	}

	if err := write(outDir, r); err != nil {
		log.Fatalf("write: %v", err)
	}
	return nil
}

func write(outDir string, r *result) error {
	if err := os.MkdirAll(outDir, os.ModePerm); err != nil {
		return fmt.Errorf("os.MkdirAll: %v", err)
	}
	for path, p := range r.pages {
		// Make the module root page the index.
		if path == r.module.Path {
			path = "index"
		}
		// Trim the module path from all other paths.
		path = strings.TrimPrefix(path, r.module.Path+"/")
		path = filepath.Join(outDir, path+".yml")
		if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
			return fmt.Errorf("os.MkdirAll: %v", err)
		}
		f, err := os.Create(path)
		if err != nil {
			return err
		}
		defer f.Close()
		fmt.Fprintln(f, "### YamlMime:UniversalReference")
		if err := yaml.NewEncoder(f).Encode(p); err != nil {
			return err
		}

		path = filepath.Join(outDir, "toc.yml")
		f, err = os.Create(path)
		if err != nil {
			return err
		}
		defer f.Close()
		fmt.Fprintln(f, "### YamlMime:TableOfContent")
		if err := yaml.NewEncoder(f).Encode(r.toc); err != nil {
			return err
		}
	}

	for _, ef := range r.extraFiles {
		src, err := os.Open(filepath.Join(r.module.Dir, ef.srcRelativePath))
		if err != nil {
			return err
		}
		dst, err := os.Create(filepath.Join(outDir, ef.dstRelativePath))
		if err != nil {
			return err
		}
		if _, err := io.Copy(dst, src); err != nil {
			return nil
		}
	}

	// Write the docuploader docs.metadata file. Not for DocFX.
	// See https://github.com/googleapis/docuploader/issues/11.
	// Example:
	/*
		update_time {
		  seconds: 1600048103
		  nanos: 183052000
		}
		name: "cloud.google.com/go"
		version: "v0.65.0"
		language: "go"
	*/
	path := filepath.Join(outDir, "docs.metadata")
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	now := time.Now().UTC()
	writeMetadata(f, now, r.module)
	return nil
}

func writeMetadata(w io.Writer, now time.Time, module *packages.Module) {
	fmt.Fprintf(w, `update_time {
	seconds: %d
	nanos: %d
}
name: %q
version: %q
language: "go"
`, now.Unix(), now.Nanosecond(), module.Path, module.Version)

	// Some modules specify a different path to serve from.
	// The URL will be /[stem]/[version]/[pkg path relative to module].
	// Alternatively, we could plumb this through command line flags.
	switch module.Path {
	case "google.golang.org/appengine":
		fmt.Fprintf(w, "stem: \"/appengine/docs/legacy/standard/go111/reference\"\n")
	case "google.golang.org/appengine/v2":
		fmt.Fprintf(w, "stem: \"/appengine/docs/standard/go/reference/services/bundled\"\n")
	}
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2014 gRPC 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 (
	"flag"
	"net"
	"strconv"

	"google.golang.org/grpc"
	_ "google.golang.org/grpc/balancer/grpclb"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/alts"
	"google.golang.org/grpc/credentials/oauth"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/interop"
	testpb "google.golang.org/grpc/interop/grpc_testing"
	"google.golang.org/grpc/testdata"
)

var (
	caFile                = flag.String("ca_file", "", "The file containning the CA root cert file")
	useTLS                = flag.Bool("use_tls", false, "Connection uses TLS if true")
	useALTS               = flag.Bool("use_alts", false, "Connection uses ALTS if true (this option can only be used on GCP)")
	altsHSAddr            = flag.String("alts_handshaker_service_address", "", "ALTS handshaker gRPC service address")
	testCA                = flag.Bool("use_test_ca", false, "Whether to replace platform root CAs with test CA as the CA root")
	serviceAccountKeyFile = flag.String("service_account_key_file", "", "Path to service account json key file")
	oauthScope            = flag.String("oauth_scope", "", "The scope for OAuth2 tokens")
	defaultServiceAccount = flag.String("default_service_account", "", "Email of GCE default service account")
	serverHost            = flag.String("server_host", "localhost", "The server host name")
	serverPort            = flag.Int("server_port", 10000, "The server port number")
	tlsServerName         = flag.String("server_host_override", "", "The server name use to verify the hostname returned by TLS handshake if it is not empty. Otherwise, --server_host is used.")
	testCase              = flag.String("test_case", "large_unary",
		`Configure different test cases. Valid options are:
        empty_unary : empty (zero bytes) request and response;
        large_unary : single request and (large) response;
        client_streaming : request streaming with single response;
        server_streaming : single request with response streaming;
        ping_pong : full-duplex streaming;
        empty_stream : full-duplex streaming with zero message;
        timeout_on_sleeping_server: fullduplex streaming on a sleeping server;
        compute_engine_creds: large_unary with compute engine auth;
        service_account_creds: large_unary with service account auth;
        jwt_token_creds: large_unary with jwt token auth;
        per_rpc_creds: large_unary with per rpc token;
        oauth2_auth_token: large_unary with oauth2 token auth;
        cancel_after_begin: cancellation after metadata has been sent but before payloads are sent;
        cancel_after_first_response: cancellation after receiving 1st message from the server;
        status_code_and_message: status code propagated back to client;
        custom_metadata: server will echo custom metadata;
        unimplemented_method: client attempts to call unimplemented method;
        unimplemented_service: client attempts to call unimplemented service.`)
)

func main() {
	flag.Parse()
	if *useTLS && *useALTS {
		grpclog.Fatalf("use_tls and use_alts cannot be both set to true")
	}
	serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
	var opts []grpc.DialOption
	if *useTLS {
		var sn string
		if *tlsServerName != "" {
			sn = *tlsServerName
		}
		var creds credentials.TransportCredentials
		if *testCA {
			var err error
			if *caFile == "" {
				*caFile = testdata.Path("ca.pem")
			}
			creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
			if err != nil {
				grpclog.Fatalf("Failed to create TLS credentials %v", err)
			}
		} else {
			creds = credentials.NewClientTLSFromCert(nil, sn)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
		if *testCase == "compute_engine_creds" {
			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewComputeEngine()))
		} else if *testCase == "service_account_creds" {
			jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope)
			if err != nil {
				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
			}
			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
		} else if *testCase == "jwt_token_creds" {
			jwtCreds, err := oauth.NewJWTAccessFromFile(*serviceAccountKeyFile)
			if err != nil {
				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
			}
			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
		} else if *testCase == "oauth2_auth_token" {
			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope))))
		}
	} else if *useALTS {
		altsOpts := alts.DefaultClientOptions()
		if *altsHSAddr != "" {
			altsOpts.HandshakerServiceAddress = *altsHSAddr
		}
		altsTC := alts.NewClientCreds(altsOpts)
		opts = append(opts, grpc.WithTransportCredentials(altsTC))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	opts = append(opts, grpc.WithBlock())
	conn, err := grpc.Dial(serverAddr, opts...)
	if err != nil {
		grpclog.Fatalf("Fail to dial: %v", err)
	}
	defer conn.Close()
	tc := testpb.NewTestServiceClient(conn)
	switch *testCase {
	case "empty_unary":
		interop.DoEmptyUnaryCall(tc)
		grpclog.Infoln("EmptyUnaryCall done")
	case "large_unary":
		interop.DoLargeUnaryCall(tc)
		grpclog.Infoln("LargeUnaryCall done")
	case "client_streaming":
		interop.DoClientStreaming(tc)
		grpclog.Infoln("ClientStreaming done")
	case "server_streaming":
		interop.DoServerStreaming(tc)
		grpclog.Infoln("ServerStreaming done")
	case "ping_pong":
		interop.DoPingPong(tc)
		grpclog.Infoln("Pingpong done")
	case "empty_stream":
		interop.DoEmptyStream(tc)
		grpclog.Infoln("Emptystream done")
	case "timeout_on_sleeping_server":
		interop.DoTimeoutOnSleepingServer(tc)
		grpclog.Infoln("TimeoutOnSleepingServer done")
	case "compute_engine_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute compute_engine_creds test case.")
		}
		interop.DoComputeEngineCreds(tc, *defaultServiceAccount, *oauthScope)
		grpclog.Infoln("ComputeEngineCreds done")
	case "service_account_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute service_account_creds test case.")
		}
		interop.DoServiceAccountCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("ServiceAccountCreds done")
	case "jwt_token_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute jwt_token_creds test case.")
		}
		interop.DoJWTTokenCreds(tc, *serviceAccountKeyFile)
		grpclog.Infoln("JWTtokenCreds done")
	case "per_rpc_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute per_rpc_creds test case.")
		}
		interop.DoPerRPCCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("PerRPCCreds done")
	case "oauth2_auth_token":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute oauth2_auth_token test case.")
		}
		interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("Oauth2TokenCreds done")
	case "cancel_after_begin":
		interop.DoCancelAfterBegin(tc)
		grpclog.Infoln("CancelAfterBegin done")
	case "cancel_after_first_response":
		interop.DoCancelAfterFirstResponse(tc)
		grpclog.Infoln("CancelAfterFirstResponse done")
	case "status_code_and_message":
		interop.DoStatusCodeAndMessage(tc)
		grpclog.Infoln("StatusCodeAndMessage done")
	case "custom_metadata":
		interop.DoCustomMetadata(tc)
		grpclog.Infoln("CustomMetadata done")
	case "unimplemented_method":
		interop.DoUnimplementedMethod(conn)
		grpclog.Infoln("UnimplementedMethod done")
	case "unimplemented_service":
		interop.DoUnimplementedService(testpb.NewUnimplementedServiceClient(conn))
		grpclog.Infoln("UnimplementedService done")
	default:
		grpclog.Fatal("Unsupported test case: ", *testCase)
	}
}
<commit_msg>interop: set dns as default scheme in interop client (#2165)<commit_after>/*
 *
 * Copyright 2014 gRPC 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 (
	"flag"
	"net"
	"strconv"

	"google.golang.org/grpc"
	_ "google.golang.org/grpc/balancer/grpclb"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/alts"
	"google.golang.org/grpc/credentials/oauth"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/interop"
	testpb "google.golang.org/grpc/interop/grpc_testing"
	"google.golang.org/grpc/resolver"
	"google.golang.org/grpc/testdata"
)

var (
	caFile                = flag.String("ca_file", "", "The file containning the CA root cert file")
	useTLS                = flag.Bool("use_tls", false, "Connection uses TLS if true")
	useALTS               = flag.Bool("use_alts", false, "Connection uses ALTS if true (this option can only be used on GCP)")
	altsHSAddr            = flag.String("alts_handshaker_service_address", "", "ALTS handshaker gRPC service address")
	testCA                = flag.Bool("use_test_ca", false, "Whether to replace platform root CAs with test CA as the CA root")
	serviceAccountKeyFile = flag.String("service_account_key_file", "", "Path to service account json key file")
	oauthScope            = flag.String("oauth_scope", "", "The scope for OAuth2 tokens")
	defaultServiceAccount = flag.String("default_service_account", "", "Email of GCE default service account")
	serverHost            = flag.String("server_host", "localhost", "The server host name")
	serverPort            = flag.Int("server_port", 10000, "The server port number")
	tlsServerName         = flag.String("server_host_override", "", "The server name use to verify the hostname returned by TLS handshake if it is not empty. Otherwise, --server_host is used.")
	testCase              = flag.String("test_case", "large_unary",
		`Configure different test cases. Valid options are:
        empty_unary : empty (zero bytes) request and response;
        large_unary : single request and (large) response;
        client_streaming : request streaming with single response;
        server_streaming : single request with response streaming;
        ping_pong : full-duplex streaming;
        empty_stream : full-duplex streaming with zero message;
        timeout_on_sleeping_server: fullduplex streaming on a sleeping server;
        compute_engine_creds: large_unary with compute engine auth;
        service_account_creds: large_unary with service account auth;
        jwt_token_creds: large_unary with jwt token auth;
        per_rpc_creds: large_unary with per rpc token;
        oauth2_auth_token: large_unary with oauth2 token auth;
        cancel_after_begin: cancellation after metadata has been sent but before payloads are sent;
        cancel_after_first_response: cancellation after receiving 1st message from the server;
        status_code_and_message: status code propagated back to client;
        custom_metadata: server will echo custom metadata;
        unimplemented_method: client attempts to call unimplemented method;
        unimplemented_service: client attempts to call unimplemented service.`)
)

func main() {
	flag.Parse()
	resolver.SetDefaultScheme("dns")
	if *useTLS && *useALTS {
		grpclog.Fatalf("use_tls and use_alts cannot be both set to true")
	}
	serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
	var opts []grpc.DialOption
	if *useTLS {
		var sn string
		if *tlsServerName != "" {
			sn = *tlsServerName
		}
		var creds credentials.TransportCredentials
		if *testCA {
			var err error
			if *caFile == "" {
				*caFile = testdata.Path("ca.pem")
			}
			creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
			if err != nil {
				grpclog.Fatalf("Failed to create TLS credentials %v", err)
			}
		} else {
			creds = credentials.NewClientTLSFromCert(nil, sn)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
		if *testCase == "compute_engine_creds" {
			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewComputeEngine()))
		} else if *testCase == "service_account_creds" {
			jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope)
			if err != nil {
				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
			}
			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
		} else if *testCase == "jwt_token_creds" {
			jwtCreds, err := oauth.NewJWTAccessFromFile(*serviceAccountKeyFile)
			if err != nil {
				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
			}
			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
		} else if *testCase == "oauth2_auth_token" {
			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope))))
		}
	} else if *useALTS {
		altsOpts := alts.DefaultClientOptions()
		if *altsHSAddr != "" {
			altsOpts.HandshakerServiceAddress = *altsHSAddr
		}
		altsTC := alts.NewClientCreds(altsOpts)
		opts = append(opts, grpc.WithTransportCredentials(altsTC))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	opts = append(opts, grpc.WithBlock())
	conn, err := grpc.Dial(serverAddr, opts...)
	if err != nil {
		grpclog.Fatalf("Fail to dial: %v", err)
	}
	defer conn.Close()
	tc := testpb.NewTestServiceClient(conn)
	switch *testCase {
	case "empty_unary":
		interop.DoEmptyUnaryCall(tc)
		grpclog.Infoln("EmptyUnaryCall done")
	case "large_unary":
		interop.DoLargeUnaryCall(tc)
		grpclog.Infoln("LargeUnaryCall done")
	case "client_streaming":
		interop.DoClientStreaming(tc)
		grpclog.Infoln("ClientStreaming done")
	case "server_streaming":
		interop.DoServerStreaming(tc)
		grpclog.Infoln("ServerStreaming done")
	case "ping_pong":
		interop.DoPingPong(tc)
		grpclog.Infoln("Pingpong done")
	case "empty_stream":
		interop.DoEmptyStream(tc)
		grpclog.Infoln("Emptystream done")
	case "timeout_on_sleeping_server":
		interop.DoTimeoutOnSleepingServer(tc)
		grpclog.Infoln("TimeoutOnSleepingServer done")
	case "compute_engine_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute compute_engine_creds test case.")
		}
		interop.DoComputeEngineCreds(tc, *defaultServiceAccount, *oauthScope)
		grpclog.Infoln("ComputeEngineCreds done")
	case "service_account_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute service_account_creds test case.")
		}
		interop.DoServiceAccountCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("ServiceAccountCreds done")
	case "jwt_token_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute jwt_token_creds test case.")
		}
		interop.DoJWTTokenCreds(tc, *serviceAccountKeyFile)
		grpclog.Infoln("JWTtokenCreds done")
	case "per_rpc_creds":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute per_rpc_creds test case.")
		}
		interop.DoPerRPCCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("PerRPCCreds done")
	case "oauth2_auth_token":
		if !*useTLS {
			grpclog.Fatalf("TLS is not enabled. TLS is required to execute oauth2_auth_token test case.")
		}
		interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope)
		grpclog.Infoln("Oauth2TokenCreds done")
	case "cancel_after_begin":
		interop.DoCancelAfterBegin(tc)
		grpclog.Infoln("CancelAfterBegin done")
	case "cancel_after_first_response":
		interop.DoCancelAfterFirstResponse(tc)
		grpclog.Infoln("CancelAfterFirstResponse done")
	case "status_code_and_message":
		interop.DoStatusCodeAndMessage(tc)
		grpclog.Infoln("StatusCodeAndMessage done")
	case "custom_metadata":
		interop.DoCustomMetadata(tc)
		grpclog.Infoln("CustomMetadata done")
	case "unimplemented_method":
		interop.DoUnimplementedMethod(conn)
		grpclog.Infoln("UnimplementedMethod done")
	case "unimplemented_service":
		interop.DoUnimplementedService(testpb.NewUnimplementedServiceClient(conn))
		grpclog.Infoln("UnimplementedService done")
	default:
		grpclog.Fatal("Unsupported test case: ", *testCase)
	}
}
<|endoftext|>


<commit_before>package interval_test
// Copyright ©2011 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"fmt"
	"github.com/kortschak/BioGo/interval"
	"strings"
)

// "example":[-22, 6), "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[34, 61)
func ExampleInsert() {
	tree := interval.NewTree()
	chromosome := "example"
	segments := [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}}

	for _, s := range segments {
		if i, err := interval.New(chromosome, s[0], s[1], 0, nil); err == nil {
			tree.Insert(i)
		} else {
			fmt.Println(err)
		}
	}

	PrintAll(tree)
}

// "example":[-22, 6)
func ExampleIntersect() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := interval.New("example", -15, -2, 0, nil); err == nil {
		for s := range tree.Intersect(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[-22, 6)
// "example":[3, 7)
func ExampleContain() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := interval.New("example", 4, 6, 0, nil); err == nil {
		for s := range tree.Contain(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[2, 3)
func ExampleWithin() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := interval.New("example", 1, 5, 0, nil); err == nil {
		for s := range tree.Within(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[-22, 6) <nil> <nil> <nil>
// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[34, 61)
func ExampleRemove() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := interval.New("example", -15, -2, 0, nil); err == nil {
		for s := range tree.Intersect(i, 0) {
			r := tree.Remove(s)
			fmt.Println(r, r.Left(), r.Right(),r.Parent())
		}
	}

	PrintAll(tree)
}

// Inserted
// "example":[0, 4)
// "example":[27, 61)
// Replaced
// "example":[0, 4)
// "example":[34, 61)
// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[27, 61)
func ExampleMerge() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {34, 61}})
	chromosome := "example"
	segments := [][]int{{0, 1}, {27, 42}}
	inserted := []*interval.Interval{}
	replaced := []*interval.Interval{}

	for _, s := range segments {
		if i, err := interval.New(chromosome, s[0], s[1], 0, nil); err == nil {
			n, o := tree.Merge(i, 0)
			inserted = append(inserted, n...)
			replaced = append(replaced, o...)
		} else {
			fmt.Println(err)
		}
	}

	fmt.Println("Inserted")
	for _, s := range inserted {
		fmt.Printf("%s\n", s)
	}

	fmt.Println("Replaced")
	for _, s := range replaced {
		fmt.Printf("%s\n", s)
	}

	PrintAll(tree)
}

// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[27, 61)
func ExampleTraverseAll() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {27, 61}})
	segs := []string{}
	for i := range tree.TraverseAll() {
		segs = append(segs, i.String())
	}
	fmt.Println(strings.Join(segs, ", "))
}

// flattened: ["example":[0, 12) "example":[27, 61)]
// original: [["example":[0, 4) "example":[2, 3) "example":[3, 7) "example":[5, 10) "example":[8, 12)] ["example":[27, 61)]]
func ExampleFlatten() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {27, 61}})
	start, end := tree.Range("example")
	if i, err := interval.New("example", start, end, 0, nil); err == nil {
		flat, original := tree.Flatten(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// flattened: ["example":[3, 10)]
// original: [["example":[3, 7) "example":[5, 10)]]
func ExampleFlattenContain() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})

	if i, err := interval.New("example", 6, 7, 0, nil); err == nil {
		flat, original := tree.FlattenContaining(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// flattened: ["example":[2, 7)]
// original: [["example":[2, 3) "example":[3, 7)]]
func ExampleFlattenWithin() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})

	if i, err := interval.New("example", 2, 7, 0, nil); err == nil {
		flat, original := tree.FlattenWithin(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// Helpers

func CreateExampleTree(chromosome string, segments [][]int) (tree interval.Tree) {
	tree = interval.NewTree()

	for _, s := range segments {
		i, _ := interval.New(chromosome, s[0], s[1], 0, nil)
		tree.Insert(i)
	}

	return
}

func PrintAll(t interval.Tree) {
	segs := []string{}
	for i := range t.TraverseAll() {
		segs = append(segs, i.String())
	}
	fmt.Println(strings.Join(segs, ", "))
}
<commit_msg>Put ExampleXXX tests in interval package.<commit_after>package interval
// Copyright ©2011 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import (
	"fmt"
	"strings"
)

// "example":[-22, 6), "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[34, 61)
func ExampleInsert() {
	tree := NewTree()
	chromosome := "example"
	segments := [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}}

	for _, s := range segments {
		if i, err := New(chromosome, s[0], s[1], 0, nil); err == nil {
			tree.Insert(i)
		} else {
			fmt.Println(err)
		}
	}

	PrintAll(tree)
}

// "example":[-22, 6)
func ExampleIntersect() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := New("example", -15, -2, 0, nil); err == nil {
		for s := range tree.Intersect(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[-22, 6)
// "example":[3, 7)
func ExampleContain() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := New("example", 4, 6, 0, nil); err == nil {
		for s := range tree.Contain(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[2, 3)
func ExampleWithin() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := New("example", 1, 5, 0, nil); err == nil {
		for s := range tree.Within(i, 0) {
			fmt.Printf("%s\n", s)
		}
	}
}

// "example":[-22, 6) <nil> <nil> <nil>
// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[34, 61)
func ExampleRemove() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})
	if i, err := New("example", -15, -2, 0, nil); err == nil {
		for s := range tree.Intersect(i, 0) {
			r := tree.Remove(s)
			fmt.Println(r, r.Left(), r.Right(),r.Parent())
		}
	}

	PrintAll(tree)
}

// Inserted
// "example":[0, 4)
// "example":[27, 61)
// Replaced
// "example":[0, 4)
// "example":[34, 61)
// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[27, 61)
func ExampleMerge() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {34, 61}})
	chromosome := "example"
	segments := [][]int{{0, 1}, {27, 42}}
	inserted := []*Interval{}
	replaced := []*Interval{}

	for _, s := range segments {
		if i, err := New(chromosome, s[0], s[1], 0, nil); err == nil {
			n, o := tree.Merge(i, 0)
			inserted = append(inserted, n...)
			replaced = append(replaced, o...)
		} else {
			fmt.Println(err)
		}
	}

	fmt.Println("Inserted")
	for _, s := range inserted {
		fmt.Printf("%s\n", s)
	}

	fmt.Println("Replaced")
	for _, s := range replaced {
		fmt.Printf("%s\n", s)
	}

	PrintAll(tree)
}

// "example":[0, 4), "example":[2, 3), "example":[3, 7), "example":[5, 10), "example":[8, 12), "example":[27, 61)
func ExampleTraverseAll() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {27, 61}})
	segs := []string{}
	for i := range tree.TraverseAll() {
		segs = append(segs, i.String())
	}
	fmt.Println(strings.Join(segs, ", "))
}

// flattened: ["example":[0, 12) "example":[27, 61)]
// original: [["example":[0, 4) "example":[2, 3) "example":[3, 7) "example":[5, 10) "example":[8, 12)] ["example":[27, 61)]]
func ExampleFlatten() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {27, 61}})
	start, end := tree.Range("example")
	if i, err := New("example", start, end, 0, nil); err == nil {
		flat, original := tree.Flatten(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// flattened: ["example":[3, 10)]
// original: [["example":[3, 7) "example":[5, 10)]]
func ExampleFlattenContain() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})

	if i, err := New("example", 6, 7, 0, nil); err == nil {
		flat, original := tree.FlattenContaining(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// flattened: ["example":[2, 7)]
// original: [["example":[2, 3) "example":[3, 7)]]
func ExampleFlattenWithin() {
	tree := CreateExampleTree("example", [][]int{{0, 4}, {8, 12}, {2, 3}, {5, 10}, {3, 7}, {-22, 6}, {34, 61}})

	if i, err := New("example", 2, 7, 0, nil); err == nil {
		flat, original := tree.FlattenWithin(i, 0, 0)
		fmt.Printf("flattened: %v\noriginal: %v\n", flat, original)
	}
}

// Helpers

func CreateExampleTree(chromosome string, segments [][]int) (tree Tree) {
	tree = NewTree()

	for _, s := range segments {
		i, _ := New(chromosome, s[0], s[1], 0, nil)
		tree.Insert(i)
	}

	return
}

func PrintAll(t Tree) {
	segs := []string{}
	for i := range t.TraverseAll() {
		segs = append(segs, i.String())
	}
	fmt.Println(strings.Join(segs, ", "))
}
<|endoftext|>


<commit_before>package integration_test

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/concourse/baggageclaim"
)

var _ = Describe("Import Strategy", func() {
	var (
		runner *BaggageClaimRunner
		client baggageclaim.Client
	)

	BeforeEach(func() {
		runner = NewRunner(baggageClaimPath)
		runner.Start()
		client = runner.Client()
	})

	AfterEach(func() {
		runner.Stop()
		runner.Cleanup()
	})

	Describe("API", func() {
		Describe("POST /volumes", func() {
			var (
				dir string

				strategy baggageclaim.ImportStrategy

				volume baggageclaim.Volume
			)

			BeforeEach(func() {
				var err error
				dir, err = ioutil.TempDir("", "host_path")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "file-with-perms"), []byte("file-with-perms-contents"), 0600)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "some-file"), []byte("some-file-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "some-dir"), 0755)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "some-dir", "file-in-dir"), []byte("file-in-dir-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "empty-dir"), 0755)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "dir-with-perms"), 0700)
				Expect(err).NotTo(HaveOccurred())

				strategy = baggageclaim.ImportStrategy{
					Path: dir,
				}
			})

			AfterEach(func() {
				Expect(os.RemoveAll(dir)).To(Succeed())
			})

			assert := func() {
				It("is in the volume dir", func() {
					Expect(volume.Path()).To(HavePrefix(runner.VolumeDir()))
				})

				It("has the correct contents", func() {
					createdDir := volume.Path()

					Expect(createdDir).To(BeADirectory())

					Expect(filepath.Join(createdDir, "some-file")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "some-file"))).To(Equal([]byte("some-file-contents")))

					Expect(filepath.Join(createdDir, "file-with-perms")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "file-with-perms"))).To(Equal([]byte("file-with-perms-contents")))
					fi, err := os.Lstat(filepath.Join(createdDir, "file-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err := os.Lstat(filepath.Join(dir, "file-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))

					Expect(filepath.Join(createdDir, "some-dir")).To(BeADirectory())

					Expect(filepath.Join(createdDir, "some-dir", "file-in-dir")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "some-dir", "file-in-dir"))).To(Equal([]byte("file-in-dir-contents")))
					fi, err = os.Lstat(filepath.Join(createdDir, "some-dir", "file-in-dir"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err = os.Lstat(filepath.Join(dir, "some-dir", "file-in-dir"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))
					Expect(filepath.Join(createdDir, "empty-dir")).To(BeADirectory())

					Expect(filepath.Join(createdDir, "dir-with-perms")).To(BeADirectory())
					fi, err = os.Lstat(filepath.Join(createdDir, "dir-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err = os.Lstat(filepath.Join(dir, "dir-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))
				})
			}

			JustBeforeEach(func() {
				var err error
				volume, err = client.CreateVolume(logger, "some-handle", baggageclaim.VolumeSpec{
					Strategy: strategy,
				})
				Expect(err).NotTo(HaveOccurred())
			})

			assert()

			Context("when the path is a .tgz", func() {
				var tgz *os.File

				BeforeEach(func() {
					var err error
					tgz, err = ioutil.TempFile("", "host_path_archive")
					Expect(err).ToNot(HaveOccurred())

					Expect(tgz.Close()).To(Succeed())

					tar := exec.Command("tar", "-czvf", tgz.Name(), "-C", strategy.Path, ".")
					tar.Stdout = GinkgoWriter
					tar.Stderr = GinkgoWriter
					Expect(tar.Run()).To(Succeed())

					strategy.Path = tgz.Name()
				})

				AfterEach(func() {
					Expect(os.RemoveAll(tgz.Name())).To(Succeed())
				})

				assert()
			})
		})
	})
})
<commit_msg>make import strategy test work on windows<commit_after>package integration_test

import (
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/concourse/go-archive/tgzfs"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/concourse/baggageclaim"
)

var _ = Describe("Import Strategy", func() {
	var (
		runner *BaggageClaimRunner
		client baggageclaim.Client
	)

	BeforeEach(func() {
		runner = NewRunner(baggageClaimPath)
		runner.Start()
		client = runner.Client()
	})

	AfterEach(func() {
		runner.Stop()
		runner.Cleanup()
	})

	Describe("API", func() {
		Describe("POST /volumes", func() {
			var (
				dir string

				strategy baggageclaim.ImportStrategy

				volume baggageclaim.Volume
			)

			BeforeEach(func() {
				var err error
				dir, err = ioutil.TempDir("", "host_path")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "file-with-perms"), []byte("file-with-perms-contents"), 0600)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "some-file"), []byte("some-file-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "some-dir"), 0755)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(dir, "some-dir", "file-in-dir"), []byte("file-in-dir-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "empty-dir"), 0755)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(filepath.Join(dir, "dir-with-perms"), 0700)
				Expect(err).NotTo(HaveOccurred())

				strategy = baggageclaim.ImportStrategy{
					Path: dir,
				}
			})

			AfterEach(func() {
				Expect(os.RemoveAll(dir)).To(Succeed())
			})

			assert := func() {
				It("is in the volume dir", func() {
					Expect(volume.Path()).To(HavePrefix(runner.VolumeDir()))
				})

				It("has the correct contents", func() {
					createdDir := volume.Path()

					Expect(createdDir).To(BeADirectory())

					Expect(filepath.Join(createdDir, "some-file")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "some-file"))).To(Equal([]byte("some-file-contents")))

					Expect(filepath.Join(createdDir, "file-with-perms")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "file-with-perms"))).To(Equal([]byte("file-with-perms-contents")))
					fi, err := os.Lstat(filepath.Join(createdDir, "file-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err := os.Lstat(filepath.Join(dir, "file-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))

					Expect(filepath.Join(createdDir, "some-dir")).To(BeADirectory())

					Expect(filepath.Join(createdDir, "some-dir", "file-in-dir")).To(BeARegularFile())
					Expect(ioutil.ReadFile(filepath.Join(createdDir, "some-dir", "file-in-dir"))).To(Equal([]byte("file-in-dir-contents")))
					fi, err = os.Lstat(filepath.Join(createdDir, "some-dir", "file-in-dir"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err = os.Lstat(filepath.Join(dir, "some-dir", "file-in-dir"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))
					Expect(filepath.Join(createdDir, "empty-dir")).To(BeADirectory())

					Expect(filepath.Join(createdDir, "dir-with-perms")).To(BeADirectory())
					fi, err = os.Lstat(filepath.Join(createdDir, "dir-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					expectedFI, err = os.Lstat(filepath.Join(dir, "dir-with-perms"))
					Expect(err).NotTo(HaveOccurred())
					Expect(fi.Mode()).To(Equal(expectedFI.Mode()))
				})
			}

			JustBeforeEach(func() {
				var err error
				volume, err = client.CreateVolume(logger, "some-handle", baggageclaim.VolumeSpec{
					Strategy: strategy,
				})
				Expect(err).NotTo(HaveOccurred())
			})

			assert()

			Context("when the path is a .tgz", func() {
				var tgz *os.File

				BeforeEach(func() {
					var err error
					tgz, err = ioutil.TempFile("", "host_path_archive")
					Expect(err).ToNot(HaveOccurred())

					err = tgzfs.Compress(tgz, strategy.Path, ".")
					Expect(err).ToNot(HaveOccurred())

					Expect(tgz.Close()).To(Succeed())

					strategy.Path = tgz.Name()
				})

				AfterEach(func() {
					Expect(os.RemoveAll(tgz.Name())).To(Succeed())
				})

				assert()
			})
		})
	})
})
<|endoftext|>


<commit_before>package monitor

import (
	"github.com/sai-lab/mouryou/lib/convert"
	"github.com/sai-lab/mouryou/lib/logger"
	"github.com/sai-lab/mouryou/lib/models"
)

// WeightMonitor は重みを計測する関数です。
func WeightMonitor(config *models.Config) {
	for _ = range StateCh {
		length := len(config.Cluster.VirtualMachines)
		weights := map[string]int{}
		weights["weights"] = -1
		for i, state := range States {
			weights[state.Name] = state.Weight
			if i == length-1 {
				break
			}
		}
		ar := convert.MapToArray(weights)
		logger.Write(ar)
		logger.Print(ar)
	}
}
<commit_msg>起動していないサーバの重みはログに吐き出さないように変更<commit_after>package monitor

import (
	"github.com/sai-lab/mouryou/lib/convert"
	"github.com/sai-lab/mouryou/lib/logger"
	"github.com/sai-lab/mouryou/lib/models"
)

// WeightMonitor は重みを計測する関数です。
func WeightMonitor(config *models.Config) {
	for _ = range LoadCh {
		length := len(config.Cluster.VirtualMachines)
		weights := map[string]int{}
		weights["weights"] = -1
		for i, state := range States {
			if state.Info != "booted up" {
				continue
			}
			weights[state.Name] = state.Weight
			if i == length-1 {
				break
			}
		}
		ar := convert.MapToArray(weights)
		logger.Write(ar)
		logger.Print(ar)
	}
}
<|endoftext|>


<commit_before>package marathon

import(
	"net/http"
	"io/ioutil"
	"encoding/json"
	"strings"
	"sort"
)

// Describes an app process running
type Task struct {
	Host string
	Port int
}

// An app may have multiple processes
type App struct {
	Id string
	EscapedId string
	HealthCheckPath string
	Tasks []Task
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type MarathonTaskList []MarathonTask

type MarathonTasks struct {
	Tasks MarathonTaskList `json:tasks`
}

type MarathonTask struct {
	AppId string
	Id    string
	Host  string
	Ports []int
	StartedAt string
	StagedAt  string
	Version   string
}

func (slice MarathonTaskList) Len() int {
	return len(slice)
}

func (slice MarathonTaskList) Less(i, j int) bool {
	return slice[i].StagedAt < slice[j].StagedAt
}

func (slice MarathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type MarathonApps struct {
	Apps []MarathonApp `json:apps`
}

type MarathonApp struct {
	Id string `json:id`
	HealthChecks []HealthChecks `json:healthChecks`
}

type HealthChecks struct {
	Path string `json:path`
}

func fetchMarathonApps(endpoint string) (map[string]MarathonApp, error) {
	response, err := http.Get(endpoint + "/v2/apps")

	if err != nil {
		return nil, err
	} else {
		defer response.Body.Close()
		var appResponse MarathonApps

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

		err = json.Unmarshal(contents, &appResponse)
		if err != nil {
			return nil, err
		}

		dataById := map[string]MarathonApp{}

		for _, appConfig := range appResponse.Apps {
			dataById[appConfig.Id] = appConfig
		}

		return dataById, nil
	}
}

func fetchTasks(endpoint string) (map[string][]MarathonTask, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", endpoint + "/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	response, err := client.Do(req)

	var tasks MarathonTasks

	if err != nil {
		return nil, err
	} else {
		contents, err := ioutil.ReadAll(response.Body)
		defer response.Body.Close()
		if err != nil { return nil, err }

		err = json.Unmarshal(contents, &tasks)
		if err != nil { return nil, err }

		taskList := tasks.Tasks
		sort.Sort(taskList)

		tasksById := map[string][]MarathonTask{}
		for _, task := range taskList {
			if tasksById[task.AppId] == nil {
				tasksById[task.AppId] = []MarathonTask{}
			}
			tasksById[task.AppId] = append(tasksById[task.AppId], task)
		}

		return tasksById, nil
	}
}

func createApps(tasksById map[string][]MarathonTask, marathonApps map[string]MarathonApp) AppList {

	apps := AppList{}

	for appId, tasks  := range tasksById {
			simpleTasks := []Task{}

			for _, task := range tasks {
				simpleTasks = append(simpleTasks, Task{ Host: task.Host, Port: task.Ports[0] })
			}

			// Try to handle old app id format without slashes
			appPath := appId
			if (!strings.HasPrefix(appId, "/")) {
				appPath = "/" + appId
			}

			app := App {
				// Since Marathon 0.7, apps are namespaced with path
				Id: appPath,
				// Used for template
				EscapedId: strings.Replace(appId, "/", "::", -1),
				Tasks: simpleTasks,
				HealthCheckPath: parseHealthCheckPath(marathonApps[appId].HealthChecks),
			}
			apps = append(apps, app)
	}
	return apps
}

func parseHealthCheckPath(checks []HealthChecks) string {
	if (len(checks) > 0) {
		return checks[0].Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(endpoint string) (AppList, error) {
	tasks, err := fetchTasks(endpoint)
	if err != nil { return nil, err }

	marathonApps, err := fetchMarathonApps(endpoint)
	if err != nil { return nil, err }

	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<commit_msg>Fix #24 Handle tasks without port assigned<commit_after>package marathon

import(
	"net/http"
	"io/ioutil"
	"encoding/json"
	"strings"
	"sort"
)

// Describes an app process running
type Task struct {
	Host string
	Port int
}

// An app may have multiple processes
type App struct {
	Id string
	EscapedId string
	HealthCheckPath string
	Tasks []Task
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type MarathonTaskList []MarathonTask

type MarathonTasks struct {
	Tasks MarathonTaskList `json:tasks`
}

type MarathonTask struct {
	AppId string
	Id    string
	Host  string
	Ports []int
	StartedAt string
	StagedAt  string
	Version   string
}

func (slice MarathonTaskList) Len() int {
	return len(slice)
}

func (slice MarathonTaskList) Less(i, j int) bool {
	return slice[i].StagedAt < slice[j].StagedAt
}

func (slice MarathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type MarathonApps struct {
	Apps []MarathonApp `json:apps`
}

type MarathonApp struct {
	Id string `json:id`
	HealthChecks []HealthChecks `json:healthChecks`
}

type HealthChecks struct {
	Path string `json:path`
}

func fetchMarathonApps(endpoint string) (map[string]MarathonApp, error) {
	response, err := http.Get(endpoint + "/v2/apps")

	if err != nil {
		return nil, err
	} else {
		defer response.Body.Close()
		var appResponse MarathonApps

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

		err = json.Unmarshal(contents, &appResponse)
		if err != nil {
			return nil, err
		}

		dataById := map[string]MarathonApp{}

		for _, appConfig := range appResponse.Apps {
			dataById[appConfig.Id] = appConfig
		}

		return dataById, nil
	}
}

func fetchTasks(endpoint string) (map[string][]MarathonTask, error) {
	client := &http.Client{}
	req, err := http.NewRequest("GET", endpoint + "/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	response, err := client.Do(req)

	var tasks MarathonTasks

	if err != nil {
		return nil, err
	} else {
		contents, err := ioutil.ReadAll(response.Body)
		defer response.Body.Close()
		if err != nil { return nil, err }

		err = json.Unmarshal(contents, &tasks)
		if err != nil { return nil, err }

		taskList := tasks.Tasks
		sort.Sort(taskList)

		tasksById := map[string][]MarathonTask{}
		for _, task := range taskList {
			if tasksById[task.AppId] == nil {
				tasksById[task.AppId] = []MarathonTask{}
			}
			tasksById[task.AppId] = append(tasksById[task.AppId], task)
		}

		return tasksById, nil
	}
}

func createApps(tasksById map[string][]MarathonTask, marathonApps map[string]MarathonApp) AppList {

	apps := AppList{}

	for appId, tasks  := range tasksById {
			simpleTasks := []Task{}

			for _, task := range tasks {
				if len(task.Ports) > 0 {
					simpleTasks = append(simpleTasks, Task{ Host: task.Host, Port: task.Ports[0] })
				}
			}

			// Try to handle old app id format without slashes
			appPath := appId
			if (!strings.HasPrefix(appId, "/")) {
				appPath = "/" + appId
			}

			app := App {
				// Since Marathon 0.7, apps are namespaced with path
				Id: appPath,
				// Used for template
				EscapedId: strings.Replace(appId, "/", "::", -1),
				Tasks: simpleTasks,
				HealthCheckPath: parseHealthCheckPath(marathonApps[appId].HealthChecks),
			}
			apps = append(apps, app)
	}
	return apps
}

func parseHealthCheckPath(checks []HealthChecks) string {
	if (len(checks) > 0) {
		return checks[0].Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(endpoint string) (AppList, error) {
	tasks, err := fetchTasks(endpoint)
	if err != nil { return nil, err }

	marathonApps, err := fetchMarathonApps(endpoint)
	if err != nil { return nil, err }

	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<|endoftext|>


<commit_before>package mysql

const (
	MinProtocolVersion byte   = 10
	MaxPayloadLen      int    = 1<<24 - 1
	TimeFormat         string = "2006-01-02 15:04:05"
	ServerVersion      string = "5.5.31-mixer-0.1"
)

const (
	OK_HEADER          byte = 0x00
	ERR_HEADER         byte = 0xff
	EOF_HEADER         byte = 0xfe
	LocalInFile_HEADER byte = 0xfb
)

const (
	SERVER_STATUS_IN_TRANS             uint16 = 0x0001
	SERVER_STATUS_AUTOCOMMIT                  = 0x0002
	SERVER_MORE_RESULTS_EXISTS                = 0x0008
	SERVER_STATUS_NO_GOOD_INDEX_USED          = 0x0010
	SERVER_STATUS_NO_INDEX_USED               = 0x0020
	SERVER_STATUS_CURSOR_EXISTS               = 0x0040
	SERVER_STATUS_LAST_ROW_SEND               = 0x0080
	SERVER_STATUS_DB_DROPPED                  = 0x0100
	SERVER_STATUS_NO_BACKSLASH_ESCAPED        = 0x0200
	SERVER_STATUS_METADATA_CHANGED            = 0x0400
	SERVER_QUERY_WAS_SLOW                     = 0x0800
	SERVER_PS_OUT_PARAMS                      = 0x1000
)

const (
	COM_SLEEP byte = iota
	COM_QUIT
	COM_INIT_DB
	COM_QUERY
	COM_FIELD_LIST
	COM_CREATE_DB
	COM_DROP_DB
	COM_REFRESH
	COM_SHUTDOWN
	COM_STATISTICS
	COM_PROCESS_INFO
	COM_CONNECT
	COM_PROCESS_KILL
	COM_DEBUG
	COM_PING
	COM_TIME
	COM_DELAYED_INSERT
	COM_CHANGE_USER
	COM_BINLOG_DUMP
	COM_TABLE_DUMP
	COM_CONNECT_OUT
	COM_REGISTER_SLAVE
	COM_STMT_PREPARE
	COM_STMT_EXECUTE
	COM_STMT_SEND_LONG_DATA
	COM_STMT_CLOSE
	COM_STMT_RESET
	COM_SET_OPTION
	COM_STMT_FETCH
	COM_DAEMON
	COM_BINLOG_DUMP_GTID
	COM_RESET_CONNECTION
)

const (
	CLIENT_LONG_PASSWORD uint32 = 1 << iota
	CLIENT_FOUND_ROWS
	CLIENT_LONG_FLAG
	CLIENT_CONNECT_WITH_DB
	CLIENT_NO_SCHEMA
	CLIENT_COMPRESS
	CLIENT_ODBC
	CLIENT_LOCAL_FILES
	CLIENT_IGNORE_SPACE
	CLIENT_PROTOCOL_41
	CLIENT_INTERACTIVE
	CLIENT_SSL
	CLIENT_IGNORE_SIGPIPE
	CLIENT_TRANSACTIONS
	CLIENT_RESERVED
	CLIENT_SECURE_CONNECTION
	CLIENT_MULTI_STATEMENTS
	CLIENT_MULTI_RESULTS
	CLIENT_PS_MULTI_RESULTS
	CLIENT_PLUGIN_AUTH
	CLIENT_CONNECT_ATTRS
	CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
)

const (
	MYSQL_TYPE_DECIMAL byte = iota
	MYSQL_TYPE_TINY
	MYSQL_TYPE_SHORT
	MYSQL_TYPE_LONG
	MYSQL_TYPE_FLOAT
	MYSQL_TYPE_DOUBLE
	MYSQL_TYPE_NULL
	MYSQL_TYPE_TIMESTAMP
	MYSQL_TYPE_LONGLONG
	MYSQL_TYPE_INT24
	MYSQL_TYPE_DATE
	MYSQL_TYPE_TIME
	MYSQL_TYPE_DATETIME
	MYSQL_TYPE_YEAR
	MYSQL_TYPE_NEWDATE
	MYSQL_TYPE_VARCHAR
	MYSQL_TYPE_BIT
)

const (
	MYSQL_TYPE_NEWDECIMAL byte = iota + 0xf6
	MYSQL_TYPE_ENUM
	MYSQL_TYPE_SET
	MYSQL_TYPE_TINY_BLOB
	MYSQL_TYPE_MEDIUM_BLOB
	MYSQL_TYPE_LONG_BLOB
	MYSQL_TYPE_BLOB
	MYSQL_TYPE_VAR_STRING
	MYSQL_TYPE_STRING
	MYSQL_TYPE_GEOMETRY
)

const (
	NOT_NULL_FLAG       = 1
	PRI_KEY_FLAG        = 2
	UNIQUE_KEY_FLAG     = 4
	BLOB_FLAG           = 16
	UNSIGNED_FLAG       = 32
	ZEROFILL_FLAG       = 64
	BINARY_FLAG         = 128
	ENUM_FLAG           = 256
	AUTO_INCREMENT_FLAG = 512
	TIMESTAMP_FLAG      = 1024
	SET_FLAG            = 2048
	NUM_FLAG            = 32768
	PART_KEY_FLAG       = 16384
	GROUP_FLAG          = 32768
	UNIQUE_FLAG         = 65536
)

const (
	DEFAULT_UTF8_CHARSET byte = 33

	AUTH_NAME = "mysql_native_password"
)
<commit_msg>update const type<commit_after>package mysql

const (
	MinProtocolVersion byte   = 10
	MaxPayloadLen      int    = 1<<24 - 1
	TimeFormat         string = "2006-01-02 15:04:05"
	ServerVersion      string = "5.5.31-mixer-0.1"
)

const (
	OK_HEADER          byte = 0x00
	ERR_HEADER         byte = 0xff
	EOF_HEADER         byte = 0xfe
	LocalInFile_HEADER byte = 0xfb
)

const (
	SERVER_STATUS_IN_TRANS             uint16 = 0x0001
	SERVER_STATUS_AUTOCOMMIT           uint16 = 0x0002
	SERVER_MORE_RESULTS_EXISTS         uint16 = 0x0008
	SERVER_STATUS_NO_GOOD_INDEX_USED   uint16 = 0x0010
	SERVER_STATUS_NO_INDEX_USED        uint16 = 0x0020
	SERVER_STATUS_CURSOR_EXISTS        uint16 = 0x0040
	SERVER_STATUS_LAST_ROW_SEND        uint16 = 0x0080
	SERVER_STATUS_DB_DROPPED           uint16 = 0x0100
	SERVER_STATUS_NO_BACKSLASH_ESCAPED uint16 = 0x0200
	SERVER_STATUS_METADATA_CHANGED     uint16 = 0x0400
	SERVER_QUERY_WAS_SLOW              uint16 = 0x0800
	SERVER_PS_OUT_PARAMS               uint16 = 0x1000
)

const (
	COM_SLEEP byte = iota
	COM_QUIT
	COM_INIT_DB
	COM_QUERY
	COM_FIELD_LIST
	COM_CREATE_DB
	COM_DROP_DB
	COM_REFRESH
	COM_SHUTDOWN
	COM_STATISTICS
	COM_PROCESS_INFO
	COM_CONNECT
	COM_PROCESS_KILL
	COM_DEBUG
	COM_PING
	COM_TIME
	COM_DELAYED_INSERT
	COM_CHANGE_USER
	COM_BINLOG_DUMP
	COM_TABLE_DUMP
	COM_CONNECT_OUT
	COM_REGISTER_SLAVE
	COM_STMT_PREPARE
	COM_STMT_EXECUTE
	COM_STMT_SEND_LONG_DATA
	COM_STMT_CLOSE
	COM_STMT_RESET
	COM_SET_OPTION
	COM_STMT_FETCH
	COM_DAEMON
	COM_BINLOG_DUMP_GTID
	COM_RESET_CONNECTION
)

const (
	CLIENT_LONG_PASSWORD uint32 = 1 << iota
	CLIENT_FOUND_ROWS
	CLIENT_LONG_FLAG
	CLIENT_CONNECT_WITH_DB
	CLIENT_NO_SCHEMA
	CLIENT_COMPRESS
	CLIENT_ODBC
	CLIENT_LOCAL_FILES
	CLIENT_IGNORE_SPACE
	CLIENT_PROTOCOL_41
	CLIENT_INTERACTIVE
	CLIENT_SSL
	CLIENT_IGNORE_SIGPIPE
	CLIENT_TRANSACTIONS
	CLIENT_RESERVED
	CLIENT_SECURE_CONNECTION
	CLIENT_MULTI_STATEMENTS
	CLIENT_MULTI_RESULTS
	CLIENT_PS_MULTI_RESULTS
	CLIENT_PLUGIN_AUTH
	CLIENT_CONNECT_ATTRS
	CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
)

const (
	MYSQL_TYPE_DECIMAL byte = iota
	MYSQL_TYPE_TINY
	MYSQL_TYPE_SHORT
	MYSQL_TYPE_LONG
	MYSQL_TYPE_FLOAT
	MYSQL_TYPE_DOUBLE
	MYSQL_TYPE_NULL
	MYSQL_TYPE_TIMESTAMP
	MYSQL_TYPE_LONGLONG
	MYSQL_TYPE_INT24
	MYSQL_TYPE_DATE
	MYSQL_TYPE_TIME
	MYSQL_TYPE_DATETIME
	MYSQL_TYPE_YEAR
	MYSQL_TYPE_NEWDATE
	MYSQL_TYPE_VARCHAR
	MYSQL_TYPE_BIT
)

const (
	MYSQL_TYPE_NEWDECIMAL byte = iota + 0xf6
	MYSQL_TYPE_ENUM
	MYSQL_TYPE_SET
	MYSQL_TYPE_TINY_BLOB
	MYSQL_TYPE_MEDIUM_BLOB
	MYSQL_TYPE_LONG_BLOB
	MYSQL_TYPE_BLOB
	MYSQL_TYPE_VAR_STRING
	MYSQL_TYPE_STRING
	MYSQL_TYPE_GEOMETRY
)

const (
	NOT_NULL_FLAG       = 1
	PRI_KEY_FLAG        = 2
	UNIQUE_KEY_FLAG     = 4
	BLOB_FLAG           = 16
	UNSIGNED_FLAG       = 32
	ZEROFILL_FLAG       = 64
	BINARY_FLAG         = 128
	ENUM_FLAG           = 256
	AUTO_INCREMENT_FLAG = 512
	TIMESTAMP_FLAG      = 1024
	SET_FLAG            = 2048
	NUM_FLAG            = 32768
	PART_KEY_FLAG       = 16384
	GROUP_FLAG          = 32768
	UNIQUE_FLAG         = 65536
)

const (
	DEFAULT_UTF8_CHARSET byte = 33

	AUTH_NAME = "mysql_native_password"
)
<|endoftext|>


<commit_before>package dht

import (
	"sync"

	key "github.com/ipfs/go-ipfs/blocks/key"
	notif "github.com/ipfs/go-ipfs/notifications"
	peer "github.com/ipfs/go-ipfs/p2p/peer"
	queue "github.com/ipfs/go-ipfs/p2p/peer/queue"
	"github.com/ipfs/go-ipfs/routing"
	u "github.com/ipfs/go-ipfs/util"
	pset "github.com/ipfs/go-ipfs/util/peerset"
	todoctr "github.com/ipfs/go-ipfs/util/todocounter"
	logging "github.com/ipfs/go-ipfs/vendor/QmQg1J6vikuXF9oDvm4wpdeAUvvkVEKW1EYDw9HhTMnP2b/go-log"

	process "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	ctxproc "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
)

var maxQueryConcurrency = AlphaValue

type dhtQuery struct {
	dht         *IpfsDHT
	key         key.Key   // the key we're querying for
	qfunc       queryFunc // the function to execute per peer
	concurrency int       // the concurrency parameter
}

type dhtQueryResult struct {
	value         []byte          // GetValue
	peer          peer.PeerInfo   // FindPeer
	providerPeers []peer.PeerInfo // GetProviders
	closerPeers   []peer.PeerInfo // *
	success       bool
}

// constructs query
func (dht *IpfsDHT) newQuery(k key.Key, f queryFunc) *dhtQuery {
	return &dhtQuery{
		key:         k,
		dht:         dht,
		qfunc:       f,
		concurrency: maxQueryConcurrency,
	}
}

// QueryFunc is a function that runs a particular query with a given peer.
// It returns either:
// - the value
// - a list of peers potentially better able to serve the query
// - an error
type queryFunc func(context.Context, peer.ID) (*dhtQueryResult, error)

// Run runs the query at hand. pass in a list of peers to use first.
func (q *dhtQuery) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	runner := newQueryRunner(q)
	return runner.Run(ctx, peers)
}

type dhtQueryRunner struct {
	query          *dhtQuery        // query to run
	peersSeen      *pset.PeerSet    // all peers queried. prevent querying same peer 2x
	peersToQuery   *queue.ChanQueue // peers remaining to be queried
	peersRemaining todoctr.Counter  // peersToQuery + currently processing

	result *dhtQueryResult // query result
	errs   u.MultiErr      // result errors. maybe should be a map[peer.ID]error

	rateLimit chan struct{} // processing semaphore
	log       logging.EventLogger

	runCtx context.Context

	proc process.Process
	sync.RWMutex
}

func newQueryRunner(q *dhtQuery) *dhtQueryRunner {
	proc := process.WithParent(process.Background())
	ctx := ctxproc.OnClosingContext(proc)
	return &dhtQueryRunner{
		query:          q,
		peersToQuery:   queue.NewChanQueue(ctx, queue.NewXORDistancePQ(q.key)),
		peersRemaining: todoctr.NewSyncCounter(),
		peersSeen:      pset.New(),
		rateLimit:      make(chan struct{}, q.concurrency),
		proc:           proc,
	}
}

func (r *dhtQueryRunner) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
	r.log = log
	r.runCtx = ctx

	if len(peers) == 0 {
		log.Warning("Running query with no peers!")
		return nil, nil
	}

	// setup concurrency rate limiting
	for i := 0; i < r.query.concurrency; i++ {
		r.rateLimit <- struct{}{}
	}

	// add all the peers we got first.
	for _, p := range peers {
		r.addPeerToQuery(p)
	}

	// go do this thing.
	// do it as a child proc to make sure Run exits
	// ONLY AFTER spawn workers has exited.
	r.proc.Go(r.spawnWorkers)

	// so workers are working.

	// wait until they're done.
	err := routing.ErrNotFound

	// now, if the context finishes, close the proc.
	// we have to do it here because the logic before is setup, which
	// should run without closing the proc.
	ctxproc.CloseAfterContext(r.proc, ctx)

	select {
	case <-r.peersRemaining.Done():
		r.proc.Close()
		r.RLock()
		defer r.RUnlock()

		err = routing.ErrNotFound

		// if every query to every peer failed, something must be very wrong.
		if len(r.errs) > 0 && len(r.errs) == r.peersSeen.Size() {
			log.Debugf("query errs: %s", r.errs)
			err = r.errs[0]
		}

	case <-r.proc.Closed():
		r.RLock()
		defer r.RUnlock()
		err = context.DeadlineExceeded
	}

	if r.result != nil && r.result.success {
		return r.result, nil
	}

	return nil, err
}

func (r *dhtQueryRunner) addPeerToQuery(next peer.ID) {
	// if new peer is ourselves...
	if next == r.query.dht.self {
		r.log.Debug("addPeerToQuery skip self")
		return
	}

	if !r.peersSeen.TryAdd(next) {
		return
	}

	notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
		Type: notif.AddingPeer,
		ID:   next,
	})

	r.peersRemaining.Increment(1)
	select {
	case r.peersToQuery.EnqChan <- next:
	case <-r.proc.Closing():
	}
}

func (r *dhtQueryRunner) spawnWorkers(proc process.Process) {
	for {

		select {
		case <-r.peersRemaining.Done():
			return

		case <-r.proc.Closing():
			return

		case <-r.rateLimit:
			select {
			case p, more := <-r.peersToQuery.DeqChan:
				if !more {
					return // channel closed.
				}

				// do it as a child func to make sure Run exits
				// ONLY AFTER spawn workers has exited.
				proc.Go(func(proc process.Process) {
					r.queryPeer(proc, p)
				})
			case <-r.proc.Closing():
				return
			case <-r.peersRemaining.Done():
				return
			}
		}
	}
}

func (r *dhtQueryRunner) queryPeer(proc process.Process, p peer.ID) {
	// ok let's do this!

	// create a context from our proc.
	ctx := ctxproc.OnClosingContext(proc)

	// make sure we do this when we exit
	defer func() {
		// signal we're done proccessing peer p
		r.peersRemaining.Decrement(1)
		r.rateLimit <- struct{}{}
	}()

	// make sure we're connected to the peer.
	// FIXME abstract away into the network layer
	if conns := r.query.dht.host.Network().ConnsToPeer(p); len(conns) == 0 {
		log.Error("not connected. dialing.")

		notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
			Type: notif.DialingPeer,
			ID:   p,
		})
		// while we dial, we do not take up a rate limit. this is to allow
		// forward progress during potentially very high latency dials.
		r.rateLimit <- struct{}{}

		pi := peer.PeerInfo{ID: p}

		if err := r.query.dht.host.Connect(ctx, pi); err != nil {
			log.Debugf("Error connecting: %s", err)

			notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
				Type:  notif.QueryError,
				Extra: err.Error(),
				ID:    p,
			})

			r.Lock()
			r.errs = append(r.errs, err)
			r.Unlock()
			<-r.rateLimit // need to grab it again, as we deferred.
			return
		}
		<-r.rateLimit // need to grab it again, as we deferred.
		log.Debugf("connected. dial success.")
	}

	// finally, run the query against this peer
	res, err := r.query.qfunc(ctx, p)

	if err != nil {
		log.Debugf("ERROR worker for: %v %v", p, err)
		r.Lock()
		r.errs = append(r.errs, err)
		r.Unlock()

	} else if res.success {
		log.Debugf("SUCCESS worker for: %v %s", p, res)
		r.Lock()
		r.result = res
		r.Unlock()
		go r.proc.Close() // signal to everyone that we're done.
		// must be async, as we're one of the children, and Close blocks.

	} else if len(res.closerPeers) > 0 {
		log.Debugf("PEERS CLOSER -- worker for: %v (%d closer peers)", p, len(res.closerPeers))
		for _, next := range res.closerPeers {
			if next.ID == r.query.dht.self { // dont add self.
				log.Debugf("PEERS CLOSER -- worker for: %v found self", p)
				continue
			}

			// add their addresses to the dialer's peerstore
			r.query.dht.peerstore.AddAddrs(next.ID, next.Addrs, peer.TempAddrTTL)
			r.addPeerToQuery(next.ID)
			log.Debugf("PEERS CLOSER -- worker for: %v added %v (%v)", p, next.ID, next.Addrs)
		}
	} else {
		log.Debugf("QUERY worker for: %v - not found, and no closer peers.", p)
	}
}
<commit_msg>drop error log down to debug<commit_after>package dht

import (
	"sync"

	key "github.com/ipfs/go-ipfs/blocks/key"
	notif "github.com/ipfs/go-ipfs/notifications"
	peer "github.com/ipfs/go-ipfs/p2p/peer"
	queue "github.com/ipfs/go-ipfs/p2p/peer/queue"
	"github.com/ipfs/go-ipfs/routing"
	u "github.com/ipfs/go-ipfs/util"
	pset "github.com/ipfs/go-ipfs/util/peerset"
	todoctr "github.com/ipfs/go-ipfs/util/todocounter"
	logging "github.com/ipfs/go-ipfs/vendor/QmQg1J6vikuXF9oDvm4wpdeAUvvkVEKW1EYDw9HhTMnP2b/go-log"

	process "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
	ctxproc "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
)

var maxQueryConcurrency = AlphaValue

type dhtQuery struct {
	dht         *IpfsDHT
	key         key.Key   // the key we're querying for
	qfunc       queryFunc // the function to execute per peer
	concurrency int       // the concurrency parameter
}

type dhtQueryResult struct {
	value         []byte          // GetValue
	peer          peer.PeerInfo   // FindPeer
	providerPeers []peer.PeerInfo // GetProviders
	closerPeers   []peer.PeerInfo // *
	success       bool
}

// constructs query
func (dht *IpfsDHT) newQuery(k key.Key, f queryFunc) *dhtQuery {
	return &dhtQuery{
		key:         k,
		dht:         dht,
		qfunc:       f,
		concurrency: maxQueryConcurrency,
	}
}

// QueryFunc is a function that runs a particular query with a given peer.
// It returns either:
// - the value
// - a list of peers potentially better able to serve the query
// - an error
type queryFunc func(context.Context, peer.ID) (*dhtQueryResult, error)

// Run runs the query at hand. pass in a list of peers to use first.
func (q *dhtQuery) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	runner := newQueryRunner(q)
	return runner.Run(ctx, peers)
}

type dhtQueryRunner struct {
	query          *dhtQuery        // query to run
	peersSeen      *pset.PeerSet    // all peers queried. prevent querying same peer 2x
	peersToQuery   *queue.ChanQueue // peers remaining to be queried
	peersRemaining todoctr.Counter  // peersToQuery + currently processing

	result *dhtQueryResult // query result
	errs   u.MultiErr      // result errors. maybe should be a map[peer.ID]error

	rateLimit chan struct{} // processing semaphore
	log       logging.EventLogger

	runCtx context.Context

	proc process.Process
	sync.RWMutex
}

func newQueryRunner(q *dhtQuery) *dhtQueryRunner {
	proc := process.WithParent(process.Background())
	ctx := ctxproc.OnClosingContext(proc)
	return &dhtQueryRunner{
		query:          q,
		peersToQuery:   queue.NewChanQueue(ctx, queue.NewXORDistancePQ(q.key)),
		peersRemaining: todoctr.NewSyncCounter(),
		peersSeen:      pset.New(),
		rateLimit:      make(chan struct{}, q.concurrency),
		proc:           proc,
	}
}

func (r *dhtQueryRunner) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
	r.log = log
	r.runCtx = ctx

	if len(peers) == 0 {
		log.Warning("Running query with no peers!")
		return nil, nil
	}

	// setup concurrency rate limiting
	for i := 0; i < r.query.concurrency; i++ {
		r.rateLimit <- struct{}{}
	}

	// add all the peers we got first.
	for _, p := range peers {
		r.addPeerToQuery(p)
	}

	// go do this thing.
	// do it as a child proc to make sure Run exits
	// ONLY AFTER spawn workers has exited.
	r.proc.Go(r.spawnWorkers)

	// so workers are working.

	// wait until they're done.
	err := routing.ErrNotFound

	// now, if the context finishes, close the proc.
	// we have to do it here because the logic before is setup, which
	// should run without closing the proc.
	ctxproc.CloseAfterContext(r.proc, ctx)

	select {
	case <-r.peersRemaining.Done():
		r.proc.Close()
		r.RLock()
		defer r.RUnlock()

		err = routing.ErrNotFound

		// if every query to every peer failed, something must be very wrong.
		if len(r.errs) > 0 && len(r.errs) == r.peersSeen.Size() {
			log.Debugf("query errs: %s", r.errs)
			err = r.errs[0]
		}

	case <-r.proc.Closed():
		r.RLock()
		defer r.RUnlock()
		err = context.DeadlineExceeded
	}

	if r.result != nil && r.result.success {
		return r.result, nil
	}

	return nil, err
}

func (r *dhtQueryRunner) addPeerToQuery(next peer.ID) {
	// if new peer is ourselves...
	if next == r.query.dht.self {
		r.log.Debug("addPeerToQuery skip self")
		return
	}

	if !r.peersSeen.TryAdd(next) {
		return
	}

	notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
		Type: notif.AddingPeer,
		ID:   next,
	})

	r.peersRemaining.Increment(1)
	select {
	case r.peersToQuery.EnqChan <- next:
	case <-r.proc.Closing():
	}
}

func (r *dhtQueryRunner) spawnWorkers(proc process.Process) {
	for {

		select {
		case <-r.peersRemaining.Done():
			return

		case <-r.proc.Closing():
			return

		case <-r.rateLimit:
			select {
			case p, more := <-r.peersToQuery.DeqChan:
				if !more {
					return // channel closed.
				}

				// do it as a child func to make sure Run exits
				// ONLY AFTER spawn workers has exited.
				proc.Go(func(proc process.Process) {
					r.queryPeer(proc, p)
				})
			case <-r.proc.Closing():
				return
			case <-r.peersRemaining.Done():
				return
			}
		}
	}
}

func (r *dhtQueryRunner) queryPeer(proc process.Process, p peer.ID) {
	// ok let's do this!

	// create a context from our proc.
	ctx := ctxproc.OnClosingContext(proc)

	// make sure we do this when we exit
	defer func() {
		// signal we're done proccessing peer p
		r.peersRemaining.Decrement(1)
		r.rateLimit <- struct{}{}
	}()

	// make sure we're connected to the peer.
	// FIXME abstract away into the network layer
	if conns := r.query.dht.host.Network().ConnsToPeer(p); len(conns) == 0 {
		log.Debug("not connected. dialing.")

		notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
			Type: notif.DialingPeer,
			ID:   p,
		})
		// while we dial, we do not take up a rate limit. this is to allow
		// forward progress during potentially very high latency dials.
		r.rateLimit <- struct{}{}

		pi := peer.PeerInfo{ID: p}

		if err := r.query.dht.host.Connect(ctx, pi); err != nil {
			log.Debugf("Error connecting: %s", err)

			notif.PublishQueryEvent(r.runCtx, &notif.QueryEvent{
				Type:  notif.QueryError,
				Extra: err.Error(),
				ID:    p,
			})

			r.Lock()
			r.errs = append(r.errs, err)
			r.Unlock()
			<-r.rateLimit // need to grab it again, as we deferred.
			return
		}
		<-r.rateLimit // need to grab it again, as we deferred.
		log.Debugf("connected. dial success.")
	}

	// finally, run the query against this peer
	res, err := r.query.qfunc(ctx, p)

	if err != nil {
		log.Debugf("ERROR worker for: %v %v", p, err)
		r.Lock()
		r.errs = append(r.errs, err)
		r.Unlock()

	} else if res.success {
		log.Debugf("SUCCESS worker for: %v %s", p, res)
		r.Lock()
		r.result = res
		r.Unlock()
		go r.proc.Close() // signal to everyone that we're done.
		// must be async, as we're one of the children, and Close blocks.

	} else if len(res.closerPeers) > 0 {
		log.Debugf("PEERS CLOSER -- worker for: %v (%d closer peers)", p, len(res.closerPeers))
		for _, next := range res.closerPeers {
			if next.ID == r.query.dht.self { // dont add self.
				log.Debugf("PEERS CLOSER -- worker for: %v found self", p)
				continue
			}

			// add their addresses to the dialer's peerstore
			r.query.dht.peerstore.AddAddrs(next.ID, next.Addrs, peer.TempAddrTTL)
			r.addPeerToQuery(next.ID)
			log.Debugf("PEERS CLOSER -- worker for: %v added %v (%v)", p, next.ID, next.Addrs)
		}
	} else {
		log.Debugf("QUERY worker for: %v - not found, and no closer peers.", p)
	}
}
<|endoftext|>