Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
		
							
								
								
									
										48
									
								
								vendor/golang.org/x/net/netutil/listen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/golang.org/x/net/netutil/listen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// Copyright 2013 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package netutil provides network utility functions, complementing the more
 | 
			
		||||
// common ones in the net package.
 | 
			
		||||
package netutil // import "golang.org/x/net/netutil"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LimitListener returns a Listener that accepts at most n simultaneous
 | 
			
		||||
// connections from the provided Listener.
 | 
			
		||||
func LimitListener(l net.Listener, n int) net.Listener {
 | 
			
		||||
	return &limitListener{l, make(chan struct{}, n)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type limitListener struct {
 | 
			
		||||
	net.Listener
 | 
			
		||||
	sem chan struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *limitListener) acquire() { l.sem <- struct{}{} }
 | 
			
		||||
func (l *limitListener) release() { <-l.sem }
 | 
			
		||||
 | 
			
		||||
func (l *limitListener) Accept() (net.Conn, error) {
 | 
			
		||||
	l.acquire()
 | 
			
		||||
	c, err := l.Listener.Accept()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.release()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &limitListenerConn{Conn: c, release: l.release}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type limitListenerConn struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	releaseOnce sync.Once
 | 
			
		||||
	release     func()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *limitListenerConn) Close() error {
 | 
			
		||||
	err := l.Conn.Close()
 | 
			
		||||
	l.releaseOnce.Do(l.release)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										101
									
								
								vendor/golang.org/x/net/netutil/listen_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/golang.org/x/net/netutil/listen_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
// Copyright 2013 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package netutil
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/internal/nettest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLimitListener(t *testing.T) {
 | 
			
		||||
	const max = 5
 | 
			
		||||
	attempts := (nettest.MaxOpenFiles() - max) / 2
 | 
			
		||||
	if attempts > 256 { // maximum length of accept queue is 128 by default
 | 
			
		||||
		attempts = 256
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l, err := net.Listen("tcp", "127.0.0.1:0")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer l.Close()
 | 
			
		||||
	l = LimitListener(l, max)
 | 
			
		||||
 | 
			
		||||
	var open int32
 | 
			
		||||
	go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		if n := atomic.AddInt32(&open, 1); n > max {
 | 
			
		||||
			t.Errorf("%d open connections, want <= %d", n, max)
 | 
			
		||||
		}
 | 
			
		||||
		defer atomic.AddInt32(&open, -1)
 | 
			
		||||
		time.Sleep(10 * time.Millisecond)
 | 
			
		||||
		fmt.Fprint(w, "some body")
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
	var wg sync.WaitGroup
 | 
			
		||||
	var failed int32
 | 
			
		||||
	for i := 0; i < attempts; i++ {
 | 
			
		||||
		wg.Add(1)
 | 
			
		||||
		go func() {
 | 
			
		||||
			defer wg.Done()
 | 
			
		||||
			c := http.Client{Timeout: 3 * time.Second}
 | 
			
		||||
			r, err := c.Get("http://" + l.Addr().String())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Log(err)
 | 
			
		||||
				atomic.AddInt32(&failed, 1)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			defer r.Body.Close()
 | 
			
		||||
			io.Copy(ioutil.Discard, r.Body)
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
 | 
			
		||||
	// We expect some Gets to fail as the kernel's accept queue is filled,
 | 
			
		||||
	// but most should succeed.
 | 
			
		||||
	if int(failed) >= attempts/2 {
 | 
			
		||||
		t.Errorf("%d requests failed within %d attempts", failed, attempts)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type errorListener struct {
 | 
			
		||||
	net.Listener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (errorListener) Accept() (net.Conn, error) {
 | 
			
		||||
	return nil, errFake
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errFake = errors.New("fake error from errorListener")
 | 
			
		||||
 | 
			
		||||
// This used to hang.
 | 
			
		||||
func TestLimitListenerError(t *testing.T) {
 | 
			
		||||
	donec := make(chan bool, 1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		const n = 2
 | 
			
		||||
		ll := LimitListener(errorListener{}, n)
 | 
			
		||||
		for i := 0; i < n+1; i++ {
 | 
			
		||||
			_, err := ll.Accept()
 | 
			
		||||
			if err != errFake {
 | 
			
		||||
				t.Fatalf("Accept error = %v; want errFake", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		donec <- true
 | 
			
		||||
	}()
 | 
			
		||||
	select {
 | 
			
		||||
	case <-donec:
 | 
			
		||||
	case <-time.After(5 * time.Second):
 | 
			
		||||
		t.Fatal("timeout. deadlock?")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user