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

JPA Java Discussion :

Problème mémoire JPA/TopLink


Sujet :

JPA Java

  1. #1
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut Problème mémoire JPA/TopLink
    Bonjour,

    Je rencontre depuis peu un problème très bloquant avec JPA et la mémoire.
    En effet, je dois parcourir une liste d'entités et créer à partir de chaque entité un fichier XML que je stocke sur le disque dur.

    Hors, je me rends compte que, a chaque passage dans ma boucle, ma mémoire prends quelques Mo supplémentaire et, malgré le passage du GC, ces quelques Mo ne sont jamais libéré. Après 20/25 passages dans la boucle j'arrive a plus de 500Mo de mémoire et la bah HeapSpace......

    Après avoir analysé la mémoire, je me rends compte que l'ensemble des entités sont gardées en mémoire (encore utilisée ou non).

    Je n'utilise pas de transactions, ni de commit ou autre car je prends juste une entité a chaque boucle pour la parcourir et créer directement mon fichier XML.

    Quelqu'un a t il une solution pour libérer l'espace mémoire occupé par une entité JPA ??

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Effectivement c enorme l'espace mémoire occupé, combien forment en moyen les tailles de fichiers xmls generés? essaie de passer à null les entités juste après leur usage, pour faciliter le boulot du GC, mais bon n'empêche que le pb doit venir ailleurs.

  3. #3
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    J'ai bien pensé aussi que le soucis venait d'ailleurs.
    Je prends bien chaque entité et je la met à null une fois que j'en ai plus besoin.
    Mais rien n'y fait et la mémoire grimpe toujours autant.....
    J'ai donc pris la peine d'analyser la mémoire avec un outil dédié et les seuls objets encore présent dans la mémoire sont les entités (aucunes n'a été supprimées par le GC).

    Mes fichier XML font entre 500ko et 10Mo (pouvant contenir + de 200 000 lignes).

    Le tout correspond à une procédure d'exportation de données de ma base vers ces fichiers XML.
    Hors quand je réalise le même genre de manipulation mais cette fois pour l'importation des données, la pas de soucis de ce genre (en veillant a mettre mes objets a null etc ).

    Je suis totalement bloqué et je ne sais vraiment plus quoi faire (2 jours complet de taff pour rien ).

    Merci pr ta réponse!

  4. #4
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Petite précision :

    J'ai remarqué que je n'étais pas le seul a avoir se problème. En effet, mon collègue rencontre également se phénomène (a une moindre mesure) lorsqu'il instancie un objet de type entité JPA et qu'il le parcours. L'espace mémoire occupé pour la lecture de l'objet n'est jamais libéré même si l'entité qu'il vient de parcourir est mise à null une fois la lecture réalisée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Exemple :
    //Client = Entité JPA correspondant à une table Client de ma base
    Client toto = new Client();
     
    afficher(toto.getName);
    afficher(toto.getAdresse);
    afficher(toto.getGenre);
    for(Fils f : toto.getListFils)
    {
         afficher(f.getName);
    }
     
    toto = null;
    Voila un exemple mais si je veux faire ca pour tt les client la mémoire augmente de quelques Mo a chaque fois.

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Bonsoir,

    Je n'utilise pas de transactions, ni de commit ou autre car je prends juste une entité a chaque boucle pour la parcourir et créer directement mon fichier XML.
    Mais tu fais bien des appels en base, non ?

    Si c'est le cas :
    je ne connais pas trop Toplink, mais ca serait pas lui qui utiliserait un cache de second niveau pour tes entités ?

    L'espace mémoire occupé pour la lecture de l'objet n'est jamais libéré même si l'entité qu'il vient de parcourir est mise à null une fois la lecture réalisée.
    Tu dois sûrement le savoir mais c'est parce que tu mets un objet à null qu'il est forcément supprimé par le GC.
    Si ton objet entité reste référencé par un autre objet non éligible au nettoyage du GC, le GC ne le supprimera pas.

    Le tout correspond à une procédure d'exportation de données de ma base vers ces fichiers XML.
    Hors quand je réalise le même genre de manipulation mais cette fois pour l'importation des données, la pas de soucis de ce genre (en veillant a mettre mes objets a null etc ).
    Dans l'autre sens (xml-> bdd), tu n'utilises pas de cache dans la couche persistance puisque tu fais que des insertions. La piste du cache de second niveau reste plausible.

    Je viens de jeter un coup d'oeil sur le net et il se trouve qu'au moins une des implémentations de Toplink utilisent le cache de second niveau par défaut : http://weblogs.java.net/blog/guruwon...nding_t_1.html

    La phrase intéressante
    Session cache is turned on by default so you can use it now without any extra configuration. With this 2nd-level cache you can get performance benefits.
    Le site propose des solutions pour désactiver le cache.

    Sinon, j'avais une petite question : vous utilisez toplink pour des raisons particulières ?

  6. #6
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Merci pour ta réponse !
    Effecitvement je fais des appels en base puisque je récupère une liste d'entités, que je parcours ensuite et pour chacunes, je vais lire les valeurs, récupérer les listes de fils, de petit fils etc etc etc

    Le cache L2 de EclipseLink ou TopLink est bien activé par défaut mais je viens de le désactiver et rien n'y fait....toujours le même soucis.

    J'ai commenté l'ensemble du code qui ne concernait pas directement la lecture des entités JPA et le problème persiste donc je suis maintenant plus que certain que le soucis viens bien de la.

    Il y a t il un moyen de visualiser en temps réel la taille des caches utilisés par JPA ?

    Merci d'avance

  7. #7
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    J'ai réalisé un petit code de test qui parcour juste quelques unes des entités pour voir.
    Je précise qu'il n'y a que cela qui tourne !!!

    Voici le résultat :
    Code :
    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
    public class TestJpa
    {
    	public static void main(String[] args){
    		PersistenceService manager = PersistenceService.getInstance();
    		SQLUtil connect = new SQLUtil("root", "");
    		if (connect.getResult())
    		{
    			manager.initialize(connect.getMap());
    		}
     
    		List<Baselineinfo> lBlis = (List<Baselineinfo>)manager.getResultListNamed("Baselineinfo.findAll");
     
    		for(Baselineinfo bli : lBlis)
    		{
    			ddd(bli);
    		}
     
    	}
     
    	public static void ddd(Baselineinfo _bli)
    	{
    		System.out.println("BLI : "+_bli.getBliTitle());
    		for(Dfi dfi : _bli.getDfiList())
    		{
    			System.out.println("DFI : " + dfi.getDfiDfi());
    			for(Dui dui : dfi.getDuiList())
    			{
    				System.out.println("DUI : " + dui.getDuiDui());
    				for(Enumerate enums : dui.getEnumerateList())
    				{
    					System.out.println("Enum : "+enums.getEnmMin()+"-"+enums.getEnmMax());
    					enums = null;
    				}
    				dui = null;
    			}
    			dfi = null;
    		}
    	}
    }
    extrait du persistence.xml :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <shared-cache-mode>NONE</shared-cache-mode>
    <properties>
    <property name="eclipselink.cache.shared.default" value="false"/>
    <property name="eclipselink.query-results-cache" value="false"/>
    </properties>
    et visualisation de la mémoire (attention les yeux !!!) :

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Surement ton cache de premier niveau qui sature.
    Utilise la méthode clear de ton EntityManager pour le vider, ou remove pour détacher tes entités.

  9. #9
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Merci pour l'aide mais remove me génère une erreur
    et clear ne change rien !

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Salut !

    On va supposer que le cache de second niveau est bien désactivé et que le problème reste le cache de 1er niveau.
    Tu peux essayer résoudre le problème en fermant l'entityManager lorsque tu as terminé avec un ensemble d'entités récupérés (en gros que ca te dérange pas que les entités récupérés soient détachées) .
    L'EM fermé, le cache de 1er niveau sera ainsi rincé.

  11. #11
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Alors j'ai bien testé avec un close et un clear pour l'entityManager et rien n'y fait !
    Il y a t'il un moyen de voir ou de forcer le cache de 2eme niveau a se vider ?

    code modifié :

    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
    static PersistenceService manager = PersistenceService.getInstance();
    	public static void main(String[] args){
     
    		SQLUtil connect = new SQLUtil("root", "");
    		if (connect.getResult())
    		{
    			manager.initialize(connect.getMap());
    		}
     
    		List<Baselineinfo> lBlis = (List<Baselineinfo>)manager.getResultListNamed("Baselineinfo.findAll");
     
    		for(Baselineinfo bli : lBlis)
    		{
    			manager.initialize(connect.getMap());
    			try
    			{
    				ddd(bli);
    				manager.clear();
    			}
    			catch (Exception e)
    			{
    				e.printStackTrace();
    			}
    			manager.close();
    		}
     
    	}
    la courbe mémoire reste la même (a peu de chose près) !

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Bah pour le second niveau, je sais comment faire avec Jpa-Hibernate (sessionFactory.getAllSecondLevelCacheRegions()) maintenant avec Jpa-Toplink, je connais pas. Il y a peut-être un équivalent.

    C'est quoi la classe PersistenceService ?
    Tu la considères comme ton entiyManager.
    C'est une classe à toi ou une classe toplink ?

  13. #13
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    C'est une classe à moi oui qui regroupe un ensemble de service JPA
    (création de transaction, EntityManager(close, clear, etc), commit, ....
    Mais ce n'est pas un EntityManager non.

  14. #14
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Ok.
    Le problème est peut être dedans alors.
    Que fait initialize()? Que fait clear() ? Que fait close() ?

    Si tu veux savoir si le prob est bien un prob de cache de second niveau, tu peux toujours comparer les temps d'accès au 1er et second appel d'une même requête chacun effectué dans leur propre transaction.

    Ouvre une transaction, fait un appel jpa qui récupère beaucoup d'entités,chronomètre le temps d'exécution de la requête, puis ferme la transaction (qui fermera l'em).
    Ouvre une nouvelle transaction, fait la même requête, chronomètre le temps d'exécution de la requête.
    Si t'as une différence sensible entre les deux temps, le cache de second niveau est surement toujours actif.

  15. #15
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Bien vu !
    1 er passage : 2096 milli secondes
    2eme : 282 milli

    donc effectivement le cache est bien activé ou un truc du genre !
    Le soucis, si tu regarde la partie de mon xml, c'est que je lui ai bien dit de ne pas s'activer !!

    Que faire ?

    Le clear fait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monEntityManager.clear();
    le close :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    monEntityManagerFactory.close;
    monEntityManagerFactory = null;
    monEntityManager.close;
    monEntityManager = null;

  16. #16
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Ca confirme la piste du second niveau.
    Je viens de voir ce que t'as mis dans le XML pour désactiver le cache:
    <property name="eclipselink.cache.shared.default" value="false"/>

    Sur le blog posté hier, j'ai pourtant lu ca :
    There is also "toplink.cache.shared.default" property for all entities like below.

    <property name="toplink.cache.shared.default" value="false"/>

    But this is not recommended[*]. Also it has a bug so it doesn’t work now.
    Essaye en précisant les entités pour lesquelles tu veux désactiver le cache
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <persistence ...>
      <persistence-unit name="HR">
      ...
        <properties>
        ...
          <property name="toplink.cache.shared.Employee" value="false"/>
          <property name="toplink.cache.shared.Department" value="false"/>
     
        </properties>
      </persistence-unit>
    </persistence>
    En outre, tu utilises la propriété du cache d' EclipseLink et non de TopLink.
    Pourquoi ?
    Tu utilises EclipseLink(produit qui dérive de TopLink) ou TopLink ?

  17. #17
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Oui, je viens de voir que je m'étais planté .... désolé j'utilise bien EclipseLink (pourquoi....je ne sais pas...ca m'a été imposé !).

    je vais donc essayé de faire entité par entité pour desactiver le shared cache et je te donne des news.

    Merci beaucoup pour ton aide

  18. #18
    Membre averti
    Inscrit en
    Octobre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 17
    Par défaut
    Mon persistence.xml modifié :

    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
     
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <shared-cache-mode>NONE</shared-cache-mode>
    <properties>
    	<property name="eclipselink.cache.shared.Baselineinfo" value="false"/>
    	<property name="eclipselink.cache.shared.Ca" value="false"/>
    	<property name="eclipselink.cache.shared.CaDui" value="false"/>
    	<property name="eclipselink.cache.shared.CaBaselineinfo"value="false"/>
    	<property name="eclipselink.cache.shared.CaCases" value="false"/>
    	<property name="eclipselink.cache.shared.CaDatafield" value="false"/>
    	<property name="eclipselink.cache.shared.CaMessage" value="false"/>
    	<property name="eclipselink.cache.shared.CaWhen" value="false"/>
    	<property name="eclipselink.cache.shared.CaWord" value="false"/>
    	<property name="eclipselink.cache.shared.CodingWhen" value="false"/>
    	<property name="eclipselink.cache.shared.Datafield" value="false"/>
    	<property name="eclipselink.cache.shared.Dfi" value="false"/>
    	<property name="eclipselink.cache.shared.Dui" value="false"/>
    	<property name="eclipselink.cache.shared.Enumerate" value="false"/>
    	<property name="eclipselink.cache.shared.Formula" value="false"/>
    	<property name="eclipselink.cache.shared.Formularange" value="false"/>
    	<property name="eclipselink.cache.shared.ImplEnumerate" value="false"/>
    	<property name="eclipselink.cache.shared.ImplField" value="false"/>
    	<property name="eclipselink.cache.shared.ImplMessage" value="false"/>
    	<property name="eclipselink.cache.shared.ImplPlatform" value="false"/>
    	<property name="eclipselink.cache.shared.ImplWord" value="false"/>
    	<property name="eclipselink.cache.shared.Message" value="false"/>
    	<property name="eclipselink.cache.shared.Parameter" value="false"/>
    	<property name="eclipselink.cache.shared.Platform" value="false"/>
    	<property name="eclipselink.cache.shared.Word" value="false"/>
    	<property name="eclipselink.query-results-cache"value="false"/>
    et malheureusement, toujours la meme différence de temps entre le parcour de deux meme entité et la mémoire grimpe toujours autant !
    Ca ne doit pas marché du tout ce truc la lol !

    je vais pleurer un ptit coup et je reviens lol

  19. #19
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Merci beaucoup pour ton aide
    Pas de souci

    Ca ne doit pas marché du tout ce truc la lol !

    Ou c'est peut-être meme pas reconnu par EclipseLink.
    Si tu mets qqch qu'il ne reconnait pas ds le persistence.xml, t'es pas insulté au moins avec des logs warn ou info ?

    je vais pleurer un ptit coup et je reviens lol
    , au point ou on en est, pourquoi pas mettre le niveau de log à debug pour tout ce qui concerne JPA et EclipseLink. Tu auras peut-être des infos intéressantes sur la configuration effective du cache et aussi sur ce qui se passe lors des deux appels à la même requête.

    Sinon, y a encore l'exécution en mode debug avec la joie de découvrir l'implémentation d'EclipseLink
    Courage

  20. #20
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 966
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 966
    Par défaut
    JPA n'est pas fait pour ce genre d'utilisation : ce n'est pas pour rien que des solutions comme SpringBatch ont été développées…

    ce que vous rencontrez est tout simplement le fait que vous chargez petit à petit l'ensemble de votre DB en mémoire et toutes les entités étant interconnectées, il n'y a pas vraiment moyen pour le GC de savoir quoi libérer… d'autant plus qu'en n'utilisant pas les transactions, vous vous privez d'un moyen simple d'indiquer ce qui peut être libéré…

    néanmoins si vous désirez malgré tout utiliser JPA, voici une architecture simple qui fonctionne à défaut d'être la plus performante possible :

    vous définissez une classe "ExportService" qui gérera 2 "helpers" :
    un qui aura le rôle de "DataSource" et l'autre qui sera le "DataWriter" (définissez les interfaces appropriées… )

    l'exportation (au sens large) sera alors la séquence suivante :

    l'appelant crée l'ExportService et l'initialise avec le DataSource et le DataWriter appropriés

    l'appelant demande à l'ExportService de notifier le DataWriter qu'il est sur le point de commencer (prélude)
    la méthode de l'ExportService qui appelle le "prelude" du DataWriter est transactionnelle
    (pour l'export en XML c'est le bon endroit pour écrire l'entête, le tag global,…)

    ensuite l'appelant boucle sur l'exportation proprement dite en appelant une méthode (transactionelle) de l'ExportService "doExportData" qui renverra son statut "fini" ou "non", par exemple :

    while (exportService.doExportData()) ;

    doExportData :
    demande à la DataSource les données à exporter par CHUNCK (évidemment, sinon çà n'apporte rien…)
    et les donnent au DataWriter
    renvoit true/false en fonction du fait qu'il y ait encore des données à traiter ou non

    à la fin, l'appelant demande à l'ExportService de notifier le DataWriter que c'est terminé (postlude) de nouveau dans une méthode transactionnelle… (bon endroit pour fermer le tag global, fermer le fichier, …)

    seules les méthodes de l'ExportService sont transactionnelles (d'où son appellation de "Service"…)
    et si vous devez remonter des erreurs faites le par des exceptions catchées par l'appelant qui contrôle l'ExportService…

    si vous devez garantir qu'il n'y ait pas de modifications de la DB pendant l'export, il faudra définir un niveau transactionnel supérieur (sur celui qui appelle l'ExportService…) et bien étudier le modèle de propagation à utiliser…

    (il est évidemment assez simple de définir le service symétrique pour les importations… mais dans les 2 cas, seul un des DataSource/DataWriter peut être transactionnel… pour faire un "DataMovingService" avec les 2 extrémités transactionnelles il faut revoir un peu l'emplacement des frontières de transactions… et de toute façon si les 2 extrémités sont 2 DBs différentes vous ne pourrez plus utiliser @Transactionnal…)

Discussions similaires

  1. Problème d'insertion en JPA (TOPLINK)
    Par tchernogod dans le forum Persistance des données
    Réponses: 0
    Dernier message: 26/04/2011, 13h09
  2. [CR9] [VB.NET] problème mémoire
    Par prophetky dans le forum SDK
    Réponses: 1
    Dernier message: 26/05/2005, 09h36
  3. Problème mémoire
    Par charliejo dans le forum MFC
    Réponses: 8
    Dernier message: 13/04/2005, 14h45
  4. Problémes mémoire avec le bde sur des bases paradox
    Par Keke des Iles dans le forum Bases de données
    Réponses: 2
    Dernier message: 27/05/2004, 17h55
  5. Problème mémoire avec une dll par chargement dynamique
    Par widze19 dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/12/2003, 14h20

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