buildframework/helium/sf/python/pythoncore/lib/ccm/extra.py
author wbernard
Tue, 27 Apr 2010 08:33:08 +0300
changeset 587 85df38eb4012
child 588 c7c26511138f
permissions -rw-r--r--
helium_9.0-a7879c935424
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
587
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     1
#============================================================================ 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     2
#Name        : extra.py 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     3
#Part of     : Helium 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     4
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     5
#Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     6
#All rights reserved.
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     7
#This component and the accompanying materials are made available
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     8
#under the terms of the License "Eclipse Public License v1.0"
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
     9
#which accompanies this distribution, and is available
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    10
#at the URL "http://www.eclipse.org/legal/epl-v10.html".
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    11
#
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    12
#Initial Contributors:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    13
#Nokia Corporation - initial contribution.
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    14
#
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    15
#Contributors:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    16
#
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    17
#Description:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    18
#===============================================================================
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    19
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    20
""" Library that contains custom Synergy functionnlities: e.g
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    21
        * Snapshotter that can snapshot unfrozen baselines
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    22
        * Threaded snapshotter.
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    23
"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    24
import ccm
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    25
import os
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    26
import threading
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    27
import threadpool
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    28
import traceback
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    29
import logging
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    30
from xml.dom.minidom import getDOMImplementation, parse
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    31
import StringIO     #pylint throws this up as unused but it is required by delete call in the code 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    32
                    #so do not remove unless removeing the delete (which is required at some point).
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    33
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    34
# Uncomment this line to enable logging in this module, or configure logging elsewhere
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    35
#logging.basicConfig(level=logging.DEBUG)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    36
_logger = logging.getLogger('ccm.extra')
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    37
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    38
class CCMExtraException(ccm.CCMException):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    39
    """ Exception raised by the methods of this module. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    40
    def __init__(self, description, subexceptions):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    41
        ccm.CCMException.__init__(self, description)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    42
        self.subexceptions = subexceptions
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    43
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    44
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    45
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    46
def Snapshot(project, targetdir, dir=None):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    47
    """ This function can snapshot anything from Synergy, even prep/working projects """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    48
    assert project != None, "a project object must be supplied"
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    49
    assert project.type == "project", "project must be of project type"
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    50
    if not dir:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    51
        dir = project.root_dir()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    52
    targetdir = os.path.join(targetdir, dir.name)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    53
    os.makedirs(targetdir)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    54
    for object in dir.children(project):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    55
        if object.type == 'dir':
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    56
            Snapshot(project, targetdir, object)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    57
        elif object.type == 'project':
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    58
            Snapshot(object, targetdir)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    59
        else:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    60
            object.to_file(os.path.join(targetdir, object.name))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    61
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    62
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    63
class _FastSnapshot:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    64
    """ Snapshot Job executed by the thread pool. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    65
    def __init__(self, pool, project, targetdir, callback, exc_hld):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    66
        """ Construtor, will store the parameter for the checkout. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    67
        self.pool = pool
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    68
        self.project = project
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    69
        self.targetdir = targetdir
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    70
        self.callback = callback
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    71
        self.exc_hld = exc_hld
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    72
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    73
    def __call__(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    74
        """ Do the checkout, and then walkthrough the project hierarchy to find subproject to snapshot. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    75
        _logger.info("Snapshotting %s under %s" % (self.project, self.targetdir))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    76
        self.project.snapshot(self.targetdir, False)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    77
        def walk(dir, targetdir):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    78
            """walkthrough the project hierarchy to find subproject to snapshot"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    79
            for object in dir.children(self.project):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    80
                if isinstance(object, ccm.Dir):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    81
                    walk(object, os.path.join(targetdir, object.name))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    82
                elif isinstance(object, ccm.Project):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    83
                    _logger.info("Adding project %s" % object.objectname)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    84
                    self.pool.addWork(_FastSnapshot(self.pool, object, targetdir, self.callback, self.exc_hld))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    85
                    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    86
        if len(self.project.subprojects) > 0:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    87
            rootdir = self.project.root_dir()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    88
            walk(rootdir, os.path.join(self.targetdir, rootdir.name))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    89
        return ""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    90
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    91
def FastSnapshot(project, targetdir, threads=4):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    92
    """ Create snapshot running by running snapshots concurrently.
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    93
        Snapshot will be made recursively top-down, and each sub project will
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    94
        be snapshotted in parallel. 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    95
    """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    96
    assert threads > 0, "Number of threads must be > 0."
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    97
    assert project != None, "a project object must be supplied."
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    98
    assert project.type == "project", "project must be of project type."
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
    99
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   100
    # error handling
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   101
    exceptions = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   102
    results = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   103
    def handle_exception(request, exc_info):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   104
        """ append the exceptions"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   105
        _logger.error( "Exception occurred in request #%s: %s" % (request.requestID, exc_info[1]))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   106
        exceptions.append(exc_info[1])
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   107
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   108
    def handle_result(result):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   109
        """ append the result"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   110
        results.append(result)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   111
   
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   112
    pool = threadpool.ThreadPool(threads)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   113
    pool.addWork(_FastSnapshot(pool, project, targetdir, handle_result, handle_exception))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   114
    pool.wait()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   115
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   116
    if len(exceptions):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   117
        raise CCMExtraException("Errors occurred during snapshot.", exceptions)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   118
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   119
    return "\n".join(results)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   120
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   121
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   122
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   123
def FastMaintainWorkArea(project, path, pst=None, threads=4, wat=False):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   124
    """ Maintain the workarea of a project in parallel. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   125
    assert threads > 0, "Number of threads must be > 0."
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   126
    assert isinstance(project, ccm.Project), "a valid project object must be supplied."
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   127
            
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   128
    # error handling
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   129
    exceptions = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   130
    results = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   131
    def handle_exception(request, exc_info):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   132
        """append the exception"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   133
        _logger.error( "Exception occured in request #%s: %s\n%s" % (request.requestID, exc_info[1], traceback.format_exception(exc_info[0], exc_info[1], exc_info[2])))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   134
        exceptions.append(exc_info[1])
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   135
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   136
    def handle_result(result):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   137
        """append  the result"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   138
        results.append(result)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   139
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   140
    class __MaintainProject:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   141
        """_Maintain Project"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   142
        def __init__(self, subproject, toplevel, wat=False):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   143
            self.subproject = subproject
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   144
            self.toplevel = toplevel
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   145
            self.wat = wat
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   146
        
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   147
        def __call__(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   148
            output = ""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   149
            _logger.info("Maintaining project %s" % self.subproject)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   150
            for tuple in self.subproject.finduse():
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   151
                if tuple['project'] == self.toplevel:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   152
                    self.subproject['wa_path'] = os.path.join(self.toplevel['wa_path'], tuple['path'])
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   153
                    self.subproject["project_subdir_template"] = ""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   154
                    _logger.info("Maintaining project %s under %s" % (self.subproject, self.subproject['wa_path']))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   155
                    output = self.subproject.work_area(True, True, True, wat=self.wat)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   156
            _logger.info("Project %s maintained" % self.subproject)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   157
            return output
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   158
            
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   159
    pool = threadpool.ThreadPool(threads)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   160
    project.work_area(True, False, True, path, pst, wat=wat)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   161
    for subproject in project.get_members(type="project"):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   162
        _logger.info("Adding project %s" % subproject)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   163
        pool.addWork(__MaintainProject(subproject, project, wat), callback=handle_result, exc_callback=handle_exception)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   164
    pool.wait()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   165
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   166
    if len(exceptions) > 0:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   167
        raise CCMExtraException("Errors occured during work area maintenance.", exceptions)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   168
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   169
    return "\n".join(results)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   170
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   171
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   172
def get_toplevel_project(session, path):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   173
    """get the top level project from CCM or return None"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   174
    try:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   175
        wainfo = session.get_workarea_info(path)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   176
        project = get_toplevel_project(session, os.path.dirname(wainfo['path']))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   177
        if project == None:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   178
            project = wainfo['project']
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   179
        return project
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   180
    except ccm.CCMException:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   181
        return None
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   182
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   183
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   184
class SessionProvider:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   185
    """ A class which provides an open user session """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   186
    def __init__(self, opener=None):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   187
        """initialisation"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   188
        self._opener = opener
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   189
        if self._opener is None:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   190
            self._opener = ccm.open_session
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   191
        
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   192
    def get(self, username=None, password=None, engine=None, dbpath=None, database=None, reuse=True):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   193
        """return the paramaters required to open a synergy session"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   194
        _logger.debug("SessionProvider: Creating a new session.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   195
        return self._opener(username, password, engine, dbpath, database, reuse)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   196
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   197
    def __del__(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   198
        """delete the CCM session"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   199
        _logger.info("Deleting the session provider.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   200
        self.close()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   201
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   202
    def close(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   203
        """close the session which actually does nothing"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   204
        pass
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   205
        
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   206
        
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   207
class CachedSessionProvider(SessionProvider):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   208
    """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   209
<sessions>
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   210
    <session database="foobar" ccmaddr="xxxx"/>
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   211
    <session database="foobarx" ccmaddr="xxxx"/>
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   212
</sessions>
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   213
    """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   214
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   215
    def __init__(self, opener=None, cache=None):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   216
        """ Creates CachedSessionProvider, with a specific 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   217
            opener and cache file.
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   218
        """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   219
        SessionProvider.__init__(self, opener=opener)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   220
        _logger.info("Using CachedSessionProvider.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   221
        self.__closed = False
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   222
        self._lock = threading.Lock()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   223
        self.cacheXml = cache
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   224
        self.cacheFree = {}
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   225
        self.cacheUsed = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   226
        self.load()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   227
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   228
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   229
    def close(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   230
        """ Closing the SessionProvider. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   231
        _logger.info("Closing the CachedSessionProvider.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   232
        self.save()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   233
        if self.cacheXml == None:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   234
            _logger.info("Cleaning up opened sessions.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   235
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   236
            for dbname in self.cacheFree.keys():
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   237
                while len(self.cacheFree[dbname]) > 0:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   238
                    session = self.cacheFree[dbname].pop()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   239
                    session.close_on_exit = True
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   240
                    session.close()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   241
            while len(self.cacheUsed) > 0:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   242
                session = self.cacheUsed.pop()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   243
                session.close_on_exit = True
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   244
            self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   245
        self.__closed = True
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   246
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   247
    def save(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   248
        """ save the sessionProvider"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   249
        if self.cacheXml is not None and not self.__closed:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   250
            _logger.info("Writing %s" % self.cacheXml)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   251
            impl = getDOMImplementation()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   252
            sessions = impl.createDocument(None, "sessions", None)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   253
            top_element = sessions.documentElement
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   254
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   255
            def add_session(dbname, session):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   256
                """add session"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   257
                sessionNode = sessions.createElement("session")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   258
                sessionNode.setAttribute("database", dbname)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   259
                sessionNode.setAttribute("ccmaddr", session.addr())
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   260
                top_element.appendChild(sessionNode)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   261
            for dbname in self.cacheFree.keys():
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   262
                for session in self.cacheFree[dbname]:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   263
                    add_session(dbname, session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   264
            for session in self.cacheUsed:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   265
                add_session(session.database(), session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   266
            self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   267
            open_f = open(self.cacheXml, "w+")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   268
            open_f.write(sessions.toprettyxml())
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   269
            open_f.close()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   270
            _logger.debug(sessions.toprettyxml())
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   271
            
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   272
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   273
    def load(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   274
        """load the command"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   275
        if self.cacheXml is not None and os.path.exists(self.cacheXml):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   276
            _logger.info("Loading %s" % self.cacheXml)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   277
            doc = parse(open(self.cacheXml, 'r')) 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   278
            sessions = doc.documentElement
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   279
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   280
            try:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   281
                for child in sessions.childNodes:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   282
                    if child.nodeType == child.ELEMENT_NODE and child.tagName == "session" and child.hasAttribute('database') and child.hasAttribute('ccmaddr'):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   283
                        if child.getAttribute('database') not in self.cacheFree:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   284
                            self.cacheFree[child.getAttribute('database')] = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   285
                        if ccm.session_exists(child.getAttribute('ccmaddr'), child.getAttribute('database')):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   286
                            _logger.info(" + Session: database=%s, ccmaddr=%s" % (child.getAttribute('database'), child.getAttribute('ccmaddr')))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   287
                            self.cacheFree[child.getAttribute('database')].append(ccm.Session(None, None, None, ccm_addr=child.getAttribute('ccmaddr'), close_on_exit=False))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   288
                        else:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   289
                            _logger.info(" - Session database=%s, ccmaddr=%s doesn't seem to be valid anymore." % (child.getAttribute('database'), child.getAttribute('ccmaddr')))
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   290
            finally:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   291
                self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   292
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   293
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   294
    def get(self, username=None, password=None, engine=None, dbpath=None, database=None, reuse=True):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   295
        """create a CCM session"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   296
        if self.__closed:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   297
            raise Exception("Could not create further session the provider is closed.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   298
        _logger.debug("CachedSessionProvider: Getting a session.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   299
        if database is not None and database in self.cacheFree and len(self.cacheFree[database]) > 0:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   300
            _logger.info("CachedSessionProvider: Reusing session.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   301
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   302
            session_free = self.cacheFree[database].pop()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   303
            self.cacheUsed.append(session_free)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   304
            self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   305
            return CachedProxySession(self, session_free) 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   306
        else:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   307
            _logger.debug("CachedSessionProvider: Creating new session.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   308
            session = SessionProvider.get(self, username, password, engine, dbpath, database, False)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   309
            session.close_on_exit = False
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   310
            proxy_session = CachedProxySession(self, session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   311
            data_base = proxy_session.database()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   312
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   313
            if data_base not in self.cacheFree:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   314
                self.cacheFree[data_base] = []
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   315
            self.cacheUsed.append(session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   316
            self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   317
            return proxy_session
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   318
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   319
    def free(self, session):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   320
        """freeup a CCM session"""
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   321
        _logger.debug("CachedSessionProvider: Freeing session: %s" % session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   322
        data_base = session.database()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   323
        if session in self.cacheUsed:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   324
            _logger.debug("CachedSessionProvider: Removing session from used list.")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   325
            self._lock.acquire()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   326
            self.cacheUsed.remove(session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   327
            self.cacheFree[data_base].append(session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   328
            self._lock.release()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   329
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   330
class CachedProxySession:
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   331
    """ Proxy session which will cleanup the session and free it from the provider """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   332
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   333
    def __init__(self, provider, session):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   334
        """ Constructor. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   335
        self.__session = session 
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   336
        self.__provider = provider
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   337
    
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   338
    def __getattr__(self, attrib):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   339
        """ Delegate attributes to the session object. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   340
        _logger.debug("CachedProxySession.__getattr__(%s)" % attrib)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   341
        if attrib == "close":
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   342
            return self.__close
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   343
        return getattr(self.__session, attrib)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   344
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   345
    def __close(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   346
        """ Overriding the session closing. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   347
        _logger.debug("CachedProxySession.__close")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   348
        self.__provider.free(self.__session)
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   349
        self.__session.close()
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   350
        
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   351
    def __del__(self):
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   352
        """ Free the session on destruction. """
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   353
        _logger.debug("CachedProxySession.__del__")
85df38eb4012 helium_9.0-a7879c935424
wbernard
parents:
diff changeset
   354
        self.__close()