net.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright 2014 Google Inc. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package internal
  5. // This file implements a network dialer that limits the number of concurrent connections.
  6. // It is only used for API calls.
  7. import (
  8. "log"
  9. "net"
  10. "runtime"
  11. "sync"
  12. "time"
  13. )
  14. var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable.
  15. func limitRelease() {
  16. // non-blocking
  17. select {
  18. case <-limitSem:
  19. default:
  20. // This should not normally happen.
  21. log.Print("appengine: unbalanced limitSem release!")
  22. }
  23. }
  24. func limitDial(network, addr string) (net.Conn, error) {
  25. limitSem <- 1
  26. // Dial with a timeout in case the API host is MIA.
  27. // The connection should normally be very fast.
  28. conn, err := net.DialTimeout(network, addr, 500*time.Millisecond)
  29. if err != nil {
  30. limitRelease()
  31. return nil, err
  32. }
  33. lc := &limitConn{Conn: conn}
  34. runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required
  35. return lc, nil
  36. }
  37. type limitConn struct {
  38. close sync.Once
  39. net.Conn
  40. }
  41. func (lc *limitConn) Close() error {
  42. defer lc.close.Do(func() {
  43. limitRelease()
  44. runtime.SetFinalizer(lc, nil)
  45. })
  46. return lc.Conn.Close()
  47. }