Example #1
0
 def shutdown(self, tid=None):
     """Free `Repository` instances bound to a given thread identifier"""
     if tid:
         assert tid == threading._get_ident()
         with self._lock:
             repositories = self._cache.pop(tid, {})
             for reponame, repos in repositories.iteritems():
                 repos.close()
Example #2
0
 def shutdown(self, tid=None):
     """Free `Repository` instances bound to a given thread identifier"""
     if tid:
         assert tid == threading._get_ident()
         with self._lock:
             repositories = self._cache.pop(tid, {})
             for reponame, repos in repositories.iteritems():
                 repos.close()
Example #3
0
 def shutdown(self, tid=None):
     if tid:
         assert tid == threading._get_ident()
         try:
             self._lock.acquire()
             repositories = self._cache.pop(tid, {})
             for reponame, repos in repositories.iteritems():
                 repos.close()
         finally:
             self._lock.release()
Example #4
0
File: api.py Project: zjj/trac_hack
 def shutdown(self, tid=None):
     if tid:
         assert tid == threading._get_ident()
         try:
             self._lock.acquire()
             repositories = self._cache.pop(tid, {})
             for reponame, repos in repositories.iteritems():
                 repos.close()
         finally:
             self._lock.release()
Example #5
0
    def get_cnx(self, connector, kwargs, timeout=None):
        cnx = None
        log = kwargs.get('log')
        key = unicode(kwargs)
        start = time.time()
        tid = threading._get_ident()
        # Get a Connection, either directly or a deferred one
        with self._available:
            # First choice: Return the same cnx already used by the thread
            if (tid, key) in self._active:
                cnx, num = self._active[(tid, key)]
                num += 1
            else:
                if self._waiters == 0:
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                if not cnx:
                    self._waiters += 1
                    self._available.wait()
                    self._waiters -= 1
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                num = 1
            if cnx:
                self._active[(tid, key)] = (cnx, num)

        deferred = num == 1 and isinstance(cnx, tuple)
        err = None
        if deferred:
            # Potentially lenghty operations must be done without lock held
            op, cnx = cnx
            try:
                if op == 'ping':
                    cnx.ping()
                elif op == 'close':
                    cnx.close()
                if op in ('close', 'create'):
                    cnx = connector.get_connection(**kwargs)
            except TracError, e:
                err = e
                cnx = None
            except Exception, e:
                if log:
                    log.error('Exception caught on %s', op, exc_info=True)
                err = e
                cnx = None
Example #6
0
    def get_cnx(self, connector, kwargs, timeout=None):
        cnx = None
        log = kwargs.get('log')
        key = unicode(kwargs)
        start = time.time()
        tid = threading._get_ident()
        # Get a Connection, either directly or a deferred one
        with self._available:
            # First choice: Return the same cnx already used by the thread
            if (tid, key) in self._active:
                cnx, num = self._active[(tid, key)]
                num += 1
            else:
                if self._waiters == 0:
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                if not cnx:
                    self._waiters += 1
                    self._available.wait()
                    self._waiters -= 1
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                num = 1
            if cnx:
                self._active[(tid, key)] = (cnx, num)

        deferred = num == 1 and isinstance(cnx, tuple)
        err = None
        if deferred:
            # Potentially lenghty operations must be done without lock held
            op, cnx = cnx
            try:
                if op == 'ping':
                    cnx.ping()
                elif op == 'close':
                    cnx.close()
                if op in ('close', 'create'):
                    cnx = connector.get_connection(**kwargs)
            except TracError, e:
                err = e
                cnx = None
            except Exception, e:
                if log:
                    log.error('Exception caught on %s', op, exc_info=True)
                err = e
                cnx = None
Example #7
0
File: api.py Project: pkdevbox/trac
    def get_repository(self, reponame):
        """Retrieve the appropriate `Repository` for the given
        repository name.

        :param reponame: the key for specifying the repository.
                         If no name is given, take the default
                         repository.
        :return: if no corresponding repository was defined,
                 simply return `None`.

        :raises InvalidRepository: if the repository cannot be opened.
        """
        reponame = reponame or ''
        repoinfo = self.get_all_repositories().get(reponame, {})
        if 'alias' in repoinfo:
            reponame = repoinfo['alias']
            repoinfo = self.get_all_repositories().get(reponame, {})
        rdir = repoinfo.get('dir')
        if not rdir:
            return None
        rtype = repoinfo.get('type') or self.default_repository_type

        # get a Repository for the reponame (use a thread-level cache)
        with self.env.db_transaction: # prevent possible deadlock, see #4465
            with self._lock:
                tid = threading._get_ident()
                if tid in self._cache:
                    repositories = self._cache[tid]
                else:
                    repositories = self._cache[tid] = {}
                repos = repositories.get(reponame)
                if not repos:
                    if not os.path.isabs(rdir):
                        rdir = os.path.join(self.env.path, rdir)
                    connector = self._get_connector(rtype)
                    repos = connector.get_repository(rtype, rdir,
                                                     repoinfo.copy())
                    repositories[reponame] = repos
                return repos
Example #8
0
    def get_repository(self, reponame):
        """Retrieve the appropriate `Repository` for the given
        repository name.

        :param reponame: the key for specifying the repository.
                         If no name is given, take the default
                         repository.
        :return: if no corresponding repository was defined,
                 simply return `None`.

        :raises InvalidRepository: if the repository cannot be opened.
        """
        reponame = reponame or ''
        repoinfo = self.get_all_repositories().get(reponame, {})
        if 'alias' in repoinfo:
            reponame = repoinfo['alias']
            repoinfo = self.get_all_repositories().get(reponame, {})
        rdir = repoinfo.get('dir')
        if not rdir:
            return None
        rtype = repoinfo.get('type') or self.repository_type

        # get a Repository for the reponame (use a thread-level cache)
        with self.env.db_transaction:  # prevent possible deadlock, see #4465
            with self._lock:
                tid = threading._get_ident()
                if tid in self._cache:
                    repositories = self._cache[tid]
                else:
                    repositories = self._cache[tid] = {}
                repos = repositories.get(reponame)
                if not repos:
                    if not os.path.isabs(rdir):
                        rdir = os.path.join(self.env.path, rdir)
                    connector = self._get_connector(rtype)
                    repos = connector.get_repository(rtype, rdir,
                                                     repoinfo.copy())
                    repositories[reponame] = repos
                return repos
Example #9
0
    def get_repository(self, reponame):
        """Retrieve the appropriate Repository for the given name.

           :param reponame: the key for specifying the repository.
                            If no name is given, take the default 
                            repository.
           :return: if no corresponding repository was defined, 
                    simply return `None`.
        """
        reponame = reponame or ''
        repoinfo = self.get_all_repositories().get(reponame, {})
        if 'alias' in repoinfo:
            reponame = repoinfo['alias']
            repoinfo = self.get_all_repositories().get(reponame, {})
        rdir = repoinfo.get('dir')
        if not rdir:
            return None
        rtype = repoinfo.get('type') or self.repository_type

        # get a Repository for the reponame (use a thread-level cache)
        db = self.env.get_db_cnx()  # prevent possible deadlock, see #4465
        try:
            self._lock.acquire()
            tid = threading._get_ident()
            if tid in self._cache:
                repositories = self._cache[tid]
            else:
                repositories = self._cache[tid] = {}
            repos = repositories.get(reponame)
            if not repos:
                if not os.path.isabs(rdir):
                    rdir = os.path.join(self.env.path, rdir)
                connector = self._get_connector(rtype)
                repos = connector.get_repository(rtype, rdir, repoinfo.copy())
                repositories[reponame] = repos
            return repos
        finally:
            self._lock.release()
Example #10
0
File: api.py Project: zjj/trac_hack
    def get_repository(self, reponame):
        """Retrieve the appropriate Repository for the given name.

           :param reponame: the key for specifying the repository.
                            If no name is given, take the default 
                            repository.
           :return: if no corresponding repository was defined, 
                    simply return `None`.
        """
        reponame = reponame or ''
        repoinfo = self.get_all_repositories().get(reponame, {})
        if 'alias' in repoinfo:
            reponame = repoinfo['alias']
            repoinfo = self.get_all_repositories().get(reponame, {})
        rdir = repoinfo.get('dir')
        if not rdir:
            return None
        rtype = repoinfo.get('type') or self.repository_type

        # get a Repository for the reponame (use a thread-level cache)
        db = self.env.get_db_cnx() # prevent possible deadlock, see #4465
        try:
            self._lock.acquire()
            tid = threading._get_ident()
            if tid in self._cache:
                repositories = self._cache[tid]
            else:
                repositories = self._cache[tid] = {}
            repos = repositories.get(reponame)
            if not repos:
                if not os.path.isabs(rdir):
                    rdir = os.path.join(self.env.path, rdir)
                connector = self._get_connector(rtype)
                repos = connector.get_repository(rtype, rdir, repoinfo.copy())
                repositories[reponame] = repos
            return repos
        finally:
            self._lock.release()
Example #11
0
def dispatch_request(environ, start_response):
    """Main entry point for the Trac web interface.

    :param environ: the WSGI environment dict
    :param start_response: the WSGI callback for starting the response
    """

    global _warn_setuptools
    if _warn_setuptools is False:
        _warn_setuptools = True
        warn_setuptools_issue(out=environ.get('wsgi.errors'))

    # SCRIPT_URL is an Apache var containing the URL before URL rewriting
    # has been applied, so we can use it to reconstruct logical SCRIPT_NAME
    script_url = environ.get('SCRIPT_URL')
    if script_url is not None:
        path_info = environ.get('PATH_INFO')
        if not path_info:
            environ['SCRIPT_NAME'] = script_url
        else:
            # mod_wsgi squashes slashes in PATH_INFO (!)
            script_url = _slashes_re.sub('/', script_url)
            path_info = _slashes_re.sub('/', path_info)
            if script_url.endswith(path_info):
                environ['SCRIPT_NAME'] = script_url[:-len(path_info)]

    # If the expected configuration keys aren't found in the WSGI environment,
    # try looking them up in the process environment variables
    environ.setdefault('trac.env_path', os.getenv('TRAC_ENV'))
    environ.setdefault('trac.env_parent_dir', os.getenv('TRAC_ENV_PARENT_DIR'))
    environ.setdefault('trac.env_index_template',
                       os.getenv('TRAC_ENV_INDEX_TEMPLATE'))
    environ.setdefault('trac.template_vars', os.getenv('TRAC_TEMPLATE_VARS'))
    environ.setdefault('trac.locale', '')
    environ.setdefault('trac.base_url', os.getenv('TRAC_BASE_URL'))

    locale.setlocale(locale.LC_ALL, environ['trac.locale'])

    # Determine the environment
    env_path = environ.get('trac.env_path')
    if not env_path:
        env_parent_dir = environ.get('trac.env_parent_dir')
        env_paths = environ.get('trac.env_paths')
        if env_parent_dir or env_paths:
            # The first component of the path is the base name of the
            # environment
            path_info = environ.get('PATH_INFO', '').lstrip('/').split('/')
            env_name = path_info.pop(0)

            if not env_name:
                # No specific environment requested, so render an environment
                # index page
                send_project_index(environ, start_response, env_parent_dir,
                                   env_paths)
                return []

            errmsg = None

            # To make the matching patterns of request handlers work, we append
            # the environment name to the `SCRIPT_NAME` variable, and keep only
            # the remaining path in the `PATH_INFO` variable.
            script_name = environ.get('SCRIPT_NAME', '')
            try:
                script_name = unicode(script_name, 'utf-8')
                # (as Href expects unicode parameters)
                environ['SCRIPT_NAME'] = Href(script_name)(env_name)
                environ['PATH_INFO'] = '/' + '/'.join(path_info)

                if env_parent_dir:
                    env_path = os.path.join(env_parent_dir, env_name)
                else:
                    env_path = get_environments(environ).get(env_name)

                if not env_path or not os.path.isdir(env_path):
                    errmsg = 'Environment not found'
            except UnicodeDecodeError:
                errmsg = 'Invalid URL encoding (was %r)' % script_name

            if errmsg:
                start_response('404 Not Found',
                               [('Content-Type', 'text/plain'),
                                ('Content-Length', str(len(errmsg)))])
                return [errmsg]

    if not env_path:
        raise EnvironmentError('The environment options "TRAC_ENV" or '
                               '"TRAC_ENV_PARENT_DIR" or the mod_python '
                               'options "TracEnv" or "TracEnvParentDir" are '
                               'missing. Trac requires one of these options '
                               'to locate the Trac environment(s).')
    run_once = environ['wsgi.run_once']

    env = env_error = None
    try:
        env = open_environment(env_path, use_cache=not run_once)
        if env.base_url_for_redirect:
            environ['trac.base_url'] = env.base_url

        # Web front-end type and version information
        if not hasattr(env, 'webfrontend'):
            mod_wsgi_version = environ.get('mod_wsgi.version')
            if mod_wsgi_version:
                mod_wsgi_version = (
                    "%s (WSGIProcessGroup %s WSGIApplicationGroup %s)" %
                    ('.'.join([str(x) for x in mod_wsgi_version
                               ]), environ.get('mod_wsgi.process_group'),
                     environ.get('mod_wsgi.application_group') or '%{GLOBAL}'))
                environ.update({
                    'trac.web.frontend': 'mod_wsgi',
                    'trac.web.version': mod_wsgi_version
                })
            env.webfrontend = environ.get('trac.web.frontend')
            if env.webfrontend:
                env.webfrontend_version = environ['trac.web.version']
    except Exception as e:
        env_error = e

    req = RequestWithSession(environ, start_response)
    translation.make_activable(lambda: req.locale, env.path if env else None)
    try:
        return _dispatch_request(req, env, env_error)
    finally:
        translation.deactivate()
        if env and not run_once:
            env.shutdown(threading._get_ident())
            # Now it's a good time to do some clean-ups
            #
            # Note: enable the '##' lines as soon as there's a suspicion
            #       of memory leak due to uncollectable objects (typically
            #       objects with a __del__ method caught in a cycle)
            #
            ##gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
            unreachable = gc.collect()
Example #12
0
    def get_cnx(self, connector, kwargs, timeout=None):
        cnx = None
        log = kwargs.get('log')
        key = unicode(kwargs)
        start = time.time()
        tid = threading._get_ident()
        # Get a Connection, either directly or a deferred one
        with self._available:
            # First choice: Return the same cnx already used by the thread
            if (tid, key) in self._active:
                cnx, num = self._active[(tid, key)]
                num += 1
            else:
                if self._waiters == 0:
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                if not cnx:
                    self._waiters += 1
                    self._available.wait()
                    self._waiters -= 1
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                num = 1
            if cnx:
                self._active[(tid, key)] = (cnx, num)

        deferred = num == 1 and isinstance(cnx, tuple)
        exc_info = (None, None, None)
        if deferred:
            # Potentially lengthy operations must be done without lock held
            op, cnx = cnx
            try:
                if op == 'ping':
                    cnx.ping()
                elif op == 'close':
                    cnx.close()
                if op in ('close', 'create'):
                    cnx = connector.get_connection(**kwargs)
            except TracError:
                exc_info = sys.exc_info()
                cnx = None
            except Exception:
                exc_info = sys.exc_info()
                if log:
                    log.error('Exception caught on %s', op, exc_info=True)
                cnx = None

        if cnx and not isinstance(cnx, tuple):
            if deferred:
                # replace placeholder with real Connection
                with self._available:
                    self._active[(tid, key)] = (cnx, num)
            return PooledConnection(self, cnx, key, tid, log)

        if deferred:
            # cnx couldn't be reused, clear placeholder
            with self._available:
                del self._active[(tid, key)]
            if op == 'ping': # retry
                return self.get_cnx(connector, kwargs)

        # if we didn't get a cnx after wait(), something's fishy...
        if isinstance(exc_info[1], TracError):
            raise exc_info[0], exc_info[1], exc_info[2]
        timeout = time.time() - start
        errmsg = _("Unable to get database connection within %(time)d seconds.",
                   time=timeout)
        if exc_info[1]:
            errmsg += " (%s)" % exception_to_unicode(exc_info[1])
        raise TimeoutError(errmsg)
Example #13
0
                    'trac.web.version': mod_wsgi_version})
            env.webfrontend = environ.get('trac.web.frontend')
            if env.webfrontend:
                env.systeminfo.append((env.webfrontend,
                                       environ['trac.web.version']))
    except Exception, e:
        env_error = e

    req = RequestWithSession(environ, start_response)
    translation.make_activable(lambda: req.locale, env.path if env else None)
    try:
        return _dispatch_request(req, env, env_error)
    finally:
        translation.deactivate()
        if env and not run_once:
            env.shutdown(threading._get_ident())
            # Now it's a good time to do some clean-ups
            #
            # Note: enable the '##' lines as soon as there's a suspicion
            #       of memory leak due to uncollectable objects (typically
            #       objects with a __del__ method caught in a cycle)
            #
            ##gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
            unreachable = gc.collect()
            ##env.log.debug("%d unreachable objects found.", unreachable)
            ##uncollectable = len(gc.garbage)
            ##if uncollectable:
            ##    del gc.garbage[:]
            ##    env.log.warn("%d uncollectable objects found.", uncollectable)

Example #14
0
                if env is not None else Request(environ, start_response)
        except Exception, e:
            log = environ.get('wsgi.errors')
            if log:
                log.write("[FAIL] [Trac] Entry point '%s' "
                          "Method 'create_request' Reason %s" %
                          (bootstrap_ep, repr(exception_to_unicode(e))))
    if req is None:
        req = RequestWithSession(environ, start_response)
    translation.make_activable(lambda: req.locale, env.path if env else None)
    try:
        return _dispatch_request(req, env, env_error)
    finally:
        translation.deactivate()
        if env and not run_once:
            env.shutdown(threading._get_ident())
            # Now it's a good time to do some clean-ups
            #
            # Note: enable the '##' lines as soon as there's a suspicion
            #       of memory leak due to uncollectable objects (typically
            #       objects with a __del__ method caught in a cycle)
            #
            ##gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
            unreachable = gc.collect()
            ##env.log.debug("%d unreachable objects found.", unreachable)
            ##uncollectable = len(gc.garbage)
            ##if uncollectable:
            ##    del gc.garbage[:]
            ##    env.log.warn("%d uncollectable objects found.", uncollectable)

Example #15
0
def dispatch_request(environ, start_response):
    """Main entry point for the Trac web interface.

    :param environ: the WSGI environment dict
    :param start_response: the WSGI callback for starting the response
    """

    global _warn_setuptools
    if _warn_setuptools is False:
        _warn_setuptools = True
        warn_setuptools_issue(out=environ.get('wsgi.errors'))

    # SCRIPT_URL is an Apache var containing the URL before URL rewriting
    # has been applied, so we can use it to reconstruct logical SCRIPT_NAME
    script_url = environ.get('SCRIPT_URL')
    if script_url is not None:
        path_info = environ.get('PATH_INFO')
        if not path_info:
            environ['SCRIPT_NAME'] = script_url
        else:
            # mod_wsgi squashes slashes in PATH_INFO (!)
            script_url = _slashes_re.sub('/', script_url)
            path_info = _slashes_re.sub('/', path_info)
            if script_url.endswith(path_info):
                environ['SCRIPT_NAME'] = script_url[:-len(path_info)]

    # If the expected configuration keys aren't found in the WSGI environment,
    # try looking them up in the process environment variables
    environ.setdefault('trac.env_path', os.getenv('TRAC_ENV'))
    environ.setdefault('trac.env_parent_dir',
                       os.getenv('TRAC_ENV_PARENT_DIR'))
    environ.setdefault('trac.env_index_template',
                       os.getenv('TRAC_ENV_INDEX_TEMPLATE'))
    environ.setdefault('trac.template_vars',
                       os.getenv('TRAC_TEMPLATE_VARS'))
    environ.setdefault('trac.locale', '')
    environ.setdefault('trac.base_url',
                       os.getenv('TRAC_BASE_URL'))


    locale.setlocale(locale.LC_ALL, environ['trac.locale'])

    # Determine the environment
    env_path = environ.get('trac.env_path')
    if not env_path:
        env_parent_dir = environ.get('trac.env_parent_dir')
        env_paths = environ.get('trac.env_paths')
        if env_parent_dir or env_paths:
            # The first component of the path is the base name of the
            # environment
            path_info = environ.get('PATH_INFO', '').lstrip('/').split('/')
            env_name = path_info.pop(0)

            if not env_name:
                # No specific environment requested, so render an environment
                # index page
                send_project_index(environ, start_response, env_parent_dir,
                                   env_paths)
                return []

            errmsg = None

            # To make the matching patterns of request handlers work, we append
            # the environment name to the `SCRIPT_NAME` variable, and keep only
            # the remaining path in the `PATH_INFO` variable.
            script_name = environ.get('SCRIPT_NAME', '')
            try:
                script_name = unicode(script_name, 'utf-8')
                # (as Href expects unicode parameters)
                environ['SCRIPT_NAME'] = Href(script_name)(env_name)
                environ['PATH_INFO'] = '/' + '/'.join(path_info)

                if env_parent_dir:
                    env_path = os.path.join(env_parent_dir, env_name)
                else:
                    env_path = get_environments(environ).get(env_name)

                if not env_path or not os.path.isdir(env_path):
                    errmsg = 'Environment not found'
            except UnicodeDecodeError:
                errmsg = 'Invalid URL encoding (was %r)' % script_name

            if errmsg:
                start_response('404 Not Found',
                               [('Content-Type', 'text/plain'),
                                ('Content-Length', str(len(errmsg)))])
                return [errmsg]

    if not env_path:
        raise EnvironmentError('The environment options "TRAC_ENV" or '
                               '"TRAC_ENV_PARENT_DIR" or the mod_python '
                               'options "TracEnv" or "TracEnvParentDir" are '
                               'missing. Trac requires one of these options '
                               'to locate the Trac environment(s).')
    run_once = environ['wsgi.run_once']

    env = env_error = None
    try:
        env = open_environment(env_path, use_cache=not run_once)
        if env.base_url_for_redirect:
            environ['trac.base_url'] = env.base_url

        # Web front-end type and version information
        if not hasattr(env, 'webfrontend'):
            mod_wsgi_version = environ.get('mod_wsgi.version')
            if mod_wsgi_version:
                mod_wsgi_version = (
                        "%s (WSGIProcessGroup %s WSGIApplicationGroup %s)" %
                        ('.'.join([str(x) for x in mod_wsgi_version]),
                         environ.get('mod_wsgi.process_group'),
                         environ.get('mod_wsgi.application_group') or
                         '%{GLOBAL}'))
                environ.update({
                    'trac.web.frontend': 'mod_wsgi',
                    'trac.web.version': mod_wsgi_version})
            env.webfrontend = environ.get('trac.web.frontend')
            if env.webfrontend:
                env.webfrontend_version = environ['trac.web.version']
    except Exception as e:
        env_error = e

    req = RequestWithSession(environ, start_response)
    translation.make_activable(lambda: req.locale, env.path if env else None)
    try:
        return _dispatch_request(req, env, env_error)
    finally:
        translation.deactivate()
        if env and not run_once:
            env.shutdown(threading._get_ident())
            # Now it's a good time to do some clean-ups
            #
            # Note: enable the '##' lines as soon as there's a suspicion
            #       of memory leak due to uncollectable objects (typically
            #       objects with a __del__ method caught in a cycle)
            #
            ##gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
            unreachable = gc.collect()