diff options
Diffstat (limited to 'Tools/Scripts/webkitpy/port/http_lock.py')
-rw-r--r-- | Tools/Scripts/webkitpy/port/http_lock.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/Tools/Scripts/webkitpy/port/http_lock.py b/Tools/Scripts/webkitpy/port/http_lock.py new file mode 100644 index 000000000..bdde37e32 --- /dev/null +++ b/Tools/Scripts/webkitpy/port/http_lock.py @@ -0,0 +1,137 @@ +# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged +# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# FIXME: rename this file, and add more text about how this is +# different from the base file_lock class. + +"""This class helps to block NRWT threads when more NRWTs run +perf, http and websocket tests in a same time.""" + +import logging +import os +import sys +import tempfile +import time + +from webkitpy.common.system.executive import Executive +from webkitpy.common.system.file_lock import FileLock +from webkitpy.common.system.filesystem import FileSystem + + +_log = logging.getLogger(__name__) + + +class HttpLock(object): + def __init__(self, lock_path, lock_file_prefix="WebKitHttpd.lock.", guard_lock="WebKit.lock", filesystem=None, executive=None, name='HTTP'): + self._executive = executive or Executive() + self._filesystem = filesystem or FileSystem() + self._lock_path = lock_path + if not self._lock_path: + # FIXME: FileSystem should have an accessor for tempdir() + self._lock_path = tempfile.gettempdir() + self._lock_file_prefix = lock_file_prefix + self._lock_file_path_prefix = self._filesystem.join(self._lock_path, self._lock_file_prefix) + self._guard_lock_file = self._filesystem.join(self._lock_path, guard_lock) + self._guard_lock = FileLock(self._guard_lock_file) + self._process_lock_file_name = "" + self._name = name + + def cleanup_http_lock(self): + """Delete the lock file if exists.""" + if self._filesystem.exists(self._process_lock_file_name): + _log.debug("Removing lock file: %s" % self._process_lock_file_name) + self._filesystem.remove(self._process_lock_file_name) + + def _extract_lock_number(self, lock_file_name): + """Return the lock number from lock file.""" + prefix_length = len(self._lock_file_path_prefix) + return int(lock_file_name[prefix_length:]) + + def _lock_file_list(self): + """Return the list of lock files sequentially.""" + lock_list = self._filesystem.glob(self._lock_file_path_prefix + '*') + lock_list.sort(key=self._extract_lock_number) + return lock_list + + def _next_lock_number(self): + """Return the next available lock number.""" + lock_list = self._lock_file_list() + if not lock_list: + return 0 + return self._extract_lock_number(lock_list[-1]) + 1 + + def _current_lock_pid(self): + """Return with the current lock pid. If the lock is not valid + it deletes the lock file.""" + lock_list = self._lock_file_list() + if not lock_list: + _log.debug("No lock file list") + return + try: + current_pid = self._filesystem.read_text_file(lock_list[0]) + if not (current_pid and self._executive.check_running_pid(int(current_pid))): + _log.debug("Removing stuck lock file: %s" % lock_list[0]) + self._filesystem.remove(lock_list[0]) + return + except IOError, e: + _log.debug("IOError: %s" % e) + return + except OSError, e: + _log.debug("OSError: %s" % e) + return + return int(current_pid) + + def _create_lock_file(self): + """The lock files are used to schedule the running test sessions in first + come first served order. The guard lock ensures that the lock numbers are + sequential.""" + if not self._filesystem.exists(self._lock_path): + _log.debug("Lock directory does not exist: %s" % self._lock_path) + return False + + if not self._guard_lock.acquire_lock(): + _log.debug("Guard lock timed out!") + return False + + self._process_lock_file_name = (self._lock_file_path_prefix + str(self._next_lock_number())) + _log.debug("Creating lock file: %s" % self._process_lock_file_name) + # FIXME: Executive.py should have an accessor for getpid() + self._filesystem.write_text_file(self._process_lock_file_name, str(os.getpid())) + self._guard_lock.release_lock() + return True + + def wait_for_httpd_lock(self): + """Create a lock file and wait until it's turn comes. If something goes wrong + it wont do any locking.""" + if not self._create_lock_file(): + _log.debug("Warning, %s locking failed!" % self._name) + return + + # FIXME: This can hang forever! + while self._current_lock_pid() != os.getpid(): + time.sleep(1) + + _log.debug("%s lock acquired" % self._name) |