IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Blocage avec eventlet


Sujet :

Python

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 31
    Points : 13
    Points
    13
    Par défaut Blocage avec eventlet
    Bonjour,

    J'ai un problème de blocage en créant des threads via l'api eventlet.
    En effet, je veux exécuter un programme qui fait la synchronisation avec une base de donnée ldap parallèlement avec un autre programme.
    Mais, en lançant mon script l'exécution se bloque sur la fonction faisant la synchronisation ldap et empêche l'appel des autres fonctions via eventlet.
    Je tiens à vous informer que le problème n'est pas reproductible en lançant des thread avec l'api thread !!!
    Mais, j'ai une contrainte forte d'utiliser eventlet pour mon cas.

    Voici mon code ci-dessous. L’exécution de ce script requière une configuration du serveur et du client ldap.
    Pour résumer, je me demande comment dois-je utiliser l'api eventlet pour avoir un comportement identique à celui de l'api thread afin d'éviter ce blocage ?

    D'avance merci.
    Cordialement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    """
    This script implements a syncrepl consumer which syncs data from an OpenLDAP
    server to a local (shelve) database.
    Notes:
    The bound user needs read access to the attributes entryDN and entryCSN.
    This needs the following software:
    Python
    pyasn1 0.1.4+
    pyasn1-modules
    python-ldap 2.4.10+
    """
     
    # Import the python-ldap modules
    import ldap,ldapurl
    # Import specific classes from python-ldap
    from ldap.ldapobject import ReconnectLDAPObject
    from ldap.syncrepl import SyncreplConsumer
     
    # Import modules from Python standard lib
    import shelve,signal,time,sys,logging
    import eventlet
    #import thread
    eventlet.monkey_patch()
     
    # Global state
    watcher_running = True
    ldap_connection = False
     
     
     
    class SyncReplConsumer(ReconnectLDAPObject,SyncreplConsumer):
        """
        Syncrepl Consumer interface
        """
        def __init__(self,db_path,*args,**kwargs):
            # Initialise the LDAP Connection first
            ldap.ldapobject.ReconnectLDAPObject.__init__(self, *args, **kwargs)
            # Now prepare the data store
            self.__data = shelve.open(db_path, 'c')
            # We need this for later internal use
            self.__presentUUIDs = dict()
     
        def __del__(self):
                # Close the data store properly to avoid corruption
                self.__data.close()
     
        def syncrepl_get_cookie(self):
            if 'cookie' in self.__data:
                return self.__data['cookie']
     
        def syncrepl_set_cookie(self,cookie):
            self.__data['cookie'] = cookie
     
        def syncrepl_entry(self,dn,attributes,uuid):
     
            # First we determine the type of change we have here (and store away the previous data for later if needed)
            previous_attributes = dict()
            if uuid in self.__data:
                change_type = 'modify'
                previous_attributes = self.__data[uuid]
            else:
                change_type = 'add'
            # Now we store our knowledge of the existence of this entry (including the DN as an attribute for convenience)
            attributes['dn'] = dn
            self.__data[uuid] = attributes
            # Debugging
            print 'Detected', change_type, 'of entry:', dn
            # If we have a cookie then this is not our first time being run, so it must be a change
            if 'ldap_cookie' in self.__data:
                    self.perform_application_sync(dn, attributes, previous_attributes)
     
        def syncrepl_delete(self,uuids):
            # Make sure we know about the UUID being deleted, just in case...
            uuids = [uuid for uuid in uuids if uuid in self.__data]
            # Delete all the UUID values we know of
            for uuid in uuids:
                print 'Detected deletion of entry:', self.__data[uuid]['dn']
                del self.__data[uuid]
     
        def syncrepl_present(self,uuids,refreshDeletes=False):
            # If we have not been given any UUID values, then we have recieved all the present controls...
            if uuids is None:
                # We only do things if refreshDeletes is false as the syncrepl extension will call syncrepl_delete instead when it detects a delete notice
                if refreshDeletes is False:
                    deletedEntries = [uuid for uuid in self.__data.keys() if uuid not in self.__presentUUIDs and uuid != 'ldap_cookie']
                    self.syncrepl_delete( deletedEntries )
                # Phase is now completed, reset the list
                self.__presentUUIDs = {}
            else:
                # Note down all the UUIDs we have been sent
                for uuid in uuids:
                        self.__presentUUIDs[uuid] = True
     
        def perform_application_sync(self,dn,attributes,previous_attributes):
            print 'Performing application sync for:', dn
            return True
     
     
    # Shutdown handler
    #def commenceShutdown(signum, stack):
    def commenceShutdown():
        # Declare the needed global variables
        global watcher_running, ldap_connection
        print 'Shutting down!'
     
        # We are no longer running
        watcher_running = False
     
        # Tear down the server connection
        if( ldap_connection ):
                del ldap_connection
     
        # Shutdown
        sys.exit(0)
     
    def mainOfSyncrepl(threadName):
         # Time to actually begin execution
         # Install our signal handlers
    #     signal.signal(signal.SIGTERM,commenceShutdown)
    #     signal.signal(signal.SIGINT,commenceShutdown)
         try:
           ldap_url = ldapurl.LDAPUrl('ldap://localhost/dc=exemple,dc=org?*?sub?(objectClass=*)?bindname=cn=admin%2cdc=test%2cdc=com,X-BINDPW=myPassword')#ldapurl.LDAPUrl(sys.argv[1])
         #  ldap_url = ldapurl.LDAPUrl(link)
           database_path = 'test.com'#sys.argv[2]
         #  database_path = pathName
         except IndexError,e:
           print 'Usage: syncrepl-client.py <LDAP URL> <pathname of database>'
           sys.exit(1)
         except ValueError,e:
           print 'Error parsing command-line arguments:',str(e)
           sys.exit(1)
     
         while watcher_running:
             print 'Connecting to LDAP server now...'
             # Prepare the LDAP server connection (triggers the connection as well)
             ldap_connection = SyncReplConsumer(database_path,ldap_url.initializeUrl())
     
             # Now we login to the LDAP server
             try:
                 ldap_connection.simple_bind_s(ldap_url.who,ldap_url.cred)
             except ldap.INVALID_CREDENTIALS, e:
                 print 'Login to LDAP server failed: ', str(e)
                 sys.exit(1)
             except ldap.SERVER_DOWN:
                 continue
     
             # Commence the syncing
             print 'Commencing sync process'
             ldap_search = ldap_connection.syncrepl_search(
               ldap_url.dn or '',
               ldap_url.scope or ldap.SCOPE_SUBTREE,
               mode = 'refreshAndPersist',
               filterstr = ldap_url.filterstr or '(objectClass=*)')
             print 'After syncrepl_search.'
             try:
                 while ldap_connection.syncrepl_poll( all = 1, msgid = ldap_search):
                      pass
             except KeyboardInterrupt:
              # User asked to exit
                 commenceShutdown()
                 pass
             except Exception, e:
              # Handle any exception
                 if watcher_running:
                     print 'Encountered a problem, going to retry. Error:', str(e)
    #              time.sleep(5)
                 pass
     
    # Define a function for the 2nd thread
    def print_time(ThreadName):
         count = 0
         delay = 3
         while 1:#count < 5:
             count += 1
             print "%s: %s" % (ThreadName, time.ctime(time.time()) )
             eventlet.sleep(delay)
     
     
     
    print 'Before call threads'
     
    evt1 = eventlet.spawn(mainOfSyncrepl, "Thread-1",)
    evt2 = eventlet.spawn(print_time, "Thread-2",)
    evt3 = eventlet.spawn(print_time, "Thread-3",)
     
    print 'After call threads'
     
    evt1.wait()
    evt2.wait()
    evt3.wait()
     
    print 'After wait'

  2. #2
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 31
    Points : 13
    Points
    13
    Par défaut
    Permettez-moi de rajouter un détail.
    En vérifiant si les modules relatifs à ldap sont monkey_patched ou non via la fonction eventlet.patcher.is_monkey_patched, le résultat est False pourtant j'ai appelé eventlet.monkey_patch() juste après le bloc des 'import'!!?
    Voici les lignes que j'ai ajoutées:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print "*****is_monkey_patched(ldap.syncrepl) : %s*****" % eventlet.patcher.is_monkey_patched('ldap.syncrepl') 
    print "*****is_monkey_patched(ldap.ldapobject) : %s*****" % eventlet.patcher.is_monkey_patched('ldap.ldapobject')
    Sauriez-vous comment je peux résoudre ce problème ?
    Merci d'avance.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Salut,

    Citation Envoyé par newdevso Voir le message
    Sauriez-vous comment je peux résoudre ce problème ?
    Est-ce que LDAP fait partie des bibliothèques qu'eventlet sait patcher?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 31
    Points : 13
    Points
    13
    Par défaut
    Merci wiztricks.
    Je crois que non.
    Donc, à votre avis, je ne peux pas envisager une solution avec eventlet vu ce point ou je peux le contourner autrement ?

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Citation Envoyé par newdevso Voir le message
    Donc, à votre avis, je ne peux pas envisager une solution avec eventlet vu ce point ou je peux le contourner autrement ?
    Aucune idée. Ce sont des fonctionnalités assez compliquées et plus ou moins obsolètes avec les dernières versions de Python. La question serait: si çà fonctionne avec des Threads "classiques" quel avantage espérez vous en codant çà avec des coroutines?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Blocage avec un TemplateLayout
    Par zooffy dans le forum ASP.NET
    Réponses: 0
    Dernier message: 15/06/2010, 12h22
  2. Problème de blocage avec Worksheet_Change
    Par Riri80 dans le forum Excel
    Réponses: 2
    Dernier message: 30/01/2009, 09h27
  3. blocage avec mon like
    Par ouedmouss dans le forum Langage SQL
    Réponses: 3
    Dernier message: 02/09/2005, 14h20
  4. blocage avec udp
    Par nesquik dans le forum Web & réseau
    Réponses: 3
    Dernier message: 07/07/2005, 13h35
  5. [Eclipse] Blocage avec Mandrake 9.2
    Par messier79 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 10/03/2004, 22h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo