net.go (1230B)
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 5 package internal 6 7 // This file implements a network dialer that limits the number of concurrent connections. 8 // It is only used for API calls. 9 10 import ( 11 "log" 12 "net" 13 "runtime" 14 "sync" 15 "time" 16 ) 17 18 var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable. 19 20 func limitRelease() { 21 // non-blocking 22 select { 23 case <-limitSem: 24 default: 25 // This should not normally happen. 26 log.Print("appengine: unbalanced limitSem release!") 27 } 28 } 29 30 func limitDial(network, addr string) (net.Conn, error) { 31 limitSem <- 1 32 33 // Dial with a timeout in case the API host is MIA. 34 // The connection should normally be very fast. 35 conn, err := net.DialTimeout(network, addr, 10*time.Second) 36 if err != nil { 37 limitRelease() 38 return nil, err 39 } 40 lc := &limitConn{Conn: conn} 41 runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required 42 return lc, nil 43 } 44 45 type limitConn struct { 46 close sync.Once 47 net.Conn 48 } 49 50 func (lc *limitConn) Close() error { 51 defer lc.close.Do(func() { 52 limitRelease() 53 runtime.SetFinalizer(lc, nil) 54 }) 55 return lc.Conn.Close() 56 }