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

Unified Diff: gm/rebaseline_server/server.py

Issue 64273011: rebaseline_server: clean up thread locks (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: extract_some_common_code Created 7 years, 1 month 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 | « no previous file | tools/svn.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gm/rebaseline_server/server.py
===================================================================
--- gm/rebaseline_server/server.py (revision 12295)
+++ gm/rebaseline_server/server.py (working copy)
@@ -68,7 +68,7 @@
_SERVER = None # This gets filled in by main()
-def get_routable_ip_address():
+def _get_routable_ip_address():
epoger 2013/11/20 19:51:34 made this function private (it's only used interna
"""Returns routable IP address of this host (the IP address of its network
interface that would be used for most traffic, not its localhost
interface). See http://stackoverflow.com/a/166589 """
@@ -78,7 +78,24 @@
sock.close()
return host
+def _create_svn_checkout(dir_path, repo_url):
+ """Creates local checkout of an SVN repository at the specified directory
+ path, returning an svn.Svn object referring to the local checkout.
+ Args:
+ dir_path: path to the local checkout; if this directory does not yet exist,
+ it will be created and the repo will be checked out into it
+ repo_url: URL of SVN repo to check out into dir_path (unless the local
+ checkout already exists)
+ Returns: an svn.Svn object referring to the local checkout.
+ """
+ local_checkout = svn.Svn(dir_path)
+ if not os.path.isdir(dir_path):
+ os.makedirs(dir_path)
+ local_checkout.Checkout(repo_url, '.')
+ return local_checkout
+
+
class Server(object):
""" HTTP server for our HTML rebaseline viewer. """
@@ -105,7 +122,21 @@
self._export = export
self._editable = editable
self._reload_seconds = reload_seconds
+ self._actuals_repo = _create_svn_checkout(
+ dir_path=actuals_dir, repo_url=ACTUALS_SVN_REPO)
+ # We only update the expectations dir if the server was run with a
+ # nonzero --reload argument; otherwise, we expect the user to maintain
+ # her own expectations as she sees fit.
+ #
+ # TODO(epoger): Use git instead of svn to check out expectations, since
+ # the Skia repo is moving to git.
+ if reload_seconds:
+ self._expectations_repo = _create_svn_checkout(
+ dir_path=expectations_dir, repo_url=EXPECTATIONS_SVN_REPO)
+ else:
+ self._expectations_repo = None
+
def is_exported(self):
""" Returns true iff HTTP clients on other hosts are allowed to access
this server. """
@@ -124,52 +155,25 @@
""" Create or update self.results, based on the expectations in
self._expectations_dir and the latest actuals from skia-autogen.
"""
- with self._svn_update_lock:
- # self._svn_update_lock prevents us from updating the actual GM results
- # in multiple threads simultaneously
- logging.info('Updating actual GM results in %s from SVN repo %s ...' % (
- self._actuals_dir, ACTUALS_SVN_REPO))
- actuals_repo = svn.Svn(self._actuals_dir)
- if not os.path.isdir(self._actuals_dir):
- os.makedirs(self._actuals_dir)
- actuals_repo.Checkout(ACTUALS_SVN_REPO, '.')
- else:
- actuals_repo.Update('.')
- # We only update the expectations dir if the server was run with a
- # nonzero --reload argument; otherwise, we expect the user to maintain
- # her own expectations as she sees fit.
- #
- # self._svn_update_lock prevents us from updating the expected GM results
- # in multiple threads simultaneously
- #
- # TODO(epoger): Use git instead of svn to check out expectations, since
- # the Skia repo is moving to git.
- if self._reload_seconds:
- logging.info(
- 'Updating expected GM results in %s from SVN repo %s ...' % (
- self._expectations_dir, EXPECTATIONS_SVN_REPO))
- expectations_repo = svn.Svn(self._expectations_dir)
- if not os.path.isdir(self._expectations_dir):
- os.makedirs(self._expectations_dir)
- expectations_repo.Checkout(EXPECTATIONS_SVN_REPO, '.')
- else:
- expectations_repo.Update('.')
- # end of "with self._svn_update_lock:"
+ logging.info('Updating actual GM results in %s from SVN repo %s ...' % (
+ self._actuals_dir, ACTUALS_SVN_REPO))
+ self._actuals_repo.Update('.')
+ if self._expectations_repo:
+ logging.info(
+ 'Updating expected GM results in %s from SVN repo %s ...' % (
+ self._expectations_dir, EXPECTATIONS_SVN_REPO))
+ self._expectations_repo.Update('.')
+
logging.info(
('Parsing results from actuals in %s and expectations in %s, '
+ 'and generating pixel diffs (may take a while) ...') % (
self._actuals_dir, self._expectations_dir))
- new_results = results.Results(
+ self.results = results.Results(
actuals_root=self._actuals_dir,
expected_root=self._expectations_dir,
generated_images_root=GENERATED_IMAGES_ROOT)
- # Make sure we don't update self.results while a client is in the middle
- # of reading from it.
- with self.results_lock:
- self.results = new_results
-
def _result_reloader(self):
""" If --reload argument was specified, reload results at the appropriate
interval.
@@ -179,14 +183,12 @@
self.update_results()
def run(self):
- self.results_lock = thread.allocate_lock()
- self._svn_update_lock = thread.allocate_lock()
self.update_results()
thread.start_new_thread(self._result_reloader, ())
if self._export:
server_address = ('', self._port)
- host = get_routable_ip_address()
+ host = _get_routable_ip_address()
if self._editable:
logging.warning('Running with combination of "export" and "editable" '
'flags. Users on other machines will '
@@ -236,14 +238,18 @@
"""
logging.debug('do_GET_results: sending results of type "%s"' % type)
try:
+ # Since we must make multiple calls to the Results object, grab a
+ # reference to it in case it is updated to point at a new Results
+ # object within another thread.
+ #
# TODO(epoger): Rather than using a global variable for the handler
# to refer to the Server object, make Server a subclass of
# HTTPServer, and then it could be available to the handler via
# the handler's .server instance variable.
+ results_obj = _SERVER.results
+ response_dict = results_obj.get_results_of_type(type)
+ time_updated = results_obj.get_timestamp()
- with _SERVER.results_lock:
- response_dict = _SERVER.results.get_results_of_type(type)
- time_updated = _SERVER.results.get_timestamp()
response_dict['header'] = {
# Timestamps:
# 1. when this data was last updated
@@ -353,16 +359,19 @@
logging.debug('do_POST_edits: received new GM expectations data [%s]' %
data)
- with _SERVER.results_lock:
- oldResultsType = data['oldResultsType']
- oldResults = _SERVER.results.get_results_of_type(oldResultsType)
- oldResultsHash = str(hash(repr(oldResults['testData'])))
- if oldResultsHash != data['oldResultsHash']:
- raise Exception('results of type "%s" changed while the client was '
- 'making modifications. The client should reload the '
- 'results and submit the modifications again.' %
- oldResultsType)
- _SERVER.results.edit_expectations(data['modifications'])
+ # Since we must make multiple calls to the Results object, grab a
+ # reference to it in case it is updated to point at a new Results
+ # object within another thread.
+ results_obj = _SERVER.results
+ oldResultsType = data['oldResultsType']
+ oldResults = results_obj.get_results_of_type(oldResultsType)
+ oldResultsHash = str(hash(repr(oldResults['testData'])))
+ if oldResultsHash != data['oldResultsHash']:
+ raise Exception('results of type "%s" changed while the client was '
+ 'making modifications. The client should reload the '
+ 'results and submit the modifications again.' %
+ oldResultsType)
+ results_obj.edit_expectations(data['modifications'])
# Now that the edits have been committed, update results to reflect them.
_SERVER.update_results()
« no previous file with comments | « no previous file | tools/svn.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698