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

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

Issue 280813003: Merge _idleConnections and _activeConnections into one structure, _ConnectionTarget. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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 | « no previous file | no next file » | 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 1484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 } 1495 }
1496 1496
1497 class _ConnnectionInfo { 1497 class _ConnnectionInfo {
1498 final _HttpClientConnection connection; 1498 final _HttpClientConnection connection;
1499 final _Proxy proxy; 1499 final _Proxy proxy;
1500 1500
1501 _ConnnectionInfo(this.connection, this.proxy); 1501 _ConnnectionInfo(this.connection, this.proxy);
1502 } 1502 }
1503 1503
1504 1504
1505 class _ConnectionTarget {
1506 // Unique key for this connection target.
1507 final String key;
1508 final Set<_HttpClientConnection> idle = new HashSet();
Søren Gjesse 2014/05/22 08:03:23 Rename idle and active to _idle and _active to ind
Anders Johnsen 2014/05/23 07:47:55 Done.
1509 final Set<_HttpClientConnection> active = new HashSet();
1510
1511 _ConnectionTarget(this.key);
1512
1513 bool get isEmpty => idle.isEmpty && active.isEmpty;
1514
1515 void returnConnection(_HttpClientConnection connection) {
1516 assert(active.contains(connection));
1517 active.remove(connection);
1518 idle.add(connection);
1519 }
1520
1521 void connectionClosed(_HttpClientConnection connection) {
Søren Gjesse 2014/05/22 08:03:23 Add the assert from above here as well.
Anders Johnsen 2014/05/23 07:47:55 Done.
1522 active.remove(connection);
1523 idle.remove(connection);
1524 }
1525
1526 void close(bool force) {
1527 for (var c in idle.toList()) {
1528 c.close();
1529 }
1530 if (force) {
1531 for (var c in active.toList()) {
1532 c.destroy();
1533 }
1534 }
1535 }
1536 }
1537
1538
1505 class _HttpClient implements HttpClient { 1539 class _HttpClient implements HttpClient {
1506 bool _closing = false; 1540 bool _closing = false;
1507 final Map<String, Set<_HttpClientConnection>> _idleConnections 1541 final Map<String, _ConnectionTarget> _connectionTargets
1508 = new HashMap<String, Set<_HttpClientConnection>>(); 1542 = new HashMap<String, _ConnectionTarget>();
1509 final Map<String, Set<_HttpClientConnection>> _activeConnections
1510 = new HashMap<String, Set<_HttpClientConnection>>();
1511 final List<_Credentials> _credentials = []; 1543 final List<_Credentials> _credentials = [];
1512 final List<_ProxyCredentials> _proxyCredentials = []; 1544 final List<_ProxyCredentials> _proxyCredentials = [];
1513 Function _authenticate; 1545 Function _authenticate;
1514 Function _authenticateProxy; 1546 Function _authenticateProxy;
1515 Function _findProxy = HttpClient.findProxyFromEnvironment; 1547 Function _findProxy = HttpClient.findProxyFromEnvironment;
1516 Duration _idleTimeout = const Duration(seconds: 15); 1548 Duration _idleTimeout = const Duration(seconds: 15);
1517 Function _badCertificateCallback; 1549 Function _badCertificateCallback;
1518 1550
1519 Timer _noActiveTimer; 1551 Timer _noActiveTimer;
1520 1552
1521 Duration get idleTimeout => _idleTimeout; 1553 Duration get idleTimeout => _idleTimeout;
1522 1554
1523 String userAgent = _getHttpVersion(); 1555 String userAgent = _getHttpVersion();
1524 1556
1525 void set idleTimeout(Duration timeout) { 1557 void set idleTimeout(Duration timeout) {
1526 _idleTimeout = timeout; 1558 _idleTimeout = timeout;
1527 _idleConnections.values.forEach( 1559 for (var c in _connectionTargets.values) {
1528 (l) => l.forEach((c) { 1560 for (var idle in c.idle) {
1529 // Reset timer. This is fine, as it's not happening often. 1561 // Reset timer. This is fine, as it's not happening often.
1530 c.stopTimer(); 1562 idle.stopTimer();
1531 c.startTimer(); 1563 idle.startTimer();
1532 })); 1564 }
1565 }
1533 } 1566 }
1534 1567
1535 set badCertificateCallback(bool callback(X509Certificate cert, 1568 set badCertificateCallback(bool callback(X509Certificate cert,
1536 String host, 1569 String host,
1537 int port)) { 1570 int port)) {
1538 _badCertificateCallback = callback; 1571 _badCertificateCallback = callback;
1539 } 1572 }
1540 1573
1541 1574
1542 Future<HttpClientRequest> open(String method, 1575 Future<HttpClientRequest> open(String method,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 1611
1579 Future<HttpClientRequest> headUrl(Uri url) => _openUrl("head", url); 1612 Future<HttpClientRequest> headUrl(Uri url) => _openUrl("head", url);
1580 1613
1581 Future<HttpClientRequest> patch(String host, int port, String path) 1614 Future<HttpClientRequest> patch(String host, int port, String path)
1582 => open("patch", host, port, path); 1615 => open("patch", host, port, path);
1583 1616
1584 Future<HttpClientRequest> patchUrl(Uri url) => _openUrl("patch", url); 1617 Future<HttpClientRequest> patchUrl(Uri url) => _openUrl("patch", url);
1585 1618
1586 void close({bool force: false}) { 1619 void close({bool force: false}) {
1587 _closing = true; 1620 _closing = true;
1588 // Create flattened copy of _idleConnections, as 'destory' will manipulate 1621 _connectionTargets.values.toList().forEach((c) => c.close(force));
1589 // it. 1622 assert(!_connectionTargets.values.any((s) => s.idle.isNotEmpty));
1590 var idle = _idleConnections.values.fold( 1623 assert(!force || _connectionTargets.isEmpty);
1591 [],
1592 (l, e) {
1593 l.addAll(e);
1594 return l;
1595 });
1596 idle.forEach((e) {
1597 e.close();
1598 });
1599 assert(_idleConnections.isEmpty);
1600 if (force) {
1601 for (var connection in
1602 _activeConnections.values.expand((s) => s).toList()) {
1603 connection.destroy();
1604 }
1605 assert(_activeConnections.isEmpty);
1606 _activeConnections.clear();
1607 }
1608 } 1624 }
1609 1625
1610 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { 1626 set authenticate(Future<bool> f(Uri url, String scheme, String realm)) {
1611 _authenticate = f; 1627 _authenticate = f;
1612 } 1628 }
1613 1629
1614 void addCredentials(Uri url, String realm, HttpClientCredentials cr) => 1630 void addCredentials(Uri url, String realm, HttpClientCredentials cr) =>
1615 _credentials.add(new _SiteCredentials(url, realm, cr)); 1631 _credentials.add(new _SiteCredentials(url, realm, cr));
1616 1632
1617 set authenticateProxy( 1633 set authenticateProxy(
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 } 1712 }
1697 } 1713 }
1698 return request 1714 return request
1699 ..headers.chunkedTransferEncoding = false 1715 ..headers.chunkedTransferEncoding = false
1700 ..contentLength = 0; 1716 ..contentLength = 0;
1701 }); 1717 });
1702 } 1718 }
1703 1719
1704 // Return a live connection to the idle pool. 1720 // Return a live connection to the idle pool.
1705 void _returnConnection(_HttpClientConnection connection) { 1721 void _returnConnection(_HttpClientConnection connection) {
1706 var key = connection.key; 1722 _connectionTargets[connection.key].returnConnection(connection);
1707 _activeConnections[key].remove(connection);
1708 if (_activeConnections[key].isEmpty) {
1709 _activeConnections.remove(key);
1710 }
1711 if (_closing) {
1712 connection.close();
1713 return;
1714 }
1715 _idleConnections
1716 .putIfAbsent(key, () => new HashSet())
1717 .add(connection);
1718 connection.startTimer(); 1723 connection.startTimer();
1719 _updateTimers(); 1724 _updateTimers();
1720 } 1725 }
1721 1726
1722 // Remove a closed connnection from the active set. 1727 // Remove a closed connnection from the active set.
1723 void _connectionClosed(_HttpClientConnection connection) { 1728 void _connectionClosed(_HttpClientConnection connection) {
1724 connection.stopTimer(); 1729 connection.stopTimer();
1725 var key = connection.key; 1730 var connectionTarget = _connectionTargets[connection.key];
1726 if (_activeConnections.containsKey(key)) { 1731 if (connectionTarget != null) {
1727 _activeConnections[key].remove(connection); 1732 connectionTarget.connectionClosed(connection);
1728 if (_activeConnections[key].isEmpty) { 1733 if (connectionTarget.isEmpty) {
1729 _activeConnections.remove(key); 1734 _connectionTargets.remove(connection.key);
1730 } 1735 }
1736 _updateTimers();
1731 } 1737 }
1732 if (_idleConnections.containsKey(key)) {
1733 _idleConnections[key].remove(connection);
1734 if (_idleConnections[key].isEmpty) {
1735 _idleConnections.remove(key);
1736 }
1737 }
1738 _updateTimers();
1739 } 1738 }
1740 1739
1741 void _updateTimers() { 1740 void _updateTimers() {
1742 if (_activeConnections.isEmpty) { 1741 bool hasActive = _connectionTargets.values.any((t) => t.active.isNotEmpty);
Søren Gjesse 2014/05/22 08:03:23 Add hasActive (or hasActiveConnections) to Connect
Anders Johnsen 2014/05/23 07:47:55 Done.
1743 if (!_idleConnections.isEmpty && _noActiveTimer == null) { 1742 if (!hasActive) {
1743 bool hasIdle = _connectionTargets.values.any((t) => t.idle.isNotEmpty);
Søren Gjesse 2014/05/22 08:03:23 Add hasIdle (or hasIdleConnections) to ConnectionT
Anders Johnsen 2014/05/23 07:47:55 Done.
1744 if (hasIdle && _noActiveTimer == null) {
1744 _noActiveTimer = new Timer(const Duration(milliseconds: 100), () { 1745 _noActiveTimer = new Timer(const Duration(milliseconds: 100), () {
1745 _noActiveTimer = null; 1746 _noActiveTimer = null;
1746 if (_activeConnections.isEmpty) { 1747 bool hasActive =
1748 _connectionTargets.values.any((t) => t.active.isNotEmpty);
Søren Gjesse 2014/05/22 08:03:23 Ditto.
Anders Johnsen 2014/05/23 07:47:55 Done.
1749 if (!hasActive) {
1747 close(); 1750 close();
1748 _closing = false; 1751 _closing = false;
1749 } 1752 }
1750 }); 1753 });
1751 } 1754 }
1752 } else if (_noActiveTimer != null) { 1755 } else if (_noActiveTimer != null) {
1753 _noActiveTimer.cancel(); 1756 _noActiveTimer.cancel();
1754 _noActiveTimer = null; 1757 _noActiveTimer = null;
1755 } 1758 }
1756 } 1759 }
1757 1760
1758 // Get a new _HttpClientConnection, either from the idle pool or created from 1761 // Get a new _HttpClientConnection, either from the idle pool or created from
1759 // a new Socket. 1762 // a new Socket.
1760 Future<_ConnnectionInfo> _getConnection(String uriHost, 1763 Future<_ConnnectionInfo> _getConnection(String uriHost,
1761 int uriPort, 1764 int uriPort,
1762 _ProxyConfiguration proxyConf, 1765 _ProxyConfiguration proxyConf,
1763 bool isSecure) { 1766 bool isSecure) {
1764 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; 1767 Iterator<_Proxy> proxies = proxyConf.proxies.iterator;
1765 1768
1766 Future<_ConnnectionInfo> connect(error) { 1769 Future<_ConnnectionInfo> connect(error) {
1767 if (!proxies.moveNext()) return new Future.error(error); 1770 if (!proxies.moveNext()) return new Future.error(error);
1768 _Proxy proxy = proxies.current; 1771 _Proxy proxy = proxies.current;
1769 String host = proxy.isDirect ? uriHost: proxy.host; 1772 String host = proxy.isDirect ? uriHost: proxy.host;
1770 int port = proxy.isDirect ? uriPort: proxy.port; 1773 int port = proxy.isDirect ? uriPort: proxy.port;
1771 String key = _HttpClientConnection.makeKey(isSecure, host, port); 1774 String key = _HttpClientConnection.makeKey(isSecure, host, port);
1772 if (_idleConnections.containsKey(key)) { 1775 var connectionTarget = _connectionTargets[key];
1773 var connection = _idleConnections[key].first; 1776 if (connectionTarget != null && connectionTarget.idle.isNotEmpty) {
Søren Gjesse 2014/05/22 08:03:23 Add method getConnection to ConnectionTarget to av
Anders Johnsen 2014/05/23 07:47:55 Done.
1774 _idleConnections[key].remove(connection); 1777 var connection = connectionTarget.idle.first;
1775 if (_idleConnections[key].isEmpty) { 1778 connectionTarget.idle.remove(connection);
1776 _idleConnections.remove(key);
1777 }
1778 connection.stopTimer(); 1779 connection.stopTimer();
1779 _activeConnections 1780 connectionTarget.active.add(connection);
1780 .putIfAbsent(key, () => new HashSet())
1781 .add(connection);
1782 _updateTimers(); 1781 _updateTimers();
1783 return new Future.value(new _ConnnectionInfo(connection, proxy)); 1782 return new Future.value(new _ConnnectionInfo(connection, proxy));
1784 } 1783 }
1785 var currentBadCertificateCallback = _badCertificateCallback; 1784 var currentBadCertificateCallback = _badCertificateCallback;
1786 bool callback(X509Certificate certificate) => 1785 bool callback(X509Certificate certificate) =>
1787 currentBadCertificateCallback == null ? false : 1786 currentBadCertificateCallback == null ? false :
1788 currentBadCertificateCallback(certificate, uriHost, uriPort); 1787 currentBadCertificateCallback(certificate, uriHost, uriPort);
1789 Future socketFuture = (isSecure && proxy.isDirect 1788 Future socketFuture = (isSecure && proxy.isDirect
1790 ? SecureSocket.connect(host, 1789 ? SecureSocket.connect(host,
1791 port, 1790 port,
1792 sendClientCertificate: true, 1791 sendClientCertificate: true,
1793 onBadCertificate: callback) 1792 onBadCertificate: callback)
1794 : Socket.connect(host, port)); 1793 : Socket.connect(host, port));
1795 return socketFuture.then((socket) { 1794 return socketFuture.then((socket) {
1796 socket.setOption(SocketOption.TCP_NODELAY, true); 1795 socket.setOption(SocketOption.TCP_NODELAY, true);
1797 var connection = new _HttpClientConnection(key, socket, this); 1796 var connection = new _HttpClientConnection(key, socket, this);
1798 if (isSecure && !proxy.isDirect) { 1797 if (isSecure && !proxy.isDirect) {
1799 connection._dispose = true; 1798 connection._dispose = true;
1800 return connection.createProxyTunnel( 1799 return connection.createProxyTunnel(
1801 uriHost, uriPort, proxy, callback) 1800 uriHost, uriPort, proxy, callback)
1802 .then((tunnel) { 1801 .then((tunnel) {
1803 _activeConnections 1802 var connectionTarget = _connectionTargets
1804 .putIfAbsent(tunnel.key, () => new HashSet()) 1803 .putIfAbsent(tunnel.key,
1805 .add(tunnel); 1804 () => new _ConnectionTarget(tunnel.key));
1805 connectionTarget.active.add(tunnel);
Søren Gjesse 2014/05/22 08:03:23 Add method addConnection to ConnectionTarget
Anders Johnsen 2014/05/23 07:47:55 Done.
1806 return new _ConnnectionInfo(tunnel, proxy); 1806 return new _ConnnectionInfo(tunnel, proxy);
1807 }); 1807 });
1808 } else { 1808 } else {
1809 _activeConnections 1809 var connectionTarget = _connectionTargets
1810 .putIfAbsent(key, () => new HashSet()) 1810 .putIfAbsent(key, () => new _ConnectionTarget(key));
1811 .add(connection); 1811 connectionTarget.active.add(connection);
1812 return new _ConnnectionInfo(connection, proxy); 1812 return new _ConnnectionInfo(connection, proxy);
1813 } 1813 }
1814 }, onError: (error) { 1814 }, onError: (error) {
1815 // Continue with next proxy. 1815 // Continue with next proxy.
1816 return connect(error); 1816 return connect(error);
1817 }); 1817 });
1818 } 1818 }
1819 return connect(new HttpException("No proxies given")); 1819 return connect(new HttpException("No proxies given"));
1820 } 1820 }
1821 1821
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after
2636 const _RedirectInfo(this.statusCode, this.method, this.location); 2636 const _RedirectInfo(this.statusCode, this.method, this.location);
2637 } 2637 }
2638 2638
2639 String _getHttpVersion() { 2639 String _getHttpVersion() {
2640 var version = Platform.version; 2640 var version = Platform.version;
2641 // Only include major and minor version numbers. 2641 // Only include major and minor version numbers.
2642 int index = version.indexOf('.', version.indexOf('.') + 1); 2642 int index = version.indexOf('.', version.indexOf('.') + 1);
2643 version = version.substring(0, index); 2643 version = version.substring(0, index);
2644 return 'Dart/$version (dart:io)'; 2644 return 'Dart/$version (dart:io)';
2645 } 2645 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698