Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 311513002: Enable throttleing of HttpClient per host, with default being 6. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/io/http.dart ('k') | sdk/lib/io/io.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.io; 5 part of dart.io;
6 6
7 const int _OUTGOING_BUFFER_SIZE = 8 * 1024; 7 const int _OUTGOING_BUFFER_SIZE = 8 * 1024;
8 8
9 class _HttpIncoming extends Stream<List<int>> { 9 class _HttpIncoming extends Stream<List<int>> {
10 final int _transferLength; 10 final int _transferLength;
(...skipping 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 1515
1516 1516
1517 class _ConnectionTarget { 1517 class _ConnectionTarget {
1518 // Unique key for this connection target. 1518 // Unique key for this connection target.
1519 final String key; 1519 final String key;
1520 final String host; 1520 final String host;
1521 final int port; 1521 final int port;
1522 final bool isSecure; 1522 final bool isSecure;
1523 final Set<_HttpClientConnection> _idle = new HashSet(); 1523 final Set<_HttpClientConnection> _idle = new HashSet();
1524 final Set<_HttpClientConnection> _active = new HashSet(); 1524 final Set<_HttpClientConnection> _active = new HashSet();
1525 final Queue _pending = new ListQueue();
1525 int _connecting = 0; 1526 int _connecting = 0;
1526 1527
1527 _ConnectionTarget(this.key, this.host, this.port, this.isSecure); 1528 _ConnectionTarget(this.key, this.host, this.port, this.isSecure);
1528 1529
1529 bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0; 1530 bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0;
1530 1531
1531 bool get hasIdle => _idle.isNotEmpty; 1532 bool get hasIdle => _idle.isNotEmpty;
1532 1533
1533 bool get hasActive => _active.isNotEmpty && _connecting > 0; 1534 bool get hasActive => _active.isNotEmpty || _connecting > 0;
1534 1535
1535 _HttpClientConnection takeIdle() { 1536 _HttpClientConnection takeIdle() {
1536 assert(hasIdle); 1537 assert(hasIdle);
1537 _HttpClientConnection connection = _idle.first; 1538 _HttpClientConnection connection = _idle.first;
1538 _idle.remove(connection); 1539 _idle.remove(connection);
1539 connection.stopTimer(); 1540 connection.stopTimer();
1540 _active.add(connection); 1541 _active.add(connection);
1541 return connection; 1542 return connection;
1542 } 1543 }
1543 1544
1545 _checkPending() {
1546 if (_pending.isNotEmpty) {
1547 _pending.removeFirst()();
1548 }
1549 }
1550
1544 void addNewActive(_HttpClientConnection connection) { 1551 void addNewActive(_HttpClientConnection connection) {
1545 _active.add(connection); 1552 _active.add(connection);
1546 } 1553 }
1547 1554
1548 void returnConnection(_HttpClientConnection connection) { 1555 void returnConnection(_HttpClientConnection connection) {
1549 assert(_active.contains(connection)); 1556 assert(_active.contains(connection));
1550 _active.remove(connection); 1557 _active.remove(connection);
1551 _idle.add(connection); 1558 _idle.add(connection);
1559 connection.startTimer();
1560 _checkPending();
1552 } 1561 }
1553 1562
1554 void connectionClosed(_HttpClientConnection connection) { 1563 void connectionClosed(_HttpClientConnection connection) {
1555 assert(!_active.contains(connection) || !_idle.contains(connection)); 1564 assert(!_active.contains(connection) || !_idle.contains(connection));
1556 _active.remove(connection); 1565 _active.remove(connection);
1557 _idle.remove(connection); 1566 _idle.remove(connection);
1567 _checkPending();
1558 } 1568 }
1559 1569
1560 void close(bool force) { 1570 void close(bool force) {
1561 for (var c in _idle.toList()) { 1571 for (var c in _idle.toList()) {
1562 c.close(); 1572 c.close();
1563 } 1573 }
1564 if (force) { 1574 if (force) {
1565 for (var c in _active.toList()) { 1575 for (var c in _active.toList()) {
1566 c.destroy(); 1576 c.destroy();
1567 } 1577 }
1568 } 1578 }
1569 } 1579 }
1570 1580
1571 Future<_ConnectionInfo> connect(String uriHost, 1581 Future<_ConnectionInfo> connect(String uriHost,
1572 int uriPort, 1582 int uriPort,
1573 _Proxy proxy, 1583 _Proxy proxy,
1574 _HttpClient client) { 1584 _HttpClient client) {
1575 if (hasIdle) { 1585 if (hasIdle) {
1576 var connection = takeIdle(); 1586 var connection = takeIdle();
1577 client._updateTimers(); 1587 client._updateTimers();
1578 return new Future.value(new _ConnectionInfo(connection, proxy)); 1588 return new Future.value(new _ConnectionInfo(connection, proxy));
1579 } 1589 }
1590 if (client.maxConnectionsPerHost != null &&
1591 _active.length + _connecting >= client.maxConnectionsPerHost) {
1592 var completer = new Completer();
1593 _pending.add(() {
1594 connect(uriHost, uriPort, proxy, client)
1595 .then(completer.complete, onError: completer.completeError);
1596 });
1597 return completer.future;
1598 }
1580 var currentBadCertificateCallback = client._badCertificateCallback; 1599 var currentBadCertificateCallback = client._badCertificateCallback;
1581 bool callback(X509Certificate certificate) => 1600 bool callback(X509Certificate certificate) =>
1582 currentBadCertificateCallback == null ? false : 1601 currentBadCertificateCallback == null ? false :
1583 currentBadCertificateCallback(certificate, uriHost, uriPort); 1602 currentBadCertificateCallback(certificate, uriHost, uriPort);
1584 Future socketFuture = (isSecure && proxy.isDirect 1603 Future socketFuture = (isSecure && proxy.isDirect
1585 ? SecureSocket.connect(host, 1604 ? SecureSocket.connect(host,
1586 port, 1605 port,
1587 sendClientCertificate: true, 1606 sendClientCertificate: true,
1588 onBadCertificate: callback) 1607 onBadCertificate: callback)
1589 : Socket.connect(host, port)); 1608 : Socket.connect(host, port));
1590 _connecting++; 1609 _connecting++;
1591 return socketFuture.then((socket) { 1610 return socketFuture.then((socket) {
1592 _connecting--; 1611 _connecting--;
1593 socket.setOption(SocketOption.TCP_NODELAY, true); 1612 socket.setOption(SocketOption.TCP_NODELAY, true);
1594 var connection = new _HttpClientConnection(key, socket, client); 1613 var connection = new _HttpClientConnection(key, socket, client);
1595 if (isSecure && !proxy.isDirect) { 1614 if (isSecure && !proxy.isDirect) {
1596 connection._dispose = true; 1615 connection._dispose = true;
1597 return connection.createProxyTunnel(uriHost, uriPort, proxy, callback) 1616 return connection.createProxyTunnel(uriHost, uriPort, proxy, callback)
1598 .then((tunnel) { 1617 .then((tunnel) {
1599 client._getConnectionTarget(uriHost, uriPort, true) 1618 client._getConnectionTarget(uriHost, uriPort, true)
1600 .addNewActive(tunnel); 1619 .addNewActive(tunnel);
1601 return new _ConnectionInfo(tunnel, proxy); 1620 return new _ConnectionInfo(tunnel, proxy);
1602 }); 1621 });
1603 } else { 1622 } else {
1604 addNewActive(connection); 1623 addNewActive(connection);
1605 return new _ConnectionInfo(connection, proxy); 1624 return new _ConnectionInfo(connection, proxy);
1606 } 1625 }
1626 }, onError: (error) {
1627 _connecting--;
1628 _checkPending();
1629 throw error;
1607 }); 1630 });
1608 } 1631 }
1609 } 1632 }
1610 1633
1611 1634
1612 class _HttpClient implements HttpClient { 1635 class _HttpClient implements HttpClient {
1613 bool _closing = false; 1636 bool _closing = false;
1614 final Map<String, _ConnectionTarget> _connectionTargets 1637 final Map<String, _ConnectionTarget> _connectionTargets
1615 = new HashMap<String, _ConnectionTarget>(); 1638 = new HashMap<String, _ConnectionTarget>();
1616 final List<_Credentials> _credentials = []; 1639 final List<_Credentials> _credentials = [];
1617 final List<_ProxyCredentials> _proxyCredentials = []; 1640 final List<_ProxyCredentials> _proxyCredentials = [];
1618 Function _authenticate; 1641 Function _authenticate;
1619 Function _authenticateProxy; 1642 Function _authenticateProxy;
1620 Function _findProxy = HttpClient.findProxyFromEnvironment; 1643 Function _findProxy = HttpClient.findProxyFromEnvironment;
1621 Duration _idleTimeout = const Duration(seconds: 15); 1644 Duration _idleTimeout = const Duration(seconds: 15);
1622 Function _badCertificateCallback; 1645 Function _badCertificateCallback;
1623 1646
1624 Timer _noActiveTimer; 1647 Timer _noActiveTimer;
1625 1648
1626 Duration get idleTimeout => _idleTimeout; 1649 Duration get idleTimeout => _idleTimeout;
1627 1650
1651 int maxConnectionsPerHost;
1652
1628 String userAgent = _getHttpVersion(); 1653 String userAgent = _getHttpVersion();
1629 1654
1630 void set idleTimeout(Duration timeout) { 1655 void set idleTimeout(Duration timeout) {
1631 _idleTimeout = timeout; 1656 _idleTimeout = timeout;
1632 for (var c in _connectionTargets.values) { 1657 for (var c in _connectionTargets.values) {
1633 for (var idle in c.idle) { 1658 for (var idle in c.idle) {
1634 // Reset timer. This is fine, as it's not happening often. 1659 // Reset timer. This is fine, as it's not happening often.
1635 idle.stopTimer(); 1660 idle.stopTimer();
1636 idle.startTimer(); 1661 idle.startTimer();
1637 } 1662 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 } 1812 }
1788 return request 1813 return request
1789 ..headers.chunkedTransferEncoding = false 1814 ..headers.chunkedTransferEncoding = false
1790 ..contentLength = 0; 1815 ..contentLength = 0;
1791 }); 1816 });
1792 } 1817 }
1793 1818
1794 // Return a live connection to the idle pool. 1819 // Return a live connection to the idle pool.
1795 void _returnConnection(_HttpClientConnection connection) { 1820 void _returnConnection(_HttpClientConnection connection) {
1796 _connectionTargets[connection.key].returnConnection(connection); 1821 _connectionTargets[connection.key].returnConnection(connection);
1797 connection.startTimer();
1798 _updateTimers(); 1822 _updateTimers();
1799 } 1823 }
1800 1824
1801 // Remove a closed connnection from the active set. 1825 // Remove a closed connnection from the active set.
1802 void _connectionClosed(_HttpClientConnection connection) { 1826 void _connectionClosed(_HttpClientConnection connection) {
1803 connection.stopTimer(); 1827 connection.stopTimer();
1804 var connectionTarget = _connectionTargets[connection.key]; 1828 var connectionTarget = _connectionTargets[connection.key];
1805 if (connectionTarget != null) { 1829 if (connectionTarget != null) {
1806 connectionTarget.connectionClosed(connection); 1830 connectionTarget.connectionClosed(connection);
1807 if (connectionTarget.isEmpty) { 1831 if (connectionTarget.isEmpty) {
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after
2729 const _RedirectInfo(this.statusCode, this.method, this.location); 2753 const _RedirectInfo(this.statusCode, this.method, this.location);
2730 } 2754 }
2731 2755
2732 String _getHttpVersion() { 2756 String _getHttpVersion() {
2733 var version = Platform.version; 2757 var version = Platform.version;
2734 // Only include major and minor version numbers. 2758 // Only include major and minor version numbers.
2735 int index = version.indexOf('.', version.indexOf('.') + 1); 2759 int index = version.indexOf('.', version.indexOf('.') + 1);
2736 version = version.substring(0, index); 2760 version = version.substring(0, index);
2737 return 'Dart/$version (dart:io)'; 2761 return 'Dart/$version (dart:io)';
2738 } 2762 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http.dart ('k') | sdk/lib/io/io.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698