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

Unified Diff: build/android/pylib/ports.py

Issue 10689132: [android] Upstream / sync most of build/android and build/android/pylib. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/pylib/perf_tests_helper.py ('k') | build/android/pylib/run_tests_helper.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/ports.py
diff --git a/build/android/pylib/ports.py b/build/android/pylib/ports.py
new file mode 100644
index 0000000000000000000000000000000000000000..be994c362c74a0ec26f98688d72fb573fc20cfa6
--- /dev/null
+++ b/build/android/pylib/ports.py
@@ -0,0 +1,160 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Functions that deals with local and device ports."""
+
+import contextlib
+import fcntl
+import httplib
+import logging
+import os
+import re
+import socket
+import traceback
+
+import cmd_helper
+import constants
+
+
+#The following two methods are used to allocate the port source for various
+# types of test servers. Because some net relates tests can be run on shards
+# at same time, it's important to have a mechanism to allocate the port process
+# safe. In here, we implement the safe port allocation by leveraging flock.
+def ResetTestServerPortAllocation():
+ """Reset the port allocation to start from TEST_SERVER_PORT_FIRST.
+
+ Returns:
+ Returns True if reset successes. Otherwise returns False.
+ """
+ try:
+ with open(constants.TEST_SERVER_PORT_FILE, 'w') as fp:
+ fp.write('%d' % constants.TEST_SERVER_PORT_FIRST)
+ if os.path.exists(constants.TEST_SERVER_PORT_LOCKFILE):
+ os.unlink(constants.TEST_SERVER_PORT_LOCKFILE)
+ return True
+ except Exception as e:
+ logging.error(e)
+ return False
+
+
+def AllocateTestServerPort():
+ """Allocate a port incrementally.
+
+ Returns:
+ Returns a valid port which should be in between TEST_SERVER_PORT_FIRST and
+ TEST_SERVER_PORT_LAST. Returning 0 means no more valid port can be used.
+ """
+ port = 0
+ try:
+ fp_lock = open(constants.TEST_SERVER_PORT_LOCKFILE, 'w')
+ fcntl.flock(fp_lock, fcntl.LOCK_EX)
+ # Get current valid port and calculate next valid port.
+ assert os.path.exists(constants.TEST_SERVER_PORT_FILE)
+ with open(constants.TEST_SERVER_PORT_FILE, 'r+') as fp:
+ port = int(fp.read())
+ while IsHostPortUsed(port):
+ port += 1
+ if (port > constants.TEST_SERVER_PORT_LAST or
+ port < constants.TEST_SERVER_PORT_FIRST):
+ port = 0
+ else:
+ fp.seek(0, os.SEEK_SET)
+ fp.write('%d' % (port + 1))
+ except Exception as e:
+ logging.info(e)
+ finally:
+ if fp_lock:
+ fcntl.flock(fp_lock, fcntl.LOCK_UN)
+ fp_lock.close()
+ logging.info('Allocate port %d for test server.', port)
+ return port
+
+
+def IsHostPortUsed(host_port):
+ """Checks whether the specified host port is used or not.
+
+ Uses -n -P to inhibit the conversion of host/port numbers to host/port names.
+
+ Args:
+ host_port: Port on host we want to check.
+
+ Returns:
+ True if the port on host is already used, otherwise returns False.
+ """
+ port_info = '(127\.0\.0\.1)|(localhost)\:%d' % host_port
+ # TODO(jnd): Find a better way to filter the port.
+ re_port = re.compile(port_info, re.MULTILINE)
+ if re_port.findall(cmd_helper.GetCmdOutput(['lsof', '-nPi:%d' % host_port])):
+ return True
+ return False
+
+
+def IsDevicePortUsed(adb, device_port, state=''):
+ """Checks whether the specified device port is used or not.
+
+ Args:
+ adb: Instance of AndroidCommands for talking to the device.
+ device_port: Port on device we want to check.
+ state: String of the specified state. Default is empty string, which
+ means any state.
+
+ Returns:
+ True if the port on device is already used, otherwise returns False.
+ """
+ base_url = '127.0.0.1:%d' % device_port
+ netstat_results = adb.RunShellCommand('netstat', log_result=False)
+ for single_connect in netstat_results:
+ # Column 3 is the local address which we want to check with.
+ connect_results = single_connect.split()
+ is_state_match = connect_results[5] == state if state else True
+ if connect_results[3] == base_url and is_state_match:
+ return True
+ return False
+
+
+def IsHttpServerConnectable(host, port, tries=3, command='GET', path='/',
+ expected_read='', timeout=2):
+ """Checks whether the specified http server is ready to serve request or not.
+
+ Args:
+ host: Host name of the HTTP server.
+ port: Port number of the HTTP server.
+ tries: How many times we want to test the connection. The default value is
+ 3.
+ command: The http command we use to connect to HTTP server. The default
+ command is 'GET'.
+ path: The path we use when connecting to HTTP server. The default path is
+ '/'.
+ expected_read: The content we expect to read from the response. The default
+ value is ''.
+ timeout: Timeout (in seconds) for each http connection. The default is 2s.
+
+ Returns:
+ Tuple of (connect status, client error). connect status is a boolean value
+ to indicate whether the server is connectable. client_error is the error
+ message the server returns when connect status is false.
+ """
+ assert tries >= 1
+ for i in xrange(0, tries):
+ client_error = None
+ try:
+ with contextlib.closing(httplib.HTTPConnection(
+ host, port, timeout=timeout)) as http:
+ # Output some debug information when we have tried more than 2 times.
+ http.set_debuglevel(i >= 2)
+ http.request(command, path)
+ r = http.getresponse()
+ content = r.read()
+ if r.status == 200 and r.reason == 'OK' and content == expected_read:
+ return (True, '')
+ client_error = ('Bad response: %s %s version %s\n ' %
+ (r.status, r.reason, r.version) +
+ '\n '.join([': '.join(h) for h in r.getheaders()]))
+ except (httplib.HTTPException, socket.error) as e:
+ # Probably too quick connecting: try again.
+ exception_error_msgs = traceback.format_exception_only(type(e), e)
+ if exception_error_msgs:
+ client_error = ''.join(exception_error_msgs)
+ # Only returns last client_error.
+ return (False, client_error or 'Timeout')
« no previous file with comments | « build/android/pylib/perf_tests_helper.py ('k') | build/android/pylib/run_tests_helper.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698